Home | History | Annotate | Download | only in pthread_rwlock_timedwrlock
      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  *	The timeout shall expire when the absolute time specified by abs_timeout passes,
     10  *	as measured by the clock on which timeouts are based (that is, when the
     11  *	value of that clock equals or exceeds abs_timeout), or if the absolute time
     12  *	specified by abs_timeout has already been passed at the time of the call.
     13  *
     14  * Steps:
     15  * 1.  Initialize 'rwlock'
     16  * 2.  Main thread locks 'rwlock' for writing with pthread_rwlock_wrlock()
     17  * 3.  Create a child thread, specify a 'abs_timeout' as being the current time _minus_ a
     18  *     timeout period, meaning this will ensure that the abs_timeout would have already
     19  *     passed.
     20  * 4.  The thread locks 'rwlock' for writing, using pthread_rwlock_timedwrlock(). Should
     21  *	get an ETIMEOUT error.
     22  */
     23 
     24 #define _XOPEN_SOURCE 600
     25 
     26 #include <pthread.h>
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <unistd.h>
     30 #include <errno.h>
     31 #include <time.h>
     32 #include "posixtest.h"
     33 
     34 #define TIMEOUT 1
     35 
     36 static pthread_rwlock_t rwlock;
     37 static int thread_state;
     38 static int expired;
     39 
     40 /* thread_state indicates child thread state:
     41 	1: not in child thread yet;
     42 	2: just enter child thread ;
     43 	3: just before child thread exit;
     44 */
     45 
     46 #define NOT_CREATED_THREAD 1
     47 #define ENTERED_THREAD 2
     48 #define EXITING_THREAD 3
     49 
     50 static void *fn(void *arg)
     51 {
     52 	struct timespec abs_timeout;
     53 	int rc;
     54 	thread_state = ENTERED_THREAD;
     55 
     56 	if (clock_gettime(CLOCK_REALTIME, &abs_timeout) != 0) {
     57 		perror("thread: clock_gettime");
     58 		exit(PTS_UNRESOLVED);
     59 	}
     60 
     61 	/*
     62 	 * The CLOCK_REALTIME represents time passed since the Epoch
     63 	 * so we may expect that tv_sec is > TIMEOUT (1 sec)
     64 	 */
     65 	abs_timeout.tv_sec -= TIMEOUT;
     66 
     67 	printf("thread: attempt timed write-lock\n");
     68 	rc = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout);
     69 
     70 	if (rc == ETIMEDOUT) {
     71 		printf("thread: timer expired\n");
     72 		expired = 1;
     73 	} else if (rc == 0) {
     74 		printf("thread: acquired write lock\n");
     75 		expired = 0;
     76 		printf("thread: unlock write lock\n");
     77 		if (pthread_rwlock_unlock(&rwlock) != 0) {
     78 			printf("thread: failed to release lock\n");
     79 			exit(PTS_UNRESOLVED);
     80 		}
     81 	} else {
     82 		printf
     83 		    ("Error in pthread_rwlock_timedwrlock(), error code:%d.\n",
     84 		     rc);
     85 		exit(PTS_UNRESOLVED);
     86 	}
     87 
     88 	thread_state = EXITING_THREAD;
     89 	pthread_exit(0);
     90 	return NULL;
     91 }
     92 
     93 int main(void)
     94 {
     95 	int cnt = 0;
     96 	pthread_t thread1;
     97 
     98 	if (pthread_rwlock_init(&rwlock, NULL) != 0) {
     99 		printf("Error at pthread_rwlock_init()\n");
    100 		return PTS_UNRESOLVED;
    101 	}
    102 
    103 	printf("main: attempt write lock\n");
    104 	/* We have no lock, this write lock should succeed */
    105 	if (pthread_rwlock_wrlock(&rwlock) != 0) {
    106 		printf("Error at pthread_rwlock_wrlock()\n");
    107 		return PTS_UNRESOLVED;
    108 	}
    109 	printf("main: acquired write lock\n");
    110 
    111 	thread_state = NOT_CREATED_THREAD;
    112 	printf("main: create thread\n");
    113 	if (pthread_create(&thread1, NULL, fn, NULL) != 0) {
    114 		printf("Error creating thread\n");
    115 		return PTS_UNRESOLVED;
    116 	}
    117 
    118 	/* If the shared data is not altered by child after 3 seconds,
    119 	   we regard it as blocked */
    120 	/* We expect the thread _NOT_ to block */
    121 	cnt = 0;
    122 	do {
    123 		sleep(1);
    124 	} while (thread_state != EXITING_THREAD && cnt++ < 3);
    125 
    126 	switch (thread_state) {
    127 	case EXITING_THREAD:
    128 		/* the child thread does not block, check the time expired or not */
    129 		if (expired != 1) {
    130 			printf("Test FAILED: abs_timeout should expire\n");
    131 			exit(PTS_FAIL);
    132 		} else
    133 			printf("thread correctly expired and did not wait\n");
    134 		break;
    135 	case ENTERED_THREAD:
    136 		printf
    137 		    ("Test FAILED: thread blocked even when the timer expired\n");
    138 		exit(PTS_FAIL);
    139 		break;
    140 	default:
    141 		printf("Unexpected thread state %d\n", thread_state);
    142 		exit(PTS_UNRESOLVED);
    143 		break;
    144 	}
    145 
    146 	printf("main: unlock write lock\n");
    147 	if (pthread_rwlock_unlock(&rwlock) != 0) {
    148 		printf("main: Error at pthread_rwlock_unlock()\n");
    149 		return PTS_UNRESOLVED;
    150 	}
    151 
    152 	if (pthread_join(thread1, NULL) != 0) {
    153 		printf("main: Error at pthread_join()\n");
    154 		return PTS_UNRESOLVED;
    155 	}
    156 
    157 	if (pthread_rwlock_destroy(&rwlock) != 0) {
    158 		printf("main: Error at pthread_rwlockattr_destroy()\n");
    159 		return PTS_UNRESOLVED;
    160 	}
    161 
    162 	printf("Test PASSED\n");
    163 	return PTS_PASS;
    164 }
    165