2-3.c revision 354ebb48db8e66a853a58379a4808d5dcd1ceac3
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 * Test that pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) 8 * 9 * If the Thread Execution Scheduling option is supported, 10 * and the threads involved in the lock are executing with the 11 * scheduling policies SCHED_FIFO or SCHED_RR, the calling thread shall not 12 * acquire the lock if a writer holds the lock or if writers of 13 * higher or equal priority are blocked on the lock; 14 * otherwise, the calling thread shall acquire the lock. 15 * 16 * In this case, reader has higher priority than the writer 17 * 18 Steps: 19 * We have three threads, main(also a reader), writer, reader 20 * 21 * 1. Main thread set its shcedule policy as "SCHED_FIFO", with highest priority 22 * the three: sched_get_priority_min()+2. 23 * 2. Main thread read lock 'rwlock' 24 * 3. Create a writer thread, with schedule policy as "SCHED_FIFO", and priority 25 * using sched_get_priority_min(). 26 * 4. The thread write lock 'rwlock', should block. 27 * 5. Main thread create a reader thread, with schedule policy as "SCHED_FIFO", and 28 * priority sched_get_priority_min()+1 29 * 6. Reader thread read lock 'rwlock', shouldn't block, since it has a higher priority 30 * than the writer blocked on 'rwlock' 31 * 7. Main thread release the 'rwlock', the writer should get the lock first. 32 */ 33 34/* NOTE: The test result is UNSUPPORTED if Thread Execution Scheduling option 35 * is not supported. 36 */ 37 38#define _XOPEN_SOURCE 600 39#include <pthread.h> 40#include <stdio.h> 41#include <stdlib.h> 42#include <unistd.h> 43#include <string.h> 44#include <sched.h> 45#include "posixtest.h" 46 47#define TRD_POLICY SCHED_FIFO 48 49static pthread_rwlock_t rwlock; 50static int rd_thread_state; 51static int wr_thread_state; 52 53/* thread states: 54 1: not in thread yet; 55 2: just entered thread ; 56 3: just before thread exits; 57*/ 58 59#define NOT_CREATED_THREAD 1 60#define ENTERED_THREAD 2 61#define EXITING_THREAD 3 62 63static 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 75static void *fn_rd(void *arg) 76{ 77 int rc = 0; 78 int priority; 79 rd_thread_state = ENTERED_THREAD; 80 81 priority = (int)(long)arg; 82 set_priority(pthread_self(), TRD_POLICY, priority); 83 84 printf("rd_thread: attempt read lock\n"); 85 rc = pthread_rwlock_rdlock(&rwlock); 86 if (rc != 0) { 87 printf 88 ("Test FAILED: rd_thread failed to get read lock, Error code:%d\n", 89 rc); 90 exit(PTS_FAIL); 91 } else 92 printf("rd_thread: acquired read lock\n"); 93 94 sleep(1); 95 96 printf("rd_thread: unlock read lock\n"); 97 if (pthread_rwlock_unlock(&rwlock) != 0) { 98 printf("rd_thread: Error at pthread_rwlock_unlock()\n"); 99 exit(PTS_UNRESOLVED); 100 } 101 rd_thread_state = EXITING_THREAD; 102 pthread_exit(0); 103 return NULL; 104} 105 106static void *fn_wr(void *arg) 107{ 108 int rc = 0; 109 int priority; 110 wr_thread_state = ENTERED_THREAD; 111 112 priority = (long)arg; 113 set_priority(pthread_self(), TRD_POLICY, priority); 114 115 printf("wr_thread: attempt write lock\n"); 116 rc = pthread_rwlock_wrlock(&rwlock); 117 if (rc != 0) { 118 printf 119 ("Test FAILED: wr_thread failed to get write lock, Error code:%d\n", 120 rc); 121 exit(PTS_UNRESOLVED); 122 } else 123 printf("wr_thread: acquired write lock\n"); 124 125 sleep(1); 126 127 printf("wr_thread: unlock write lock\n"); 128 if (pthread_rwlock_unlock(&rwlock) != 0) { 129 printf("wr_thread: Error at pthread_rwlock_unlock()\n"); 130 exit(PTS_UNRESOLVED); 131 } 132 wr_thread_state = EXITING_THREAD; 133 pthread_exit(0); 134 return NULL; 135} 136 137int main() 138{ 139 140#ifndef _POSIX_THREAD_PRIORITY_SCHEDULING 141 printf("Posix Thread Execution Scheduling not supported\n"); 142 return PTS_UNSUPPORTED; 143#endif 144 145 int cnt = 0; 146 pthread_t rd_thread, wr_thread; 147 int priority; 148 149 /* main thread needs to have the highest priority */ 150 priority = sched_get_priority_min(TRD_POLICY) + 2; 151 set_priority(pthread_self(), TRD_POLICY, priority); 152 153 if (pthread_rwlock_init(&rwlock, NULL) != 0) { 154 printf("main: Error at pthread_rwlock_init()\n"); 155 return PTS_UNRESOLVED; 156 } 157 158 printf("main: attempt read lock\n"); 159 /* We have no lock, this read lock should succeed */ 160 if (pthread_rwlock_rdlock(&rwlock) != 0) { 161 printf 162 ("Test FAILED: main cannot get read lock when no one owns the lock\n"); 163 return PTS_FAIL; 164 } else 165 printf("main: acquired read lock\n"); 166 167 wr_thread_state = NOT_CREATED_THREAD; 168 priority = sched_get_priority_min(TRD_POLICY); 169 printf("main: create wr_thread, with priority: %d\n", priority); 170 if (pthread_create(&wr_thread, NULL, fn_wr, (void *)(long)priority) != 171 0) { 172 printf("main: Error at 1st pthread_create()\n"); 173 return PTS_UNRESOLVED; 174 } 175 176 /* If the shared data is not altered by child after 3 seconds, 177 we regard it as blocked */ 178 179 /* We expect the wr_thread to block */ 180 cnt = 0; 181 do { 182 sleep(1); 183 } while (wr_thread_state != EXITING_THREAD && cnt++ < 3); 184 185 if (wr_thread_state == EXITING_THREAD) { 186 printf 187 ("wr_thread did not block on write lock, when a reader owns the lock\n"); 188 exit(PTS_UNRESOLVED); 189 } else if (wr_thread_state != ENTERED_THREAD) { 190 printf("Unexpected wr_thread state\n"); 191 exit(PTS_UNRESOLVED); 192 } 193 194 rd_thread_state = NOT_CREATED_THREAD; 195 priority = sched_get_priority_min(TRD_POLICY) + 1; 196 printf("main: create rd_thread, with priority: %d\n", priority); 197 if (pthread_create(&rd_thread, NULL, fn_rd, (void *)(long)priority) != 198 0) { 199 printf("main: failed at creating rd_thread\n"); 200 return PTS_UNRESOLVED; 201 } 202 203 /* We expect the rd_thread get the read lock */ 204 cnt = 0; 205 do { 206 sleep(1); 207 } while (rd_thread_state != EXITING_THREAD && cnt++ < 3); 208 209 if (rd_thread_state == ENTERED_THREAD) { 210 printf("Test FAILED: rd_thread blocked on read lock\n"); 211 exit(PTS_FAIL); 212 } else if (rd_thread_state != EXITING_THREAD) { 213 printf("Unexpected rd_thread state\n"); 214 exit(PTS_UNRESOLVED); 215 } 216 217 printf("main: unlock read lock\n"); 218 if (pthread_rwlock_unlock(&rwlock) != 0) { 219 printf("main: failed to release read lock\n"); 220 exit(PTS_UNRESOLVED); 221 } 222 223 /* we expect the writer get the lock */ 224 cnt = 0; 225 do { 226 sleep(1); 227 } while (wr_thread_state != EXITING_THREAD && cnt++ < 3); 228 229 if (wr_thread_state == ENTERED_THREAD) { 230 printf 231 ("Test FAILED: higher priority wr_thread still blocked on write lock, when a reader release the lock\n"); 232 exit(PTS_FAIL); 233 } else if (wr_thread_state != EXITING_THREAD) { 234 printf("Unexpected wr_thread state\n"); 235 exit(PTS_UNRESOLVED); 236 } 237 238 if (pthread_join(wr_thread, NULL) != 0) { 239 printf("main: Error at 1st pthread_join()\n"); 240 exit(PTS_UNRESOLVED); 241 } 242 243 if (pthread_join(rd_thread, NULL) != 0) { 244 printf("main: Error at 2nd pthread_join()\n"); 245 exit(PTS_UNRESOLVED); 246 } 247 248 if (pthread_rwlock_destroy(&rwlock) != 0) { 249 printf("Error at pthread_rwlockattr_destroy()"); 250 return PTS_UNRESOLVED; 251 } 252 253 printf("Test PASSED\n"); 254 return PTS_PASS; 255} 256