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_timedrdlock(pthread_rwlock_t *rwlock) 8 * 9 * Under no circumstances shall the function fail with a timeout if the lock can be 10 * acquired immediately. The abs_timeout parameter need not be checked if the lock 11 * can be immediately acquired. 12 * 13 * Steps:n 14 * 1. Main thread create a thread. 15 * 2. Child thread lock 'rwlock' for reading with pthread_rwlock_timedrdlock(), 16 * should not fail with timeout 17 * 3. The child thread unlocks the 'rwlock' and exits. 18 * 4. Main thread create another thread. 19 * 4. The child thread lock 'rwlock' for reading, with pthread_rwlock_timedrdlock(), 20 * specifying a 'abs_timeout'. The thread sleeps until 'abs_timeout' expires. 21 * 5. The thread call pthread_rwlock_timedrdlock(). Should _NOT_ get ETIMEDOUT. 22 */ 23 24#define _XOPEN_SOURCE 600 25#include <pthread.h> 26#include <stdio.h> 27#include <stdlib.h> 28#include <unistd.h> 29#include <errno.h> 30#include "posixtest.h" 31 32#define NOT_CREATED_THREAD 1 33#define ENTERED_THREAD 2 34#define EXITING_THREAD 3 35 36#define TIMEOUT 1 37static int thread_state; 38static int currsec1; 39static int expired; 40 41static void* fn_rd_1(void *arg) 42{ 43 thread_state = ENTERED_THREAD; 44 struct timespec abs_timeout; 45 int rc; 46 pthread_rwlock_t rwlock; 47 48 if(pthread_rwlock_init(&rwlock, NULL) != 0) 49 { 50 printf("thread1: Error at pthread_rwlock_init\n"); 51 exit(PTS_UNRESOLVED); 52 } 53 54 currsec1 = time(NULL); 55 56 /* Absolute time, not relative. */ 57 abs_timeout.tv_sec = currsec1 + TIMEOUT; 58 abs_timeout.tv_nsec = 0; 59 60 printf("thread1: attempt timed read-lock\n"); 61 rc = pthread_rwlock_timedrdlock(&rwlock, &abs_timeout); 62 if(rc == ETIMEDOUT) 63 { 64 printf("thread1: timed read-lock expired\n"); 65 expired = 1; 66 } 67 else if(rc == 0) 68 { 69 printf("thread1: acquired read lock\n"); 70 expired = 0; 71 printf("thread1: unlock read lock\n"); 72 if(pthread_rwlock_unlock(&rwlock) != 0) 73 { 74 printf("thread1: failed to release read lock\n"); 75 exit(PTS_UNRESOLVED); 76 } 77 } 78 else 79 { 80 printf("thread1: Error in pthread_rwlock_timedrdlock().\n"); 81 exit(PTS_UNRESOLVED); 82 } 83 84 if(pthread_rwlock_destroy(&rwlock) != 0) 85 { 86 printf("thread1: Error at pthread_rwlockattr_destroy()"); 87 exit(PTS_UNRESOLVED); 88 } 89 thread_state = EXITING_THREAD; 90 pthread_exit(0); 91 return NULL; 92} 93 94static void* fn_rd_2(void *arg) 95{ 96 thread_state = ENTERED_THREAD; 97 struct timespec abs_timeout; 98 int rc; 99 pthread_rwlock_t rwlock; 100 101 if(pthread_rwlock_init(&rwlock, NULL) != 0) 102 { 103 printf("thread2: Error at pthread_rwlock_init\n"); 104 exit(PTS_UNRESOLVED); 105 } 106 currsec1 = time(NULL); 107 108 /* Ensure that the abs_timeout has passed by _subtracting_ the timeout value of 1 109 * from the current time. */ 110 abs_timeout.tv_sec = currsec1 - TIMEOUT; 111 abs_timeout.tv_nsec = 0; 112 113 printf("thread2: attempt timed read-lock\n"); 114 rc = pthread_rwlock_timedrdlock(&rwlock, &abs_timeout); 115 if(rc == ETIMEDOUT) 116 { 117 printf("thread2: timed read-lock expired\n"); 118 expired = 1; 119 } 120 else if(rc == 0) 121 { 122 printf("thread2: acquired read lock\n"); 123 expired = 0; 124 printf("thread2: unlock read lock\n"); 125 if(pthread_rwlock_unlock(&rwlock) != 0) 126 { 127 printf("thread2: failed to release read lock\n"); 128 exit(PTS_UNRESOLVED); 129 } 130 } 131 else 132 { 133 printf("thread2: Error in pthread_rwlock_timedrdlock().\n"); 134 exit(PTS_UNRESOLVED); 135 } 136 137 if(pthread_rwlock_destroy(&rwlock) != 0) 138 { 139 printf("thread2: Error at pthread_rwlockattr_destroy()\n"); 140 exit(PTS_UNRESOLVED); 141 } 142 thread_state = EXITING_THREAD; 143 pthread_exit(0); 144 return NULL; 145} 146 147int main() 148{ 149 int cnt = 0; 150 151 pthread_t thread1, thread2; 152 153 thread_state = NOT_CREATED_THREAD; 154 printf("main: create thread1\n"); 155 if(pthread_create(&thread1, NULL, fn_rd_1, NULL) != 0) 156 { 157 printf("Error when creating thread1\n"); 158 return PTS_UNRESOLVED; 159 } 160 161 /* If the shared data is not altered by child after 5 seconds, 162 we regard it as blocked */ 163 164 /* we expect thread1 NOT to block, but rather for the timed read-lock to expire */ 165 cnt = 0; 166 do{ 167 sleep(1); 168 }while (thread_state !=EXITING_THREAD && cnt++ < 5); 169 170 if(thread_state == EXITING_THREAD) 171 { 172 /* the child thread does not block, check the time expired or not */ 173 if(expired == 1) 174 { 175 printf("Test FAILED: thread1 incorrectly received ETIMEDOUT\n"); 176 return PTS_FAIL; 177 } 178 } 179 else if(thread_state == ENTERED_THREAD) 180 { 181 printf("Test FAILED: thread1 incorrectly blocked for reading rwlock\n"); 182 return PTS_FAIL; 183 } 184 else 185 { 186 printf("Unexpected state for thread1 %d\n", thread_state); 187 return PTS_UNRESOLVED; 188 } 189 190 if(pthread_join(thread1, NULL) != 0) 191 { 192 printf("Error when joining thread1\n"); 193 return PTS_UNRESOLVED; 194 } 195 196 printf("main: create thread2\n"); 197 thread_state = NOT_CREATED_THREAD; 198 if(pthread_create(&thread2, NULL, fn_rd_2, NULL) != 0) 199 { 200 printf("Error when creating thread2\n"); 201 return PTS_UNRESOLVED; 202 } 203 204 /* If the shared data is not altered by child after 5 seconds, 205 we regard it as blocked */ 206 207 /* we expect thread2 NOT to block */ 208 cnt = 0; 209 do{ 210 sleep(1); 211 }while (thread_state !=EXITING_THREAD && cnt++ < 5); 212 213 if(thread_state == EXITING_THREAD) 214 { 215 /* the child thread does not block, check the time expired or not */ 216 if(expired == 1) 217 { 218 printf("Test FAILED: thread2 incorrectly received ETIMEDOUT\n"); 219 return PTS_FAIL; 220 } 221 } 222 else if(thread_state == ENTERED_THREAD) 223 { 224 printf("Test FAILED: thread2 incorrectly blocked for reading rwlock\n"); 225 return PTS_FAIL; 226 } 227 else 228 { 229 printf("Unexpected state for thread2 %d\n", thread_state); 230 return PTS_UNRESOLVED; 231 } 232 233 if(pthread_join(thread2, NULL) != 0) 234 { 235 printf("Error when join thread2\n"); 236 return PTS_UNRESOLVED; 237 } 238 239 printf("Test PASSED\n"); 240 return PTS_PASS; 241} 242