1 /* 2 * Copyright (c) 2002, Intel Corporation. All rights reserved. 3 * This file is licensed under the GPL license. For the full content 4 * of this license, see the COPYING file at the top level of this 5 * source tree. 6 7 * If there are threads blocked on the lock when it becomes available, 8 * the scheduling policy shall determine which thread(s) shall acquire the lock. 9 * If the Thread Execution Scheduling option is supported, when threads executing 10 * with the scheduling policies SCHED_FIFO, SCHED_RR, or SCHED_SPORADIC are waiting 11 * on the lock, they shall acquire the lock in priority order when the lock 12 * becomes available. For equal priority threads, write locks shall take precedence 13 * over read locks. 14 * 15 Steps: 16 * We have four threads, main(also a reader), writer1, reader, writer2 17 * main has the highest priority, writer1 and reader has same priority, writer2 has lowest 18 * priority. 19 * 20 * 1. Main thread set its shcedule policy as "SCHED_FIFO", with highest priority 21 * the three: sched_get_priority_min()+3. 22 * 2. Main thread write lock 'rwlock' 23 * 3. Create a writer1 thread, with schedule policy as "SCHED_FIFO", and priority 24 * using sched_get_priority_min()+2. The writer should block. 25 * 4. Create reader thread, with same priority as writer1. The reader should also block. 26 * 5. Create a writer2 thread, with priority sched_get_priority_min(). It should block 27 * on write lock too. 28 * 7. Main thread release the 'rwlock', make sure the threads got the lock in the order 29 * writer1, reader, writer2. 30 * 31 */ 32 33 /* NOTE: The test result is UNSUPPORTED if Thread Execution Scheduling option 34 * is not supported. 35 */ 36 37 #include <pthread.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <unistd.h> 41 #include <string.h> 42 #include <sched.h> 43 #include "posixtest.h" 44 45 #define TRD_POLICY SCHED_FIFO 46 47 static pthread_rwlock_t rwlock; 48 static int rd_thread_state; 49 static int wr_thread_state_1, wr_thread_state_2; 50 51 /* thread_state: 52 1: not in child thread yet; 53 2: just enter child thread ; 54 3: after locking 55 4: thread is exiting 56 */ 57 58 #define NOT_CREATED_THREAD 1 59 #define ENTERED_THREAD 2 60 #define PASSED_LOCK 3 61 #define EXITING_THREAD 4 62 63 static int set_priority(pthread_t pid, unsigned policy, unsigned prio) 64 { 65 struct sched_param sched_param; 66 memset(&sched_param, 0, sizeof(sched_param)); 67 sched_param.sched_priority = prio; 68 if (pthread_setschedparam(pid, policy, &sched_param) == -1) { 69 printf("Can't set policy to %d and prio to %d\n", policy, prio); 70 exit(PTS_UNRESOLVED); 71 } 72 return 0; 73 } 74 75 static void *fn_rd(void *arg) 76 { 77 int rc = 0; 78 int priority; 79 rd_thread_state = ENTERED_THREAD; 80 81 priority = (long)arg; 82 set_priority(pthread_self(), TRD_POLICY, priority); 83 84 printf("reader: attempt read lock\n"); 85 rc = pthread_rwlock_rdlock(&rwlock); 86 if (rc != 0) { 87 printf 88 ("Error: rd_thread failed to get read lock, Error code:%d\n", 89 rc); 90 exit(PTS_UNRESOLVED); 91 } 92 93 rd_thread_state = PASSED_LOCK; 94 printf("reader: acquired read lock\n"); 95 96 /* Wait for main to wake us up */ 97 do { 98 sleep(1); 99 } while (rd_thread_state != EXITING_THREAD); 100 101 printf("reader: unlock read lock\n"); 102 if (pthread_rwlock_unlock(&rwlock) != 0) { 103 printf("rd_thread: Error at pthread_rwlock_unlock()\n"); 104 exit(PTS_UNRESOLVED); 105 } 106 pthread_exit(0); 107 return NULL; 108 } 109 110 static void *fn_wr_1(void *arg) 111 { 112 int rc = 0; 113 int priority; 114 wr_thread_state_1 = ENTERED_THREAD; 115 116 priority = (int)(long)arg; 117 set_priority(pthread_self(), TRD_POLICY, priority); 118 119 printf("writer1: attempt write lock\n"); 120 rc = pthread_rwlock_wrlock(&rwlock); 121 if (rc != 0) { 122 printf 123 ("Error: wr_thread failed to get write lock, Error code:%d\n", 124 rc); 125 exit(PTS_UNRESOLVED); 126 } 127 128 wr_thread_state_1 = PASSED_LOCK; 129 printf("writer1: acquired write lock\n"); 130 131 /* Wait for main to wake us up */ 132 133 do { 134 sleep(1); 135 } while (wr_thread_state_1 != EXITING_THREAD); 136 137 printf("writer1: unlock write lock\n"); 138 if (pthread_rwlock_unlock(&rwlock) != 0) { 139 printf("wr_thread: Error at pthread_rwlock_unlock()\n"); 140 exit(PTS_UNRESOLVED); 141 } 142 143 pthread_exit(0); 144 return NULL; 145 } 146 147 static void *fn_wr_2(void *arg) 148 { 149 int rc = 0; 150 int priority; 151 wr_thread_state_2 = ENTERED_THREAD; 152 153 priority = (long)arg; 154 set_priority(pthread_self(), TRD_POLICY, priority); 155 156 printf("writer2: attempt write lock\n"); 157 rc = pthread_rwlock_wrlock(&rwlock); 158 if (rc != 0) { 159 printf 160 ("Error: wr_thread failed to get write lock, Error code:%d\n", 161 rc); 162 exit(PTS_UNRESOLVED); 163 } 164 165 wr_thread_state_2 = PASSED_LOCK; 166 printf("writer2: acquired writer lock\n"); 167 168 /* Wait for main to wake us up */ 169 do { 170 sleep(1); 171 } while (wr_thread_state_2 != EXITING_THREAD); 172 173 printf("writer2: unlock writer lock\n"); 174 if (pthread_rwlock_unlock(&rwlock) != 0) { 175 printf("wr_thread: Error at pthread_rwlock_unlock()\n"); 176 exit(PTS_UNRESOLVED); 177 } 178 179 pthread_exit(0); 180 return NULL; 181 } 182 183 int main(void) 184 { 185 #ifndef _POSIX_THREAD_PRIORITY_SCHEDULING 186 printf("Posix Thread Execution Scheduling not supported\n"); 187 return PTS_UNSUPPORTED; 188 #endif 189 190 int cnt = 0; 191 pthread_t writer1, reader, writer2; 192 int priority; 193 194 /* main thread needs to have the highest priority */ 195 priority = sched_get_priority_min(TRD_POLICY) + 3; 196 set_priority(pthread_self(), TRD_POLICY, priority); 197 198 if (pthread_rwlock_init(&rwlock, NULL) != 0) { 199 printf("main: Error at pthread_rwlock_init()\n"); 200 return PTS_UNRESOLVED; 201 } 202 203 printf("main: write lock\n"); 204 /* We have no lock, this read lock should succeed */ 205 if (pthread_rwlock_wrlock(&rwlock) != 0) { 206 printf 207 ("Error: main cannot get write lock when no one owns the lock\n"); 208 return PTS_UNRESOLVED; 209 } 210 211 /* Now create 3 threads that block on this rwlock */ 212 213 wr_thread_state_1 = NOT_CREATED_THREAD; 214 priority = sched_get_priority_min(TRD_POLICY) + 2; 215 printf("main: create writer1, with priority: %d\n", priority); 216 if (pthread_create(&writer1, NULL, fn_wr_1, (void *)(long)priority) != 217 0) { 218 printf("main: Error creating writer1\n"); 219 return PTS_UNRESOLVED; 220 } 221 222 /* If the shared data is not altered by child after 2 seconds, 223 we regard it as blocked */ 224 225 /* We expect the writer1 to block */ 226 cnt = 0; 227 do { 228 sleep(1); 229 } while (wr_thread_state_1 != 3 && cnt++ < 3); 230 231 if (wr_thread_state_1 == 3) { 232 printf 233 ("writer1 did not block on write lock, when main owns the lock\n"); 234 exit(PTS_UNRESOLVED); 235 } else if (wr_thread_state_1 != 2) { 236 printf("Unexpected writer1 state\n"); 237 exit(PTS_UNRESOLVED); 238 } 239 240 /* Reader thread same priority as Writer1 thread */ 241 242 rd_thread_state = 1; 243 priority = sched_get_priority_min(TRD_POLICY) + 2; 244 printf("main: create reader, with priority: %d\n", priority); 245 if (pthread_create(&reader, NULL, fn_rd, (void *)(long)priority) != 0) { 246 printf("main: failed at creating reader\n"); 247 return PTS_UNRESOLVED; 248 } 249 250 /* We expect the reader to block */ 251 cnt = 0; 252 do { 253 sleep(1); 254 } while (rd_thread_state != 3 && cnt++ < 2); 255 256 if (rd_thread_state == 3) { 257 printf("Test Fail: reader did not block on read lock\n"); 258 exit(PTS_FAIL); 259 } else if (rd_thread_state != 2) { 260 printf("Unexpected reader state\n"); 261 exit(PTS_UNRESOLVED); 262 } 263 264 /* Writer2 is the lowest priority thread */ 265 266 wr_thread_state_2 = 1; 267 priority = sched_get_priority_min(TRD_POLICY); 268 printf("main: create writer2, with priority: %d\n", priority); 269 if (pthread_create(&writer2, NULL, fn_wr_2, (void *)(long)priority) != 270 0) { 271 printf("main: Error creating writer2\n"); 272 return PTS_UNRESOLVED; 273 } 274 275 /* If the shared data is not altered by child after 3 seconds, 276 we regard it as blocked */ 277 278 /* We expect the writer2 to block */ 279 cnt = 0; 280 do { 281 sleep(1); 282 } while (wr_thread_state_2 != 3 && cnt++ < 2); 283 284 if (wr_thread_state_2 == 3) { 285 printf 286 ("writer2 did not block on write lock, when main owns the lock\n"); 287 exit(PTS_UNRESOLVED); 288 } else if (wr_thread_state_2 != 2) { 289 printf("Unexpected writer1 state\n"); 290 exit(PTS_UNRESOLVED); 291 } 292 293 printf("main: release write lock\n"); 294 if (pthread_rwlock_unlock(&rwlock) != 0) { 295 printf("main: failed to release write lock\n"); 296 exit(PTS_UNRESOLVED); 297 } 298 299 /* we expect writer1 get the lock */ 300 cnt = 0; 301 do { 302 sleep(1); 303 } while (wr_thread_state_1 != 3 && cnt++ < 3); 304 305 if (wr_thread_state_1 == 2) { 306 printf 307 ("Test fail: writer did not get write lock, when main release the lock\n"); 308 exit(PTS_FAIL); 309 } else if (wr_thread_state_1 != 3) { 310 printf("Unexpected writer1 state\n"); 311 exit(PTS_UNRESOLVED); 312 } 313 314 /* Let writer1 release the lock */ 315 wr_thread_state_1 = 4; 316 317 if (pthread_join(writer1, NULL) != 0) { 318 printf("main: Error joining writer1\n"); 319 exit(PTS_UNRESOLVED); 320 } 321 322 /* we expect the reader get the lock when writer1 has release the lock */ 323 cnt = 0; 324 do { 325 sleep(1); 326 } while (rd_thread_state != 3 && cnt++ < 3); 327 328 if (rd_thread_state == 2) { 329 printf 330 ("Test failed: reader did not get the lock when writer1 release the lock\n"); 331 exit(PTS_FAIL); 332 } else if (rd_thread_state != 3) { 333 printf("Unexpected reader state\n"); 334 exit(PTS_UNRESOLVED); 335 } 336 337 /* Inform reader release the lock */ 338 rd_thread_state = 4; 339 340 if (pthread_join(reader, NULL) != 0) { 341 printf("main: Error joining reader\n"); 342 exit(PTS_UNRESOLVED); 343 } 344 345 /* we expect writer2 get the lock */ 346 cnt = 0; 347 do { 348 sleep(1); 349 } while (wr_thread_state_2 != 3 && cnt++ < 3); 350 351 if (wr_thread_state_2 == 2) { 352 printf 353 ("Test fail: writer2 still blocked on write lock, when main release the lock\n"); 354 exit(PTS_FAIL); 355 } else if (wr_thread_state_2 != 3) { 356 printf("Unexpected writer2 state\n"); 357 exit(PTS_UNRESOLVED); 358 } 359 360 wr_thread_state_2 = 4; 361 362 if (pthread_join(writer2, NULL) != 0) { 363 printf("main: Error joining writer1\n"); 364 exit(PTS_UNRESOLVED); 365 } 366 367 if (pthread_rwlock_destroy(&rwlock) != 0) { 368 printf("Error at pthread_rwlockattr_destroy()"); 369 return PTS_UNRESOLVED; 370 } 371 372 printf("Test PASSED\n"); 373 return PTS_PASS; 374 } 375