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_timedwrlock(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: 14 * 1. Main thread create a thread. 15 * 2. Child thread lock 'rwlock' for writing with pthread_rwlock_timedwrlock(), 16 * should not fail with timeout 17 * 3. The child thread unlocks the 'rwlock' and exit. 18 * 4. Main thread create another thread. 19 * 5. The child thread lock 'rwlock' for write, with pthread_rwlock_timedwrlock(), 20 * specifying a 'abs_timeout'. The thread sleeps untile 'abs_timeout' expires. 21 * 6. The thread call pthread_rwlock_timedwrlock(). 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 TIMEOUT 1 33 34 static int thread_state; 35 static int currsec1; 36 static int expired; 37 38 /* thread_state indicates child thread state: 39 1: not in child thread yet; 40 2: just enter child thread ; 41 3: just before child thread exit; 42 */ 43 44 #define NOT_CREATED_THREAD 1 45 #define ENTERED_THREAD 2 46 #define EXITING_THREAD 3 47 48 static void *fn_wr_1(void *arg) 49 { 50 thread_state = ENTERED_THREAD; 51 struct timespec abs_timeout; 52 int rc; 53 pthread_rwlock_t rwlock; 54 55 if (pthread_rwlock_init(&rwlock, NULL) != 0) { 56 printf("thread1: Error at pthread_rwlock_init\n"); 57 exit(PTS_UNRESOLVED); 58 } 59 60 currsec1 = time(NULL); 61 62 /* Absolute time, not relative. */ 63 abs_timeout.tv_sec = currsec1 + TIMEOUT; 64 abs_timeout.tv_nsec = 0; 65 66 printf("thread1: attempt timed lock for writing\n"); 67 rc = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout); 68 if (rc == ETIMEDOUT) { 69 printf("thread1: timer expired\n"); 70 expired = 1; 71 } else if (rc == 0) { 72 printf("thread1: acquired write lock\n"); 73 expired = 0; 74 printf("thread1: unlock write lock\n"); 75 if (pthread_rwlock_unlock(&rwlock) != 0) { 76 printf("thread1: failed to release write lock\n"); 77 exit(PTS_UNRESOLVED); 78 } 79 } else { 80 printf("thread1: Error in pthread_rwlock_timedwrlock().\n"); 81 exit(PTS_UNRESOLVED); 82 } 83 84 if (pthread_rwlock_destroy(&rwlock) != 0) { 85 printf("thread1: Error at pthread_rwlockattr_destroy()"); 86 exit(PTS_UNRESOLVED); 87 } 88 thread_state = EXITING_THREAD; 89 pthread_exit(0); 90 return NULL; 91 } 92 93 static void *fn_wr_2(void *arg) 94 { 95 thread_state = ENTERED_THREAD; 96 struct timespec abs_timeout; 97 int rc; 98 pthread_rwlock_t rwlock; 99 100 if (pthread_rwlock_init(&rwlock, NULL) != 0) { 101 printf("thread2: Error at pthread_rwlock_init\n"); 102 exit(PTS_UNRESOLVED); 103 } 104 currsec1 = time(NULL); 105 106 /* Absolute time, not relative. */ 107 abs_timeout.tv_sec = currsec1 - TIMEOUT; 108 abs_timeout.tv_nsec = 0; 109 110 printf("thread2: attempt timed lock for writing\n"); 111 rc = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout); 112 if (rc == ETIMEDOUT) { 113 printf("thread2: timer expired\n"); 114 expired = 1; 115 } else if (rc == 0) { 116 printf("thread2: acquired write lock\n"); 117 expired = 0; 118 printf("thread2: unlock write lock\n"); 119 if (pthread_rwlock_unlock(&rwlock) != 0) { 120 printf("thread2: failed to release write lock\n"); 121 exit(PTS_UNRESOLVED); 122 } 123 } else { 124 printf("thread2: Error in pthread_rwlock_timedwrlock().\n"); 125 exit(PTS_UNRESOLVED); 126 } 127 128 if (pthread_rwlock_destroy(&rwlock) != 0) { 129 printf("thread2: Error at pthread_rwlock_destroy()\n"); 130 exit(PTS_UNRESOLVED); 131 } 132 thread_state = EXITING_THREAD; 133 pthread_exit(0); 134 return NULL; 135 } 136 137 int main(void) 138 { 139 int cnt = 0; 140 141 pthread_t thread1, thread2; 142 143 thread_state = NOT_CREATED_THREAD; 144 printf("main: create thread1\n"); 145 if (pthread_create(&thread1, NULL, fn_wr_1, NULL) != 0) { 146 printf("Error when creating thread1\n"); 147 return PTS_UNRESOLVED; 148 } 149 150 /* If the shared data is not altered by child after 5 seconds, 151 we regard it as blocked */ 152 /* we expect thread1 NOT to block */ 153 cnt = 0; 154 do { 155 sleep(1); 156 } while (thread_state != 3 && cnt++ < 5); 157 158 if (thread_state == 3) { 159 /* the child thread does not block, check the time expired or not */ 160 if (expired == 1) { 161 printf 162 ("Test FAILED: thread1 got ETIMEOUT when get the lock\n"); 163 return PTS_FAIL; 164 } 165 } else if (thread_state == ENTERED_THREAD) { 166 printf("Test FAILED: thread1 blocked\n"); 167 return PTS_FAIL; 168 } else { 169 printf("Unexpected state for thread1 %d\n", thread_state); 170 return PTS_UNRESOLVED; 171 } 172 173 if (pthread_join(thread1, NULL) != 0) { 174 printf("Error when joining thread1\n"); 175 return PTS_UNRESOLVED; 176 } 177 178 thread_state = ENTERED_THREAD; 179 printf("main: create thread2\n"); 180 if (pthread_create(&thread2, NULL, fn_wr_2, NULL) != 0) { 181 printf("Error when creating thread2\n"); 182 return PTS_UNRESOLVED; 183 } 184 185 /* If the shared data is not altered by child after 5 seconds, 186 we regard it as blocked */ 187 188 /* we expect thread2 NOT to block */ 189 cnt = 0; 190 do { 191 sleep(1); 192 } while (thread_state != EXITING_THREAD && cnt++ < 3); 193 194 if (thread_state == EXITING_THREAD) { 195 /* the child thread does not block, check the time expired or not */ 196 if (expired == 1) { 197 printf("Test FAILED: thread2 got ETIMEOUT\n"); 198 return PTS_FAIL; 199 } 200 } else if (thread_state == ENTERED_THREAD) { 201 printf("Test FAILED: thread2 blocked\n"); 202 return PTS_FAIL; 203 } else { 204 printf("Unexpected state for thread2 %d\n", thread_state); 205 return PTS_UNRESOLVED; 206 } 207 208 if (pthread_join(thread2, NULL) != 0) { 209 printf("Error when join thread2\n"); 210 return PTS_UNRESOLVED; 211 } 212 213 printf("Test PASSED\n"); 214 return PTS_PASS; 215 } 216