6-1.c revision 2c28215423293e443469a07ae7011135d058b671
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 * Test pthread_rwlock_timedwrlock(pthread_rwlock_t * rwlock) 72c28215423293e443469a07ae7011135d058b671Garrett Cooper * 82c28215423293e443469a07ae7011135d058b671Garrett Cooper * If a signal that causes a signal handler to be executed is delivered to 9e9410dfd93b8e415ecbe3f7e09a085462b27836eGarrett Cooper * a thread blocked on a read-write lock via a call to pthread_rwlock_timedwrlock(), 102c28215423293e443469a07ae7011135d058b671Garrett Cooper * upon return from the signal handler the thread shall resume waiting for the lock 110dc076565f772bb1953209fb69ea150b494aaa40robbiew * as if it was not interrupted. 120dc076565f772bb1953209fb69ea150b494aaa40robbiew * 130dc076565f772bb1953209fb69ea150b494aaa40robbiew * Test that after returning from a signal handler, the reader will continue 142c28215423293e443469a07ae7011135d058b671Garrett Cooper * to wait with timedrdlock as long as the specified 'timeout' does not expire (the 150dc076565f772bb1953209fb69ea150b494aaa40robbiew * time spent in signal handler is longer than the specifed 'timeout'). 160dc076565f772bb1953209fb69ea150b494aaa40robbiew * 170dc076565f772bb1953209fb69ea150b494aaa40robbiew * Steps: 180dc076565f772bb1953209fb69ea150b494aaa40robbiew * 1. main thread create and write lock 'rwlock' 190dc076565f772bb1953209fb69ea150b494aaa40robbiew * 2. main thread create a thread sig_thread, the thread is set to handle SIGUSR1 200dc076565f772bb1953209fb69ea150b494aaa40robbiew * 3. sig_thread timed write-lock 'rwlock' for writing, it should block 212c28215423293e443469a07ae7011135d058b671Garrett Cooper * 4. While the sig_thread is waiting (not expired yet), main thread sends SIGUSR1 220dc076565f772bb1953209fb69ea150b494aaa40robbiew * to sig_thread via pthread_kill 230dc076565f772bb1953209fb69ea150b494aaa40robbiew * 5. Check that when thread handler returns, sig_thread resume block 240dc076565f772bb1953209fb69ea150b494aaa40robbiew * 7. When the wait is terminated, check that the thread wait for a proper period before 252c28215423293e443469a07ae7011135d058b671Garrett Cooper * expiring. 260dc076565f772bb1953209fb69ea150b494aaa40robbiew * 270dc076565f772bb1953209fb69ea150b494aaa40robbiew */ 280dc076565f772bb1953209fb69ea150b494aaa40robbiew 290dc076565f772bb1953209fb69ea150b494aaa40robbiew#define _XOPEN_SOURCE 600 300dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <pthread.h> 310dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdio.h> 320dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdlib.h> 330dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <signal.h> 340dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <errno.h> 350dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <unistd.h> 360dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <time.h> 370dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <sys/time.h> 380dc076565f772bb1953209fb69ea150b494aaa40robbiew#include "posixtest.h" 390dc076565f772bb1953209fb69ea150b494aaa40robbiew 400dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic pthread_t sig_thread; 410dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic pthread_rwlock_t rwlock; 420dc076565f772bb1953209fb69ea150b494aaa40robbiew 430dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic int thread_state; 440dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic int handler_called; 450dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic struct timeval before_wait, after_wait; 460dc076565f772bb1953209fb69ea150b494aaa40robbiew 472c28215423293e443469a07ae7011135d058b671Garrett Cooper/* thread_state indicates child thread state: 482c28215423293e443469a07ae7011135d058b671Garrett Cooper 1: not in child thread yet; 490dc076565f772bb1953209fb69ea150b494aaa40robbiew 2: just enter child thread ; 500dc076565f772bb1953209fb69ea150b494aaa40robbiew 3: just before child thread exit; 510dc076565f772bb1953209fb69ea150b494aaa40robbiew*/ 520dc076565f772bb1953209fb69ea150b494aaa40robbiew 530dc076565f772bb1953209fb69ea150b494aaa40robbiew#define NOT_CREATED_THREAD 1 540dc076565f772bb1953209fb69ea150b494aaa40robbiew#define ENTERED_THREAD 2 550dc076565f772bb1953209fb69ea150b494aaa40robbiew#define EXITING_THREAD 3 560dc076565f772bb1953209fb69ea150b494aaa40robbiew 570dc076565f772bb1953209fb69ea150b494aaa40robbiew#define TIMEOUT 5 580dc076565f772bb1953209fb69ea150b494aaa40robbiew 590dc076565f772bb1953209fb69ea150b494aaa40robbiew/* Signal handler called by the thread when SIGUSR1 is received */ 600dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic void sig_handler() { 610dc076565f772bb1953209fb69ea150b494aaa40robbiew 62df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (pthread_equal(pthread_self(), sig_thread)) 630dc076565f772bb1953209fb69ea150b494aaa40robbiew { 640dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("sig_handler: signal is handled by sig_thread\n"); 650dc076565f772bb1953209fb69ea150b494aaa40robbiew handler_called = 1; 662c28215423293e443469a07ae7011135d058b671Garrett Cooper 670dc076565f772bb1953209fb69ea150b494aaa40robbiew } 680dc076565f772bb1953209fb69ea150b494aaa40robbiew else 690dc076565f772bb1953209fb69ea150b494aaa40robbiew { 700dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("sig_handler: signal is not handled by sig_thread\n"); 710dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 720dc076565f772bb1953209fb69ea150b494aaa40robbiew } 730dc076565f772bb1953209fb69ea150b494aaa40robbiew} 740dc076565f772bb1953209fb69ea150b494aaa40robbiew 750dc076565f772bb1953209fb69ea150b494aaa40robbiewstatic void * th_fn(void *arg) 760dc076565f772bb1953209fb69ea150b494aaa40robbiew{ 770dc076565f772bb1953209fb69ea150b494aaa40robbiew struct sigaction act; 780dc076565f772bb1953209fb69ea150b494aaa40robbiew struct timespec abs_timeout; 790dc076565f772bb1953209fb69ea150b494aaa40robbiew int rc = 0; 802c28215423293e443469a07ae7011135d058b671Garrett Cooper 810dc076565f772bb1953209fb69ea150b494aaa40robbiew handler_called = 0; 820dc076565f772bb1953209fb69ea150b494aaa40robbiew 832c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Set up signal handler for SIGUSR1 */ 840dc076565f772bb1953209fb69ea150b494aaa40robbiew 850dc076565f772bb1953209fb69ea150b494aaa40robbiew act.sa_flags = 0; 860dc076565f772bb1953209fb69ea150b494aaa40robbiew act.sa_handler = sig_handler; 870dc076565f772bb1953209fb69ea150b494aaa40robbiew /* block all the signal when hanlding SIGUSR1 */ 880dc076565f772bb1953209fb69ea150b494aaa40robbiew sigfillset(&act.sa_mask); 890dc076565f772bb1953209fb69ea150b494aaa40robbiew sigaction(SIGUSR1, &act, 0); 902c28215423293e443469a07ae7011135d058b671Garrett Cooper 910dc076565f772bb1953209fb69ea150b494aaa40robbiew gettimeofday(&before_wait, NULL); 920dc076565f772bb1953209fb69ea150b494aaa40robbiew abs_timeout.tv_sec = before_wait.tv_sec + TIMEOUT; 930dc076565f772bb1953209fb69ea150b494aaa40robbiew abs_timeout.tv_nsec = before_wait.tv_usec * 1000; 942c28215423293e443469a07ae7011135d058b671Garrett Cooper 950dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread: attempt timed write lock, %d seconds\n", TIMEOUT); 960dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = ENTERED_THREAD; 970dc076565f772bb1953209fb69ea150b494aaa40robbiew rc = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout); 98df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (rc != ETIMEDOUT) 990dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1000dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("sig_thread: pthread_rwlock_timedwrlock returns %d\n", rc); 1010dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_FAIL); 1020dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1030dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("thread: timer correctly expired\n"); 1040dc076565f772bb1953209fb69ea150b494aaa40robbiew gettimeofday(&after_wait, NULL); 1050dc076565f772bb1953209fb69ea150b494aaa40robbiew 1060dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = EXITING_THREAD; 1070dc076565f772bb1953209fb69ea150b494aaa40robbiew pthread_exit(0); 1080dc076565f772bb1953209fb69ea150b494aaa40robbiew return NULL; 1090dc076565f772bb1953209fb69ea150b494aaa40robbiew} 1100dc076565f772bb1953209fb69ea150b494aaa40robbiew 1110dc076565f772bb1953209fb69ea150b494aaa40robbiewint main() 1120dc076565f772bb1953209fb69ea150b494aaa40robbiew{ 1130dc076565f772bb1953209fb69ea150b494aaa40robbiew int cnt; 1140dc076565f772bb1953209fb69ea150b494aaa40robbiew struct timeval time_diff; 1150dc076565f772bb1953209fb69ea150b494aaa40robbiew 116df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (pthread_rwlock_init(&rwlock, NULL) != 0) 1170dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1180dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Error at pthread_rwlock_init()\n"); 1190dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 1200dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1212c28215423293e443469a07ae7011135d058b671Garrett Cooper 1220dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: attempt write lock\n"); 123df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (pthread_rwlock_wrlock(&rwlock) != 0) 1240dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1250dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error at pthread_rwlock_wrlock()\n"); 1260dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 1270dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1280dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: acquired write lock\n"); 1290dc076565f772bb1953209fb69ea150b494aaa40robbiew 1300dc076565f772bb1953209fb69ea150b494aaa40robbiew thread_state = NOT_CREATED_THREAD; 131df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (pthread_create(&sig_thread, NULL, th_fn, NULL) != 0) 1320dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1330dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Error at pthread_create()\n"); 1340dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 1350dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1362c28215423293e443469a07ae7011135d058b671Garrett Cooper 1370dc076565f772bb1953209fb69ea150b494aaa40robbiew /* Wait for the thread to get ready for handling signal (the thread should 1382c28215423293e443469a07ae7011135d058b671Garrett Cooper * be block on rwlock since main() has the write lock at this point) */ 1390dc076565f772bb1953209fb69ea150b494aaa40robbiew cnt = 0; 1400dc076565f772bb1953209fb69ea150b494aaa40robbiew do{ 1410dc076565f772bb1953209fb69ea150b494aaa40robbiew sleep(1); 142df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper }while (thread_state != ENTERED_THREAD && cnt++ < TIMEOUT); 1432c28215423293e443469a07ae7011135d058b671Garrett Cooper 144df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (thread_state != ENTERED_THREAD) 1450dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1460dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Unexpected thread state %d\n", thread_state); 1470dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1480dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1490dc076565f772bb1953209fb69ea150b494aaa40robbiew 1500dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: fire SIGUSR1 to thread\n"); 151df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (pthread_kill(sig_thread, SIGUSR1) != 0) 1520dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1530dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error at pthread_kill()\n"); 1540dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1550dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1562c28215423293e443469a07ae7011135d058b671Garrett Cooper 1570dc076565f772bb1953209fb69ea150b494aaa40robbiew /* wait at most 2*TIMEOUT seconds */ 1580dc076565f772bb1953209fb69ea150b494aaa40robbiew cnt = 0; 1590dc076565f772bb1953209fb69ea150b494aaa40robbiew do{ 1600dc076565f772bb1953209fb69ea150b494aaa40robbiew sleep(1); 161df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper }while (thread_state != EXITING_THREAD && cnt++ < 2*TIMEOUT); 1622c28215423293e443469a07ae7011135d058b671Garrett Cooper 163df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (cnt >= 2*TIMEOUT) 1640dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1650dc076565f772bb1953209fb69ea150b494aaa40robbiew /* thread blocked*/ 1660dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Test FAILED: thread blocked even afer the abs_timeout expired\n"); 1672c28215423293e443469a07ae7011135d058b671Garrett Cooper exit(PTS_FAIL); 1680dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1692c28215423293e443469a07ae7011135d058b671Garrett Cooper 170df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (handler_called != 1) 1710dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1720dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("The handler for SIGUSR1 did not get called\n"); 1730dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_UNRESOLVED); 1742c28215423293e443469a07ae7011135d058b671Garrett Cooper } 1752c28215423293e443469a07ae7011135d058b671Garrett Cooper 1760dc076565f772bb1953209fb69ea150b494aaa40robbiew /* Test that the thread block for the correct TIMOUT time */ 1770dc076565f772bb1953209fb69ea150b494aaa40robbiew time_diff.tv_sec = after_wait.tv_sec - before_wait.tv_sec; 1780dc076565f772bb1953209fb69ea150b494aaa40robbiew time_diff.tv_usec = after_wait.tv_usec - before_wait.tv_usec; 1790dc076565f772bb1953209fb69ea150b494aaa40robbiew if (time_diff.tv_usec < 0) 1800dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1810dc076565f772bb1953209fb69ea150b494aaa40robbiew --time_diff.tv_sec; 1820dc076565f772bb1953209fb69ea150b494aaa40robbiew time_diff.tv_usec += 1000000; 1830dc076565f772bb1953209fb69ea150b494aaa40robbiew } 184df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (time_diff.tv_sec < TIMEOUT) 1850dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1860dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Test FAILED: Timeout was for %d seconds, but waited for %ld.%06ld seconds instead\n", 1870dc076565f772bb1953209fb69ea150b494aaa40robbiew TIMEOUT, (long)time_diff.tv_sec, (long)time_diff.tv_usec); 1880dc076565f772bb1953209fb69ea150b494aaa40robbiew exit(PTS_FAIL); 1890dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1900dc076565f772bb1953209fb69ea150b494aaa40robbiew 1910dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: unlock write lock\n"); 192df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (pthread_rwlock_unlock(&rwlock) != 0) 1930dc076565f772bb1953209fb69ea150b494aaa40robbiew { 1940dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error at pthread_rwlock_unlock()\n"); 1950dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 1960dc076565f772bb1953209fb69ea150b494aaa40robbiew } 1972c28215423293e443469a07ae7011135d058b671Garrett Cooper 198df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (pthread_join(sig_thread, NULL) != 0) 1990dc076565f772bb1953209fb69ea150b494aaa40robbiew { 2000dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("main: Error at pthread_join()\n"); 2010dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 2020dc076565f772bb1953209fb69ea150b494aaa40robbiew } 2032c28215423293e443469a07ae7011135d058b671Garrett Cooper 204df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper if (pthread_rwlock_destroy(&rwlock) != 0) 2050dc076565f772bb1953209fb69ea150b494aaa40robbiew { 2060dc076565f772bb1953209fb69ea150b494aaa40robbiew printf("Error at pthread_destroy()\n"); 2070dc076565f772bb1953209fb69ea150b494aaa40robbiew return PTS_UNRESOLVED; 2080dc076565f772bb1953209fb69ea150b494aaa40robbiew } 2090dc076565f772bb1953209fb69ea150b494aaa40robbiew 2102c28215423293e443469a07ae7011135d058b671Garrett Cooper printf("Test PASSED\n"); 2112c28215423293e443469a07ae7011135d058b671Garrett Cooper return PTS_PASS; 2122c28215423293e443469a07ae7011135d058b671Garrett Cooper}