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 * Test pthread_rwlock_wrlock(pthread_rwlock_t * rwlock) 7 * 8 * If a signal is delivered to a thread waiting for a read-write lock for writing, upon 9 * return from the signal handler the thread resumes waiting for the read-write lock for 10 * writing as if it was not interrupted. 11 * 12 * Steps: 13 * 1. main thread create read-write lock 'rwlock', and lock it for writing 14 * 2. main thread create a thread sig_thread, the thread is set to handle SIGUSR1 15 * 3. sig_thread try to lock 'rwlock' for writing but blocked 16 * 4. main thread send SIGUSR1 to sig_thread via pthread_kill, while sig_thread is blocking 17 * 5. test that thread handler is called 18 * 6. check that when thread handler returns, sig_thread resume block 19 * 7. main thread unlock 'rwlock', sig_thread should get the lock 20 */ 21 22#define _XOPEN_SOURCE 600 23#include <pthread.h> 24#include <stdio.h> 25#include <stdlib.h> 26#include <signal.h> 27#include <errno.h> 28#include <unistd.h> 29#include "posixtest.h" 30 31static pthread_t sig_thread; 32static pthread_rwlock_t rwlock; 33 34/* thread_state indicates child thread state: 35 1: not in child thread yet; 36 2: just enter child thread ; 37 3: just before child thread exit; 38*/ 39 40#define NOT_CREATED_THREAD 1 41#define ENTERED_THREAD 2 42#define EXITING_THREAD 3 43 44static int thread_state; 45static int handler_called; 46 47static void sig_handler() { 48 if(pthread_equal(pthread_self(), sig_thread)) 49 { 50 printf("sig_handler: handled signal SIGUSR1\n"); 51 handler_called = 1; 52 } 53 else 54 { 55 printf("signal was not handled by sig_thread\n"); 56 exit(PTS_UNRESOLVED); 57 } 58} 59 60static void * th_fn(void *arg) 61{ 62 struct sigaction act; 63 int rc = 0; 64 65 /* Set up signal handler for SIGUSR1 */ 66 act.sa_flags = 0; 67 act.sa_handler = sig_handler; 68 /* block all the signal while handling SIGUSR1 */ 69 sigfillset(&act.sa_mask); 70 sigaction(SIGUSR1, &act, NULL); 71 72 thread_state = ENTERED_THREAD; 73 printf("sig_thread: attempt write lock\n"); 74 rc = pthread_rwlock_wrlock(&rwlock); 75 if(rc != 0) 76 { 77 printf("Test FAILED: sig_thread: Error at pthread_rwlock_wrlock(), error code:%d\n", rc); 78 exit(PTS_FAIL); 79 } 80 81 printf("sig_thread: acquired write lock\n"); 82 printf("sig_thread: unlock write lock\n"); 83 if(pthread_rwlock_unlock(&rwlock) != 0) 84 { 85 printf("sig_thread: Error at pthread_rwlock_unlock()\n"); 86 exit(PTS_UNRESOLVED); 87 } 88 thread_state = EXITING_THREAD; 89 pthread_exit(0); 90 return NULL; 91} 92 93int main() 94{ 95 int cnt; 96 int rc = 0; 97 handler_called=0; 98 99 if(pthread_rwlock_init(&rwlock, NULL) != 0) 100 { 101 printf("Error at pthread_rwlock_init()\n"); 102 return PTS_UNRESOLVED; 103 } 104 105 printf("main: attempt write lock\n"); 106 rc = pthread_rwlock_wrlock(&rwlock); 107 if(rc != 0) 108 { 109 printf("main: Error at pthread_rwlock_wrlock(), error code:%d\n", rc); 110 return PTS_UNRESOLVED; 111 } 112 113 thread_state = NOT_CREATED_THREAD; 114 if(pthread_create(&sig_thread, NULL, th_fn, NULL) != 0) 115 { 116 printf("Error at pthread_create()\n"); 117 return PTS_UNRESOLVED; 118 } 119 120 /* wait at most 3 seconds for sig_thread to block*/ 121 cnt = 0; 122 do{ 123 sleep(1); 124 }while(thread_state != EXITING_THREAD && cnt++ < 3); 125 126 if(thread_state == EXITING_THREAD) 127 { 128 /* the sig_thread is not blocking*/ 129 printf("Test FAILED: the thread should block when getting write lock\n"); 130 exit(PTS_FAIL); 131 } 132 else if(thread_state != ENTERED_THREAD) 133 { 134 printf("sig_thread in unexpected state %d\n", thread_state); 135 exit(PTS_UNRESOLVED); 136 } 137 138 /* sig_thread is blocking */ 139 printf("main: fire SIGUSR1 to sig_thread\n"); 140 if(pthread_kill(sig_thread, SIGUSR1) != 0) 141 { 142 printf("Error at pthread_kill()\n"); 143 exit(PTS_UNRESOLVED); 144 } 145 146 /* wait at most 3 seconds for the singal to be handled */ 147 cnt = 0; 148 do{ 149 sleep(1); 150 }while(handler_called == 0 && cnt++ < 3); 151 152 if(handler_called != 1) 153 { 154 printf("The signal handler did not get called.\n"); 155 exit(PTS_UNRESOLVED); 156 } 157 158 /* sig_thread resume to block? */ 159 cnt = 0; 160 do{ 161 sleep(1); 162 }while(thread_state != EXITING_THREAD && cnt++ < 3); 163 164 if(thread_state == 3) 165 { 166 printf("Test FAILED: upon return from signal handler, sig_thread does not resume to wait\n"); 167 exit(PTS_FAIL); 168 } 169 170 printf("sig_thread: correctly still blocking after signal handler returns\n"); 171 printf("main: unlock write lock\n"); 172 if(pthread_rwlock_unlock(&rwlock) != 0) 173 { 174 printf("main: Error releasing write lock\n"); 175 exit(PTS_UNRESOLVED); 176 } 177 178 /* sig_thread should get write lock */ 179 cnt = 0; 180 do{ 181 sleep(1); 182 }while(thread_state != EXITING_THREAD && cnt++ < 3); 183 184 if(thread_state != EXITING_THREAD) 185 { 186 /* sig_thread does not unblock */ 187 printf("Test FAILED: sig_thread should get the write lock and exit\n"); 188 exit(PTS_FAIL); 189 } 190 191 if(pthread_join(sig_thread, NULL) != 0) 192 { 193 printf("Error at pthread_join()\n"); 194 exit(PTS_UNRESOLVED); 195 } 196 197 if(pthread_rwlock_destroy(&rwlock) != 0) 198 { 199 printf("pthread_rwlock_destroy()\n"); 200 exit(PTS_UNRESOLVED); 201 } 202 203 printf("Test PASSED\n"); 204 return PTS_PASS; 205} 206 207 208