This source file includes following definitions.
- once_execute
- once_contender_thread
- test_once
- main
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21 #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
22
23
24
25
26 #define ENABLE_LOCKING 1
27
28
29
30 #define EXPLICIT_YIELD 1
31
32
33 #define ENABLE_DEBUGGING 0
34
35
36 #define THREAD_COUNT 10
37
38
39
40
41 #define REPEAT_COUNT 50000
42
43 #include <pthread.h>
44 #include <stdint.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48
49 #if EXPLICIT_YIELD
50 # include <sched.h>
51 #endif
52
53 #if HAVE_DECL_ALARM
54 # include <signal.h>
55 # include <unistd.h>
56 #endif
57
58 #include "macros.h"
59
60 #if ENABLE_DEBUGGING
61 # define dbgprintf printf
62 #else
63 # define dbgprintf if (0) printf
64 #endif
65
66 #if EXPLICIT_YIELD
67 # define yield() sched_yield ()
68 #else
69 # define yield()
70 #endif
71
72
73 #if defined __MVS__
74
75
76
77 # define pthread_self_pointer() (*((void **) pthread_self ().__))
78 #else
79 # define pthread_self_pointer() ((void *) (uintptr_t) pthread_self ())
80 #endif
81
82
83
84
85
86
87
88 static pthread_once_t fresh_once = PTHREAD_ONCE_INIT;
89 static int ready[THREAD_COUNT];
90 static pthread_mutex_t ready_lock[THREAD_COUNT];
91 #if ENABLE_LOCKING
92 static pthread_rwlock_t fire_signal[REPEAT_COUNT];
93 #else
94 static volatile int fire_signal_state;
95 #endif
96 static pthread_once_t once_control;
97 static int performed;
98 static pthread_mutex_t performed_lock;
99
100 static void
101 once_execute (void)
102 {
103 ASSERT (pthread_mutex_lock (&performed_lock) == 0);
104 performed++;
105 ASSERT (pthread_mutex_unlock (&performed_lock) == 0);
106 }
107
108 static void *
109 once_contender_thread (void *arg)
110 {
111 int id = (int) (intptr_t) arg;
112 int repeat;
113
114 for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
115 {
116
117 ASSERT (pthread_mutex_lock (&ready_lock[id]) == 0);
118 ready[id] = 1;
119 ASSERT (pthread_mutex_unlock (&ready_lock[id]) == 0);
120
121 if (repeat == REPEAT_COUNT)
122 break;
123
124 dbgprintf ("Contender %p waiting for signal for round %d\n",
125 pthread_self_pointer (), repeat);
126 #if ENABLE_LOCKING
127
128 ASSERT (pthread_rwlock_rdlock (&fire_signal[repeat]) == 0);
129
130 ASSERT (pthread_rwlock_unlock (&fire_signal[repeat]) == 0);
131 #else
132
133 while (fire_signal_state <= repeat)
134 yield ();
135 #endif
136 dbgprintf ("Contender %p got the signal for round %d\n",
137 pthread_self_pointer (), repeat);
138
139
140 ASSERT (pthread_once (&once_control, once_execute) == 0);
141 }
142
143 return NULL;
144 }
145
146 static void
147 test_once (void)
148 {
149 int i, repeat;
150 pthread_t threads[THREAD_COUNT];
151
152
153 for (i = 0; i < THREAD_COUNT; i++)
154 {
155 pthread_mutexattr_t attr;
156
157 ready[i] = 0;
158 ASSERT (pthread_mutexattr_init (&attr) == 0);
159 ASSERT (pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL) == 0);
160 ASSERT (pthread_mutex_init (&ready_lock[i], &attr) == 0);
161 ASSERT (pthread_mutexattr_destroy (&attr) == 0);
162 }
163 #if ENABLE_LOCKING
164 for (i = 0; i < REPEAT_COUNT; i++)
165 ASSERT (pthread_rwlock_init (&fire_signal[i], NULL) == 0);
166 #else
167 fire_signal_state = 0;
168 #endif
169
170 #if ENABLE_LOCKING
171
172 for (i = REPEAT_COUNT-1; i >= 0; i--)
173 ASSERT (pthread_rwlock_wrlock (&fire_signal[i]) == 0);
174 #endif
175
176
177 for (i = 0; i < THREAD_COUNT; i++)
178 ASSERT (pthread_create (&threads[i], NULL,
179 once_contender_thread, (void *) (intptr_t) i)
180 == 0);
181
182 for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
183 {
184
185 dbgprintf ("Main thread before synchronizing for round %d\n", repeat);
186 for (;;)
187 {
188 int ready_count = 0;
189 for (i = 0; i < THREAD_COUNT; i++)
190 {
191 ASSERT (pthread_mutex_lock (&ready_lock[i]) == 0);
192 ready_count += ready[i];
193 ASSERT (pthread_mutex_unlock (&ready_lock[i]) == 0);
194 }
195 if (ready_count == THREAD_COUNT)
196 break;
197 yield ();
198 }
199 dbgprintf ("Main thread after synchronizing for round %d\n", repeat);
200
201 if (repeat > 0)
202 {
203
204
205 if (performed != 1)
206 abort ();
207 }
208
209 if (repeat == REPEAT_COUNT)
210 break;
211
212
213 memcpy (&once_control, &fresh_once, sizeof (pthread_once_t));
214
215
216 performed = 0;
217
218
219 for (i = 0; i < THREAD_COUNT; i++)
220 {
221 ASSERT (pthread_mutex_lock (&ready_lock[i]) == 0);
222 ready[i] = 0;
223 ASSERT (pthread_mutex_unlock (&ready_lock[i]) == 0);
224 }
225
226
227 dbgprintf ("Main thread giving signal for round %d\n", repeat);
228 #if ENABLE_LOCKING
229 ASSERT (pthread_rwlock_unlock (&fire_signal[repeat]) == 0);
230 #else
231 fire_signal_state = repeat + 1;
232 #endif
233 }
234
235
236 for (i = 0; i < THREAD_COUNT; i++)
237 ASSERT (pthread_join (threads[i], NULL) == 0);
238 }
239
240
241
242
243 int
244 main ()
245 {
246 #if HAVE_DECL_ALARM
247
248
249 int alarm_value = 600;
250 signal (SIGALRM, SIG_DFL);
251 alarm (alarm_value);
252 #endif
253
254 {
255 pthread_mutexattr_t attr;
256
257 ASSERT (pthread_mutexattr_init (&attr) == 0);
258 ASSERT (pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL) == 0);
259 ASSERT (pthread_mutex_init (&performed_lock, &attr) == 0);
260 ASSERT (pthread_mutexattr_destroy (&attr) == 0);
261 }
262
263 printf ("Starting test_once ..."); fflush (stdout);
264 test_once ();
265 printf (" OK\n"); fflush (stdout);
266
267 return 0;
268 }
269
270 #else
271
272
273
274 #include <stdio.h>
275
276 int
277 main ()
278 {
279 fputs ("Skipping test: multithreading not enabled\n", stderr);
280 return 77;
281 }
282
283 #endif