Add POSIX test suite 1.5.2 (http://sourceforge.net/projects/posixtest/).
[dragonfly.git] / test / contrib / posixtestsuite-1.5.2 / conformance / interfaces / pthread_rwlock_wrlock / 2-1.c
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
31 static pthread_t sig_thread;
32 static 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
44 static int thread_state;
45 static int handler_called;
46
47 static 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
60 static 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
93 int 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 }