[BZ #2526, BZ #3138, BZ #3143]
[platform/upstream/glibc.git] / nptl / tst-cond22.c
1 #include <pthread.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4
5
6 static pthread_barrier_t b;
7 static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
8 static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
9
10
11 static void
12 cl (void *arg)
13 {
14   pthread_mutex_unlock (&m);
15 }
16
17
18 static void *
19 tf (void *arg)
20 {
21   if (pthread_mutex_lock (&m) != 0)
22     {
23       printf ("%s: mutex_lock failed\n", __func__);
24       exit (1);
25     }
26   int e = pthread_barrier_wait (&b);
27   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
28     {
29       printf ("%s: barrier_wait failed\n", __func__);
30       exit (1);
31     }
32   pthread_cleanup_push (cl, NULL);
33   /* We have to loop here because the cancellation might come after
34      the cond_wait call left the cancelable area and is then waiting
35      on the mutex.  In this case the beginning of the second cond_wait
36      call will cause the cancellation to happen.  */
37   while (1)
38     {
39       if (pthread_cond_wait (&c, &m) != 0)
40         {
41           printf ("%s: cond_wait failed\n", __func__);
42           exit (1);
43         }
44       if (pthread_mutex_unlock (&m) != 0)
45         {
46           printf ("%s: mutex_unlock failed\n", __func__);
47           exit (1);
48         }
49     }
50   pthread_cleanup_pop (0);
51   return NULL;
52 }
53
54
55 static int
56 do_test (void)
57 {
58   int status = 0;
59
60   if (pthread_barrier_init (&b, NULL, 2) != 0)
61     {
62       puts ("barrier_init failed");
63       return 1;
64     }
65
66   pthread_t th;
67   if (pthread_create (&th, NULL, tf, NULL) != 0)
68     {
69       puts ("1st create failed");
70       return 1;
71     }
72   int e = pthread_barrier_wait (&b);
73   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
74     {
75       puts ("1st barrier_wait failed");
76       return 1;
77     }
78   if (pthread_mutex_lock (&m) != 0)
79     {
80       puts ("1st mutex_lock failed");
81       return 1;
82     }
83   if (pthread_cond_signal (&c) != 0)
84     {
85       puts ("1st cond_signal failed");
86       return 1;
87     }
88   if (pthread_cancel (th) != 0)
89     {
90       puts ("cancel failed");
91       return 1;
92     }
93   if (pthread_mutex_unlock (&m) != 0)
94     {
95       puts ("1st mutex_unlock failed");
96       return 1;
97     }
98   void *res;
99   if (pthread_join (th, &res) != 0)
100     {
101       puts ("1st join failed");
102       return 1;
103     }
104   if (res != PTHREAD_CANCELED)
105     {
106       puts ("first thread not canceled");
107       status = 1;
108     }
109
110   printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
111           c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
112           c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
113           c.__data.__nwaiters, c.__data.__broadcast_seq);
114
115   if (pthread_create (&th, NULL, tf, NULL) != 0)
116     {
117       puts ("2nd create failed");
118       return 1;
119     }
120   e = pthread_barrier_wait (&b);
121   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
122     {
123       puts ("2nd barrier_wait failed");
124       return 1;
125     }
126   if (pthread_mutex_lock (&m) != 0)
127     {
128       puts ("2nd mutex_lock failed");
129       return 1;
130     }
131   if (pthread_cond_signal (&c) != 0)
132     {
133       puts ("2nd cond_signal failed");
134       return 1;
135     }
136   if (pthread_mutex_unlock (&m) != 0)
137     {
138       puts ("2nd mutex_unlock failed");
139       return 1;
140     }
141   if (pthread_join (th, &res) != 0)
142     {
143       puts ("2nd join failed");
144       return 1;
145     }
146   if (res != NULL)
147     {
148       puts ("2nd thread canceled");
149       status = 1;
150     }
151
152   printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
153           c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
154           c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
155           c.__data.__nwaiters, c.__data.__broadcast_seq);
156
157   return status;
158 }
159
160 #define TEST_FUNCTION do_test ()
161 #include "../test-skeleton.c"