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