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  *	Under no circumstances shall the function fail with a timeout if the lock can be
     10  *	acquired immediately. The abs_timeout parameter need not be checked if the lock
     11  *	can be immediately acquired.
     12  *
     13  * Steps:
     14  * 1.  Main thread create a thread.
     15  * 2.  Child thread lock 'rwlock' for writing with pthread_rwlock_timedwrlock(),
     16  *	should not fail with timeout
     17  * 3.  The child thread unlocks the 'rwlock' and exit.
     18  * 4.  Main thread create another thread.
     19  * 5.  The child thread lock 'rwlock' for write, with pthread_rwlock_timedwrlock(),
     20  *	specifying a 'abs_timeout'. The thread sleeps untile 'abs_timeout' expires.
     21  * 6.  The thread call pthread_rwlock_timedwrlock(). Should not get ETIMEDOUT.
     22  */
     23 
     24 #define _XOPEN_SOURCE 600
     25 #include <pthread.h>
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <unistd.h>
     29 #include <errno.h>
     30 #include "posixtest.h"
     31 
     32 #define TIMEOUT 1
     33 
     34 static int thread_state;
     35 static int currsec1;
     36 static int expired;
     37 
     38 /* thread_state indicates child thread state:
     39 	1: not in child thread yet;
     40 	2: just enter child thread ;
     41 	3: just before child thread exit;
     42 */
     43 
     44 #define NOT_CREATED_THREAD 1
     45 #define ENTERED_THREAD 2
     46 #define EXITING_THREAD 3
     47 
     48 static void *fn_wr_1(void *arg)
     49 {
     50 	thread_state = ENTERED_THREAD;
     51 	struct timespec abs_timeout;
     52 	int rc;
     53 	pthread_rwlock_t rwlock;
     54 
     55 	if (pthread_rwlock_init(&rwlock, NULL) != 0) {
     56 		printf("thread1: Error at pthread_rwlock_init\n");
     57 		exit(PTS_UNRESOLVED);
     58 	}
     59 
     60 	currsec1 = time(NULL);
     61 
     62 	/* Absolute time, not relative. */
     63 	abs_timeout.tv_sec = currsec1 + TIMEOUT;
     64 	abs_timeout.tv_nsec = 0;
     65 
     66 	printf("thread1: attempt timed lock for writing\n");
     67 	rc = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout);
     68 	if (rc == ETIMEDOUT) {
     69 		printf("thread1: timer expired\n");
     70 		expired = 1;
     71 	} else if (rc == 0) {
     72 		printf("thread1: acquired write lock\n");
     73 		expired = 0;
     74 		printf("thread1: unlock write lock\n");
     75 		if (pthread_rwlock_unlock(&rwlock) != 0) {
     76 			printf("thread1: failed to release write lock\n");
     77 			exit(PTS_UNRESOLVED);
     78 		}
     79 	} else {
     80 		printf("thread1: Error in pthread_rwlock_timedwrlock().\n");
     81 		exit(PTS_UNRESOLVED);
     82 	}
     83 
     84 	if (pthread_rwlock_destroy(&rwlock) != 0) {
     85 		printf("thread1: Error at pthread_rwlockattr_destroy()");
     86 		exit(PTS_UNRESOLVED);
     87 	}
     88 	thread_state = EXITING_THREAD;
     89 	pthread_exit(0);
     90 	return NULL;
     91 }
     92 
     93 static void *fn_wr_2(void *arg)
     94 {
     95 	thread_state = ENTERED_THREAD;
     96 	struct timespec abs_timeout;
     97 	int rc;
     98 	pthread_rwlock_t rwlock;
     99 
    100 	if (pthread_rwlock_init(&rwlock, NULL) != 0) {
    101 		printf("thread2: Error at pthread_rwlock_init\n");
    102 		exit(PTS_UNRESOLVED);
    103 	}
    104 	currsec1 = time(NULL);
    105 
    106 	/* Absolute time, not relative. */
    107 	abs_timeout.tv_sec = currsec1 - TIMEOUT;
    108 	abs_timeout.tv_nsec = 0;
    109 
    110 	printf("thread2: attempt timed lock for writing\n");
    111 	rc = pthread_rwlock_timedwrlock(&rwlock, &abs_timeout);
    112 	if (rc == ETIMEDOUT) {
    113 		printf("thread2: timer expired\n");
    114 		expired = 1;
    115 	} else if (rc == 0) {
    116 		printf("thread2: acquired write lock\n");
    117 		expired = 0;
    118 		printf("thread2: unlock write lock\n");
    119 		if (pthread_rwlock_unlock(&rwlock) != 0) {
    120 			printf("thread2: failed to release write lock\n");
    121 			exit(PTS_UNRESOLVED);
    122 		}
    123 	} else {
    124 		printf("thread2: Error in pthread_rwlock_timedwrlock().\n");
    125 		exit(PTS_UNRESOLVED);
    126 	}
    127 
    128 	if (pthread_rwlock_destroy(&rwlock) != 0) {
    129 		printf("thread2: Error at pthread_rwlock_destroy()\n");
    130 		exit(PTS_UNRESOLVED);
    131 	}
    132 	thread_state = EXITING_THREAD;
    133 	pthread_exit(0);
    134 	return NULL;
    135 }
    136 
    137 int main(void)
    138 {
    139 	int cnt = 0;
    140 
    141 	pthread_t thread1, thread2;
    142 
    143 	thread_state = NOT_CREATED_THREAD;
    144 	printf("main: create thread1\n");
    145 	if (pthread_create(&thread1, NULL, fn_wr_1, NULL) != 0) {
    146 		printf("Error when creating thread1\n");
    147 		return PTS_UNRESOLVED;
    148 	}
    149 
    150 	/* If the shared data is not altered by child after 5 seconds,
    151 	   we regard it as blocked */
    152 	/* we expect thread1 NOT to block */
    153 	cnt = 0;
    154 	do {
    155 		sleep(1);
    156 	} while (thread_state != 3 && cnt++ < 5);
    157 
    158 	if (thread_state == 3) {
    159 		/* the child thread does not block, check the time expired or not */
    160 		if (expired == 1) {
    161 			printf
    162 			    ("Test FAILED: thread1 got ETIMEOUT when get the lock\n");
    163 			return PTS_FAIL;
    164 		}
    165 	} else if (thread_state == ENTERED_THREAD) {
    166 		printf("Test FAILED: thread1 blocked\n");
    167 		return PTS_FAIL;
    168 	} else {
    169 		printf("Unexpected state for thread1 %d\n", thread_state);
    170 		return PTS_UNRESOLVED;
    171 	}
    172 
    173 	if (pthread_join(thread1, NULL) != 0) {
    174 		printf("Error when joining thread1\n");
    175 		return PTS_UNRESOLVED;
    176 	}
    177 
    178 	thread_state = ENTERED_THREAD;
    179 	printf("main: create thread2\n");
    180 	if (pthread_create(&thread2, NULL, fn_wr_2, NULL) != 0) {
    181 		printf("Error when creating thread2\n");
    182 		return PTS_UNRESOLVED;
    183 	}
    184 
    185 	/* If the shared data is not altered by child after 5 seconds,
    186 	   we regard it as blocked */
    187 
    188 	/* we expect thread2 NOT to block */
    189 	cnt = 0;
    190 	do {
    191 		sleep(1);
    192 	} while (thread_state != EXITING_THREAD && cnt++ < 3);
    193 
    194 	if (thread_state == EXITING_THREAD) {
    195 		/* the child thread does not block, check the time expired or not */
    196 		if (expired == 1) {
    197 			printf("Test FAILED: thread2 got ETIMEOUT\n");
    198 			return PTS_FAIL;
    199 		}
    200 	} else if (thread_state == ENTERED_THREAD) {
    201 		printf("Test FAILED: thread2 blocked\n");
    202 		return PTS_FAIL;
    203 	} else {
    204 		printf("Unexpected state for thread2 %d\n", thread_state);
    205 		return PTS_UNRESOLVED;
    206 	}
    207 
    208 	if (pthread_join(thread2, NULL) != 0) {
    209 		printf("Error when join thread2\n");
    210 		return PTS_UNRESOLVED;
    211 	}
    212 
    213 	printf("Test PASSED\n");
    214 	return PTS_PASS;
    215 }
    216