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 pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) 80dc076565f772bb1953209fb69ea150b494aaa40robbiew * 92c28215423293e443469a07ae7011135d058b671Garrett Cooper * The function shall apply a write lock like the pthread_rwlock_wrlock(), with the exception 100dc076565f772bb1953209fb69ea150b494aaa40robbiew * that the funciton shall fail if any thread currently holds rwlock(for reading and writing). 110dc076565f772bb1953209fb69ea150b494aaa40robbiew * 120dc076565f772bb1953209fb69ea150b494aaa40robbiew * Steps: 130dc076565f772bb1953209fb69ea150b494aaa40robbiew * 1. Initialize a pthread_rwlock_t object 'rwlock' with pthread_rwlock_init() 140dc076565f772bb1953209fb69ea150b494aaa40robbiew * 2. Main thread lock 'rwlock' for reading with pthread_rwlock_rdlock() 152c28215423293e443469a07ae7011135d058b671Garrett Cooper * 3. Create a child thread, the thread locks 'rwlock' for writing, using 160dc076565f772bb1953209fb69ea150b494aaa40robbiew * pthread_rwlock_trywrlock(), should get EBUSY 170dc076565f772bb1953209fb69ea150b494aaa40robbiew * 4. Main thread unlocks 'rwlock' 182c28215423293e443469a07ae7011135d058b671Garrett Cooper * 5. Main thread locks 'rwlock' for writing, using pthread_rwlock_trywrlock(), 190dc076565f772bb1953209fb69ea150b494aaa40robbiew * should get the lock successfully 202c28215423293e443469a07ae7011135d058b671Garrett Cooper * 6. Create child thread to lock 'rwlock' for writing, with pthread_rwlock_trywrlock(), 210dc076565f772bb1953209fb69ea150b494aaa40robbiew * should get EBUSY 220dc076565f772bb1953209fb69ea150b494aaa40robbiew * 7. Main thread unlock 'rwlock' 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 320dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic pthread_rwlock_t rwlock; 330dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic int thread_state; 342c28215423293e443469a07ae7011135d058b671Garrett Cooperstatic int get_ebusy; 350dc076565f772bb1953209fb69ea150b494aaa40robbiew 362c28215423293e443469a07ae7011135d058b671Garrett Cooper/* thread_state indicates child thread state: 372c28215423293e443469a07ae7011135d058b671Garrett Cooper 1: not in child thread yet; 380dc076565f772bb1953209fb69ea150b494aaa40robbiew 2: just enter child thread ; 390dc076565f772bb1953209fb69ea150b494aaa40robbiew 3: just before child thread exit; 400dc076565f772bb1953209fb69ea150b494aaa40robbiew*/ 410dc076565f772bb1953209fb69ea150b494aaa40robbiew 420dc076565f772bb1953209fb69ea150b494aaa40robbiew#define NOT_CREATED_THREAD 1 430dc076565f772bb1953209fb69ea150b494aaa40robbiew#define ENTERED_THREAD 2 440dc076565f772bb1953209fb69ea150b494aaa40robbiew#define EXITING_THREAD 3 450dc076565f772bb1953209fb69ea150b494aaa40robbiew 46354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic void *fn_wr(void *arg) 472c28215423293e443469a07ae7011135d058b671Garrett Cooper{ 480dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = ENTERED_THREAD; 490dc076565f772bb1953209fb69ea150b494aaa40robbiew int rc; 500dc076565f772bb1953209fb69ea150b494aaa40robbiew 512c28215423293e443469a07ae7011135d058b671Garrett Cooper printf("thread: attempt pthread_rwlock_trywrlock()\n"); 520dc076565f772bb1953209fb69ea150b494aaa40robbiew rc = pthread_rwlock_trywrlock(&rwlock); 53354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (rc != EBUSY) { 540dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Test FAILED: thread: Expected EBUSY, got %d\n", rc); 550dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_FAIL); 560dc076565f772bb1953209fb69ea150b494aaa40robbiew } 570dc076565f772bb1953209fb69ea150b494aaa40robbiew get_ebusy = 1; 580dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread: correctly got EBUSY\n"); 590dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = EXITING_THREAD; 600dc076565f772bb1953209fb69ea150b494aaa40robbiew pthread_exit(0); 610dc076565f772bb1953209fb69ea150b494aaa40robbiew return NULL; 620dc076565f772bb1953209fb69ea150b494aaa40robbiew} 632c28215423293e443469a07ae7011135d058b671Garrett Cooper 644ca2bbdcd3003f3c8df4e6129e9c7b2bd1514f87Cyril Hrubisint main(void) 650dc076565f772bb1953209fb69ea150b494aaa40robbiew{ 660dc076565f772bb1953209fb69ea150b494aaa40robbiew int cnt = 0; 670dc076565f772bb1953209fb69ea150b494aaa40robbiew int rc = 0; 680dc076565f772bb1953209fb69ea150b494aaa40robbiew pthread_t thread1, thread2; 692c28215423293e443469a07ae7011135d058b671Garrett Cooper 700dc076565f772bb1953209fb69ea150b494aaa40robbiew get_ebusy = 0; 712c28215423293e443469a07ae7011135d058b671Garrett Cooper 72354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_init(&rwlock, NULL) != 0) { 730dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error at pthread_rwlock_init()\n"); 740dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 750dc076565f772bb1953209fb69ea150b494aaa40robbiew } 762c28215423293e443469a07ae7011135d058b671Garrett Cooper 770dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: attempt read lock\n"); 782c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We have no lock, this read lock should succeed */ 79354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_rdlock(&rwlock) != 0) { 800dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error at pthread_rwlock_rdlock()\n"); 810dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 820dc076565f772bb1953209fb69ea150b494aaa40robbiew } 830dc076565f772bb1953209fb69ea150b494aaa40robbiew 840dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: acquired read lock\n"); 850dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = NOT_CREATED_THREAD; 860dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: create thread1\n"); 87354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_create(&thread1, NULL, fn_wr, NULL) != 0) { 880dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Error creating thread1\n"); 890dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 900dc076565f772bb1953209fb69ea150b494aaa40robbiew } 912c28215423293e443469a07ae7011135d058b671Garrett Cooper 920dc076565f772bb1953209fb69ea150b494aaa40robbiew /* If the shared data is not altered by child after 3 seconds, 930dc076565f772bb1953209fb69ea150b494aaa40robbiew we regard it as blocked */ 940dc076565f772bb1953209fb69ea150b494aaa40robbiew /* We do no expect thread1 to block */ 950dc076565f772bb1953209fb69ea150b494aaa40robbiew cnt = 0; 96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao do { 970dc076565f772bb1953209fb69ea150b494aaa40robbiew sleep(1); 98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } while (thread_state != EXITING_THREAD && cnt++ < 3); 992c28215423293e443469a07ae7011135d058b671Garrett Cooper 100354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (thread_state == ENTERED_THREAD) { 1010dc076565f772bb1953209fb69ea150b494aaa40robbiew /* the child thread blocked */ 102354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf 103354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("Test FAILED: thread1 should not block on pthread_rwlock_trywrlock()\n"); 1040dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_FAIL); 105354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else if (thread_state != EXITING_THREAD) { 106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf("Unexpected thread state for thread1: %d\n", 107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao thread_state); 1080dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1090dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1102c28215423293e443469a07ae7011135d058b671Garrett Cooper 111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (get_ebusy != 1) { 1120dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Test FAILED: thread1 should get EBUSY\n"); 1130dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_FAIL); 1140dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1150dc076565f772bb1953209fb69ea150b494aaa40robbiew 1160dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: unlock read lock\n"); 117354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_unlock(&rwlock) != 0) { 1180dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error releasing read lock\n"); 1190dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1200dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1212c28215423293e443469a07ae7011135d058b671Garrett Cooper 122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_join(thread1, NULL) != 0) { 1230dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error joining thread1\n"); 1240dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1250dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1262c28215423293e443469a07ae7011135d058b671Garrett Cooper 1270dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: attempt pthread_rwlock_trywrlock()\n"); 128354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Should get the write lock */ 1290dc076565f772bb1953209fb69ea150b494aaa40robbiew rc = pthread_rwlock_trywrlock(&rwlock); 130354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (rc != 0) { 131354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf 132354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("Test FAILED: main failed at pthread_rwlock_trywrlock(), error code: %d\n", 133354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao rc); 1342c28215423293e443469a07ae7011135d058b671Garrett Cooper return PTS_FAIL; 1350dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1360dc076565f772bb1953209fb69ea150b494aaa40robbiew 1370dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: acquired write lock\n"); 1380dc076565f772bb1953209fb69ea150b494aaa40robbiew 1390dc076565f772bb1953209fb69ea150b494aaa40robbiew get_ebusy = 0; 1400dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = NOT_CREATED_THREAD; 1410dc076565f772bb1953209fb69ea150b494aaa40robbiew cnt = 0; 1420dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: create thread2\n"); 143354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_create(&thread2, NULL, fn_wr, NULL) != 0) { 1440dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error creating thread2\n"); 1450dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 1460dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1472c28215423293e443469a07ae7011135d058b671Garrett Cooper 1480dc076565f772bb1953209fb69ea150b494aaa40robbiew /* We do not expect thread2 to block */ 149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao do { 1500dc076565f772bb1953209fb69ea150b494aaa40robbiew sleep(1); 151354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } while (thread_state != EXITING_THREAD && cnt++ < 3); 1522c28215423293e443469a07ae7011135d058b671Garrett Cooper 153354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (thread_state == ENTERED_THREAD) { 154354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf 155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("Test FAILED: thread2 should not block on pthread_rwlock_trywrlock()\n"); 1560dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_FAIL); 157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else if (thread_state != EXITING_THREAD) { 1580dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Unexpected thread state: %d\n", thread_state); 1590dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1600dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1610dc076565f772bb1953209fb69ea150b494aaa40robbiew 162354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (get_ebusy != 1) { 1630dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Test FAILED: thread2 should get EBUSY\n"); 1640dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_FAIL); 1650dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1662c28215423293e443469a07ae7011135d058b671Garrett Cooper 1670dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: unlock write lock\n"); 1680dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = 1; 169354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_unlock(&rwlock) != 0) { 1700dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error at 2nd pthread_rwlock_unlock()\n"); 1710dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1720dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1730dc076565f772bb1953209fb69ea150b494aaa40robbiew 174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_join(thread2, NULL) != 0) { 1750dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error at 2cn pthread_join()\n"); 1760dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1770dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1782c28215423293e443469a07ae7011135d058b671Garrett Cooper 179354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pthread_rwlock_destroy(&rwlock) != 0) { 1800dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Error at pthread_rwlockattr_destroy()\n"); 1810dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 1822c28215423293e443469a07ae7011135d058b671Garrett Cooper } 1830dc076565f772bb1953209fb69ea150b494aaa40robbiew 1840dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Test PASSED\n"); 1850dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_PASS; 186ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman} 187