12c28215423293e443469a07ae7011135d058b671Garrett Cooper/* 20dc076565f772bb1953209fb69ea150b494aaa40robbiew * Copyright (c) 2002, Intel Corporation. All rights reserved. 30dc076565f772bb1953209fb69ea150b494aaa40robbiew * This file is licensed under the GPL license. For the full content 42c28215423293e443469a07ae7011135d058b671Garrett Cooper * of this license, see the COPYING file at the top level of this 50dc076565f772bb1953209fb69ea150b494aaa40robbiew * source tree. 60dc076565f772bb1953209fb69ea150b494aaa40robbiew 70dc076565f772bb1953209fb69ea150b494aaa40robbiew * Test that pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock) 80dc076565f772bb1953209fb69ea150b494aaa40robbiew * 92c28215423293e443469a07ae7011135d058b671Garrett Cooper * Under no circumstances shall the function fail with a timeout if the lock can be 102c28215423293e443469a07ae7011135d058b671Garrett Cooper * acquired immediately. The abs_timeout parameter need not be checked if the lock 110dc076565f772bb1953209fb69ea150b494aaa40robbiew * can be immediately acquired. 120dc076565f772bb1953209fb69ea150b494aaa40robbiew * 130dc076565f772bb1953209fb69ea150b494aaa40robbiew * Steps:n 140dc076565f772bb1953209fb69ea150b494aaa40robbiew * 1. Main thread create a thread. 152c28215423293e443469a07ae7011135d058b671Garrett Cooper * 2. Child thread lock 'rwlock' for reading with pthread_rwlock_timedrdlock(), 160dc076565f772bb1953209fb69ea150b494aaa40robbiew * should not fail with timeout 170dc076565f772bb1953209fb69ea150b494aaa40robbiew * 3. The child thread unlocks the 'rwlock' and exits. 180dc076565f772bb1953209fb69ea150b494aaa40robbiew * 4. Main thread create another thread. 192c28215423293e443469a07ae7011135d058b671Garrett Cooper * 4. The child thread lock 'rwlock' for reading, with pthread_rwlock_timedrdlock(), 200dc076565f772bb1953209fb69ea150b494aaa40robbiew * specifying a 'abs_timeout'. The thread sleeps until 'abs_timeout' expires. 210dc076565f772bb1953209fb69ea150b494aaa40robbiew * 5. The thread call pthread_rwlock_timedrdlock(). Should _NOT_ get ETIMEDOUT. 220dc076565f772bb1953209fb69ea150b494aaa40robbiew */ 230dc076565f772bb1953209fb69ea150b494aaa40robbiew 240dc076565f772bb1953209fb69ea150b494aaa40robbiew#define _XOPEN_SOURCE 600 250dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <pthread.h> 260dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdio.h> 270dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdlib.h> 280dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <unistd.h> 290dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <errno.h> 300dc076565f772bb1953209fb69ea150b494aaa40robbiew#include "posixtest.h" 310dc076565f772bb1953209fb69ea150b494aaa40robbiew 320dc076565f772bb1953209fb69ea150b494aaa40robbiew#define NOT_CREATED_THREAD 1 330dc076565f772bb1953209fb69ea150b494aaa40robbiew#define ENTERED_THREAD 2 340dc076565f772bb1953209fb69ea150b494aaa40robbiew#define EXITING_THREAD 3 350dc076565f772bb1953209fb69ea150b494aaa40robbiew 360dc076565f772bb1953209fb69ea150b494aaa40robbiew#define TIMEOUT 1 372c28215423293e443469a07ae7011135d058b671Garrett Cooperstatic int thread_state; 380dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic int currsec1; 390dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic int expired; 400dc076565f772bb1953209fb69ea150b494aaa40robbiew 41354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic void *fn_rd_1(void *arg) 422c28215423293e443469a07ae7011135d058b671Garrett Cooper{ 430dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = ENTERED_THREAD; 440dc076565f772bb1953209fb69ea150b494aaa40robbiew struct timespec abs_timeout; 450dc076565f772bb1953209fb69ea150b494aaa40robbiew int rc; 460dc076565f772bb1953209fb69ea150b494aaa40robbiew pthread_rwlock_t rwlock; 470dc076565f772bb1953209fb69ea150b494aaa40robbiew 48354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_init(&rwlock, NULL) != 0) { 490dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread1: Error at pthread_rwlock_init\n"); 500dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 510dc076565f772bb1953209fb69ea150b494aaa40robbiew } 520dc076565f772bb1953209fb69ea150b494aaa40robbiew 530dc076565f772bb1953209fb69ea150b494aaa40robbiew currsec1 = time(NULL); 540dc076565f772bb1953209fb69ea150b494aaa40robbiew 550dc076565f772bb1953209fb69ea150b494aaa40robbiew /* Absolute time, not relative. */ 560dc076565f772bb1953209fb69ea150b494aaa40robbiew abs_timeout.tv_sec = currsec1 + TIMEOUT; 572c28215423293e443469a07ae7011135d058b671Garrett Cooper abs_timeout.tv_nsec = 0; 580dc076565f772bb1953209fb69ea150b494aaa40robbiew 592c28215423293e443469a07ae7011135d058b671Garrett Cooper printf("thread1: attempt timed read-lock\n"); 600dc076565f772bb1953209fb69ea150b494aaa40robbiew rc = pthread_rwlock_timedrdlock(&rwlock, &abs_timeout); 61354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (rc == ETIMEDOUT) { 620dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread1: timed read-lock expired\n"); 630dc076565f772bb1953209fb69ea150b494aaa40robbiew expired = 1; 64354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else if (rc == 0) { 650dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread1: acquired read lock\n"); 660dc076565f772bb1953209fb69ea150b494aaa40robbiew expired = 0; 670dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread1: unlock read lock\n"); 68354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_unlock(&rwlock) != 0) { 692c28215423293e443469a07ae7011135d058b671Garrett Cooper printf("thread1: failed to release read lock\n"); 700dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 710dc076565f772bb1953209fb69ea150b494aaa40robbiew } 72354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 730dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread1: Error in pthread_rwlock_timedrdlock().\n"); 740dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 750dc076565f772bb1953209fb69ea150b494aaa40robbiew } 762c28215423293e443469a07ae7011135d058b671Garrett Cooper 77354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_destroy(&rwlock) != 0) { 780dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread1: Error at pthread_rwlockattr_destroy()"); 790dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 802c28215423293e443469a07ae7011135d058b671Garrett Cooper } 810dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = EXITING_THREAD; 820dc076565f772bb1953209fb69ea150b494aaa40robbiew pthread_exit(0); 830dc076565f772bb1953209fb69ea150b494aaa40robbiew return NULL; 840dc076565f772bb1953209fb69ea150b494aaa40robbiew} 852c28215423293e443469a07ae7011135d058b671Garrett Cooper 86354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic void *fn_rd_2(void *arg) 872c28215423293e443469a07ae7011135d058b671Garrett Cooper{ 880dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = ENTERED_THREAD; 890dc076565f772bb1953209fb69ea150b494aaa40robbiew struct timespec abs_timeout; 900dc076565f772bb1953209fb69ea150b494aaa40robbiew int rc; 910dc076565f772bb1953209fb69ea150b494aaa40robbiew pthread_rwlock_t rwlock; 920dc076565f772bb1953209fb69ea150b494aaa40robbiew 93354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_init(&rwlock, NULL) != 0) { 940dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread2: Error at pthread_rwlock_init\n"); 950dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 960dc076565f772bb1953209fb69ea150b494aaa40robbiew } 970dc076565f772bb1953209fb69ea150b494aaa40robbiew currsec1 = time(NULL); 980dc076565f772bb1953209fb69ea150b494aaa40robbiew 990dc076565f772bb1953209fb69ea150b494aaa40robbiew /* Ensure that the abs_timeout has passed by _subtracting_ the timeout value of 1 1000dc076565f772bb1953209fb69ea150b494aaa40robbiew * from the current time. */ 1010dc076565f772bb1953209fb69ea150b494aaa40robbiew abs_timeout.tv_sec = currsec1 - TIMEOUT; 1022c28215423293e443469a07ae7011135d058b671Garrett Cooper abs_timeout.tv_nsec = 0; 1032c28215423293e443469a07ae7011135d058b671Garrett Cooper 1042c28215423293e443469a07ae7011135d058b671Garrett Cooper printf("thread2: attempt timed read-lock\n"); 1050dc076565f772bb1953209fb69ea150b494aaa40robbiew rc = pthread_rwlock_timedrdlock(&rwlock, &abs_timeout); 106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (rc == ETIMEDOUT) { 1070dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread2: timed read-lock expired\n"); 1080dc076565f772bb1953209fb69ea150b494aaa40robbiew expired = 1; 109354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else if (rc == 0) { 1100dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread2: acquired read lock\n"); 1110dc076565f772bb1953209fb69ea150b494aaa40robbiew expired = 0; 1120dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread2: unlock read lock\n"); 113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_unlock(&rwlock) != 0) { 1140dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread2: failed to release read lock\n"); 1150dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1160dc076565f772bb1953209fb69ea150b494aaa40robbiew } 117354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 1180dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread2: Error in pthread_rwlock_timedrdlock().\n"); 1190dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1200dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1212c28215423293e443469a07ae7011135d058b671Garrett Cooper 122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_destroy(&rwlock) != 0) { 1230dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread2: Error at pthread_rwlockattr_destroy()\n"); 1240dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1252c28215423293e443469a07ae7011135d058b671Garrett Cooper } 1260dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = EXITING_THREAD; 1270dc076565f772bb1953209fb69ea150b494aaa40robbiew pthread_exit(0); 1280dc076565f772bb1953209fb69ea150b494aaa40robbiew return NULL; 1290dc076565f772bb1953209fb69ea150b494aaa40robbiew} 1300dc076565f772bb1953209fb69ea150b494aaa40robbiew 1314ca2bbdcd3003f3c8df4e6129e9c7b2bd1514f87Cyril Hrubisint main(void) 1320dc076565f772bb1953209fb69ea150b494aaa40robbiew{ 1330dc076565f772bb1953209fb69ea150b494aaa40robbiew int cnt = 0; 1342c28215423293e443469a07ae7011135d058b671Garrett Cooper 1350dc076565f772bb1953209fb69ea150b494aaa40robbiew pthread_t thread1, thread2; 1362c28215423293e443469a07ae7011135d058b671Garrett Cooper 1370dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = NOT_CREATED_THREAD; 1380dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: create thread1\n"); 139354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_create(&thread1, NULL, fn_rd_1, NULL) != 0) { 1400dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Error when creating thread1\n"); 1410dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 1420dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1432c28215423293e443469a07ae7011135d058b671Garrett Cooper 1440dc076565f772bb1953209fb69ea150b494aaa40robbiew /* If the shared data is not altered by child after 5 seconds, 1450dc076565f772bb1953209fb69ea150b494aaa40robbiew we regard it as blocked */ 1462c28215423293e443469a07ae7011135d058b671Garrett Cooper 1470dc076565f772bb1953209fb69ea150b494aaa40robbiew /* we expect thread1 NOT to block, but rather for the timed read-lock to expire */ 1480dc076565f772bb1953209fb69ea150b494aaa40robbiew cnt = 0; 149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao do { 1500dc076565f772bb1953209fb69ea150b494aaa40robbiew sleep(1); 151354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } while (thread_state != EXITING_THREAD && cnt++ < 5); 1522c28215423293e443469a07ae7011135d058b671Garrett Cooper 153354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (thread_state == EXITING_THREAD) { 1540dc076565f772bb1953209fb69ea150b494aaa40robbiew /* the child thread does not block, check the time expired or not */ 155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (expired == 1) { 156354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf 157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("Test FAILED: thread1 incorrectly received ETIMEDOUT\n"); 1580dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_FAIL; 1590dc076565f772bb1953209fb69ea150b494aaa40robbiew } 160354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else if (thread_state == ENTERED_THREAD) { 161354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf 162354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("Test FAILED: thread1 incorrectly blocked for reading rwlock\n"); 1630dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_FAIL; 164354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 1650dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Unexpected state for thread1 %d\n", thread_state); 1660dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 1670dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1682c28215423293e443469a07ae7011135d058b671Garrett Cooper 169354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_join(thread1, NULL) != 0) { 1700dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Error when joining thread1\n"); 1710dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 1720dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1730dc076565f772bb1953209fb69ea150b494aaa40robbiew 1740dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: create thread2\n"); 1750dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = NOT_CREATED_THREAD; 176354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_create(&thread2, NULL, fn_rd_2, NULL) != 0) { 1770dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Error when creating thread2\n"); 1780dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 1790dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1802c28215423293e443469a07ae7011135d058b671Garrett Cooper 1810dc076565f772bb1953209fb69ea150b494aaa40robbiew /* If the shared data is not altered by child after 5 seconds, 1820dc076565f772bb1953209fb69ea150b494aaa40robbiew we regard it as blocked */ 1832c28215423293e443469a07ae7011135d058b671Garrett Cooper 1840dc076565f772bb1953209fb69ea150b494aaa40robbiew /* we expect thread2 NOT to block */ 1850dc076565f772bb1953209fb69ea150b494aaa40robbiew cnt = 0; 186354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao do { 1870dc076565f772bb1953209fb69ea150b494aaa40robbiew sleep(1); 188354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } while (thread_state != EXITING_THREAD && cnt++ < 5); 1892c28215423293e443469a07ae7011135d058b671Garrett Cooper 190354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (thread_state == EXITING_THREAD) { 1910dc076565f772bb1953209fb69ea150b494aaa40robbiew /* the child thread does not block, check the time expired or not */ 192354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (expired == 1) { 193354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf 194354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("Test FAILED: thread2 incorrectly received ETIMEDOUT\n"); 1950dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_FAIL; 1960dc076565f772bb1953209fb69ea150b494aaa40robbiew } 197354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else if (thread_state == ENTERED_THREAD) { 198354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf 199354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("Test FAILED: thread2 incorrectly blocked for reading rwlock\n"); 2000dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_FAIL; 201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 2020dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Unexpected state for thread2 %d\n", thread_state); 2030dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 2040dc076565f772bb1953209fb69ea150b494aaa40robbiew } 2052c28215423293e443469a07ae7011135d058b671Garrett Cooper 206354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_join(thread2, NULL) != 0) { 2070dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Error when join thread2\n"); 2080dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 2090dc076565f772bb1953209fb69ea150b494aaa40robbiew } 2100dc076565f772bb1953209fb69ea150b494aaa40robbiew 2110dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Test PASSED\n"); 2120dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_PASS; 213ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman} 214