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}