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 (mutex: &m); |
15 | } |
16 | |
17 | |
18 | static void * |
19 | tf (void *arg) |
20 | { |
21 | if (pthread_mutex_lock (mutex: &m) != 0) |
22 | { |
23 | printf (format: "%s: mutex_lock failed\n" , __func__); |
24 | exit (1); |
25 | } |
26 | int e = pthread_barrier_wait (barrier: &b); |
27 | if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) |
28 | { |
29 | printf (format: "%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 | do |
38 | if (pthread_cond_wait (cond: &c, mutex: &m) != 0) |
39 | { |
40 | printf (format: "%s: cond_wait failed\n" , __func__); |
41 | exit (1); |
42 | } |
43 | while (arg == NULL); |
44 | pthread_cleanup_pop (0); |
45 | if (pthread_mutex_unlock (mutex: &m) != 0) |
46 | { |
47 | printf (format: "%s: mutex_unlock failed\n" , __func__); |
48 | exit (1); |
49 | } |
50 | return NULL; |
51 | } |
52 | |
53 | |
54 | static int |
55 | do_test (void) |
56 | { |
57 | int status = 0; |
58 | |
59 | if (pthread_barrier_init (barrier: &b, NULL, count: 2) != 0) |
60 | { |
61 | puts (s: "barrier_init failed" ); |
62 | return 1; |
63 | } |
64 | |
65 | pthread_t th; |
66 | if (pthread_create (newthread: &th, NULL, start_routine: tf, NULL) != 0) |
67 | { |
68 | puts (s: "1st create failed" ); |
69 | return 1; |
70 | } |
71 | int e = pthread_barrier_wait (barrier: &b); |
72 | if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) |
73 | { |
74 | puts (s: "1st barrier_wait failed" ); |
75 | return 1; |
76 | } |
77 | if (pthread_mutex_lock (mutex: &m) != 0) |
78 | { |
79 | puts (s: "1st mutex_lock failed" ); |
80 | return 1; |
81 | } |
82 | if (pthread_cond_signal (cond: &c) != 0) |
83 | { |
84 | puts (s: "1st cond_signal failed" ); |
85 | return 1; |
86 | } |
87 | if (pthread_cancel (th: th) != 0) |
88 | { |
89 | puts (s: "cancel failed" ); |
90 | return 1; |
91 | } |
92 | if (pthread_mutex_unlock (mutex: &m) != 0) |
93 | { |
94 | puts (s: "1st mutex_unlock failed" ); |
95 | return 1; |
96 | } |
97 | void *res; |
98 | if (pthread_join (th: th, thread_return: &res) != 0) |
99 | { |
100 | puts (s: "1st join failed" ); |
101 | return 1; |
102 | } |
103 | if (res != PTHREAD_CANCELED) |
104 | { |
105 | puts (s: "first thread not canceled" ); |
106 | status = 1; |
107 | } |
108 | |
109 | printf (format: "cond = { 0x%x:%x, 0x%x:%x, %u/%u/%u, %u/%u/%u, %u, %u }\n" , |
110 | c.__data.__wseq.__value32.__high, |
111 | c.__data.__wseq.__value32.__low, |
112 | c.__data.__g1_start.__value32.__high, |
113 | c.__data.__g1_start.__value32.__low, |
114 | c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0], |
115 | c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1], |
116 | c.__data.__g1_orig_size, c.__data.__wrefs); |
117 | |
118 | if (pthread_create (newthread: &th, NULL, start_routine: tf, arg: (void *) 1l) != 0) |
119 | { |
120 | puts (s: "2nd create failed" ); |
121 | return 1; |
122 | } |
123 | e = pthread_barrier_wait (barrier: &b); |
124 | if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) |
125 | { |
126 | puts (s: "2nd barrier_wait failed" ); |
127 | return 1; |
128 | } |
129 | if (pthread_mutex_lock (mutex: &m) != 0) |
130 | { |
131 | puts (s: "2nd mutex_lock failed" ); |
132 | return 1; |
133 | } |
134 | if (pthread_cond_signal (cond: &c) != 0) |
135 | { |
136 | puts (s: "2nd cond_signal failed" ); |
137 | return 1; |
138 | } |
139 | if (pthread_mutex_unlock (mutex: &m) != 0) |
140 | { |
141 | puts (s: "2nd mutex_unlock failed" ); |
142 | return 1; |
143 | } |
144 | if (pthread_join (th: th, thread_return: &res) != 0) |
145 | { |
146 | puts (s: "2nd join failed" ); |
147 | return 1; |
148 | } |
149 | if (res != NULL) |
150 | { |
151 | puts (s: "2nd thread canceled" ); |
152 | status = 1; |
153 | } |
154 | |
155 | printf (format: "cond = { 0x%x:%x, 0x%x:%x, %u/%u/%u, %u/%u/%u, %u, %u }\n" , |
156 | c.__data.__wseq.__value32.__high, |
157 | c.__data.__wseq.__value32.__low, |
158 | c.__data.__g1_start.__value32.__high, |
159 | c.__data.__g1_start.__value32.__low, |
160 | c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0], |
161 | c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1], |
162 | c.__data.__g1_orig_size, c.__data.__wrefs); |
163 | |
164 | return status; |
165 | } |
166 | |
167 | #define TEST_FUNCTION do_test () |
168 | #include "../test-skeleton.c" |
169 | |