This source file includes following definitions.
- random_account
- check_accounts
- lock_mutator_thread
- lock_checker_thread
- test_pthread_mutex_normal
- recshuffle
- reclock_mutator_thread
- reclock_checker_thread
- test_pthread_mutex_recursive
- 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
31 #define DO_TEST_LOCK 1
32 #define DO_TEST_RECURSIVE_LOCK 1
33
34
35
36 #define EXPLICIT_YIELD 1
37
38
39 #define ENABLE_DEBUGGING 0
40
41
42 #define THREAD_COUNT 10
43
44
45
46
47 #define REPEAT_COUNT 50000
48
49 #include <pthread.h>
50 #include <stdint.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54
55 #if EXPLICIT_YIELD
56 # include <sched.h>
57 #endif
58
59 #if HAVE_DECL_ALARM
60 # include <signal.h>
61 # include <unistd.h>
62 #endif
63
64 #include "macros.h"
65 #include "atomic-int-posix.h"
66
67 #if ENABLE_DEBUGGING
68 # define dbgprintf printf
69 #else
70 # define dbgprintf if (0) printf
71 #endif
72
73 #if EXPLICIT_YIELD
74 # define yield() sched_yield ()
75 #else
76 # define yield()
77 #endif
78
79
80 #if defined __MVS__
81
82
83
84 # define pthread_self_pointer() (*((void **) pthread_self ().__))
85 #else
86 # define pthread_self_pointer() ((void *) (uintptr_t) pthread_self ())
87 #endif
88
89 #define ACCOUNT_COUNT 4
90
91 static int account[ACCOUNT_COUNT];
92
93 static int
94 random_account (void)
95 {
96 return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
97 }
98
99 static void
100 check_accounts (void)
101 {
102 int i, sum;
103
104 sum = 0;
105 for (i = 0; i < ACCOUNT_COUNT; i++)
106 sum += account[i];
107 if (sum != ACCOUNT_COUNT * 1000)
108 abort ();
109 }
110
111
112
113
114
115
116
117
118 static pthread_mutex_t my_lock;
119
120 static void *
121 lock_mutator_thread (void *arg)
122 {
123 int repeat;
124
125 for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
126 {
127 int i1, i2, value;
128
129 dbgprintf ("Mutator %p before lock\n", pthread_self_pointer ());
130 ASSERT (pthread_mutex_lock (&my_lock) == 0);
131 dbgprintf ("Mutator %p after lock\n", pthread_self_pointer ());
132
133 i1 = random_account ();
134 i2 = random_account ();
135 value = ((unsigned int) rand () >> 3) % 10;
136 account[i1] += value;
137 account[i2] -= value;
138
139 dbgprintf ("Mutator %p before unlock\n", pthread_self_pointer ());
140 ASSERT (pthread_mutex_unlock (&my_lock) == 0);
141 dbgprintf ("Mutator %p after unlock\n", pthread_self_pointer ());
142
143 dbgprintf ("Mutator %p before check lock\n", pthread_self_pointer ());
144 ASSERT (pthread_mutex_lock (&my_lock) == 0);
145 check_accounts ();
146 ASSERT (pthread_mutex_unlock (&my_lock) == 0);
147 dbgprintf ("Mutator %p after check unlock\n", pthread_self_pointer ());
148
149 yield ();
150 }
151
152 dbgprintf ("Mutator %p dying.\n", pthread_self_pointer ());
153 return NULL;
154 }
155
156 static struct atomic_int lock_checker_done;
157
158 static void *
159 lock_checker_thread (void *arg)
160 {
161 while (get_atomic_int_value (&lock_checker_done) == 0)
162 {
163 dbgprintf ("Checker %p before check lock\n", pthread_self_pointer ());
164 ASSERT (pthread_mutex_lock (&my_lock) == 0);
165 check_accounts ();
166 ASSERT (pthread_mutex_unlock (&my_lock) == 0);
167 dbgprintf ("Checker %p after check unlock\n", pthread_self_pointer ());
168
169 yield ();
170 }
171
172 dbgprintf ("Checker %p dying.\n", pthread_self_pointer ());
173 return NULL;
174 }
175
176 static void
177 test_pthread_mutex_normal (void)
178 {
179 int i;
180 pthread_t checkerthread;
181 pthread_t threads[THREAD_COUNT];
182
183
184 for (i = 0; i < ACCOUNT_COUNT; i++)
185 account[i] = 1000;
186 init_atomic_int (&lock_checker_done);
187 set_atomic_int_value (&lock_checker_done, 0);
188
189
190 ASSERT (pthread_create (&checkerthread, NULL, lock_checker_thread, NULL)
191 == 0);
192 for (i = 0; i < THREAD_COUNT; i++)
193 ASSERT (pthread_create (&threads[i], NULL, lock_mutator_thread, NULL) == 0);
194
195
196 for (i = 0; i < THREAD_COUNT; i++)
197 ASSERT (pthread_join (threads[i], NULL) == 0);
198 set_atomic_int_value (&lock_checker_done, 1);
199 ASSERT (pthread_join (checkerthread, NULL) == 0);
200 check_accounts ();
201 }
202
203
204
205
206
207
208
209
210 static pthread_mutex_t my_reclock;
211
212 static void
213 recshuffle (void)
214 {
215 int i1, i2, value;
216
217 dbgprintf ("Mutator %p before lock\n", pthread_self_pointer ());
218 ASSERT (pthread_mutex_lock (&my_reclock) == 0);
219 dbgprintf ("Mutator %p after lock\n", pthread_self_pointer ());
220
221 i1 = random_account ();
222 i2 = random_account ();
223 value = ((unsigned int) rand () >> 3) % 10;
224 account[i1] += value;
225 account[i2] -= value;
226
227
228 if (((unsigned int) rand () >> 3) % 2)
229 recshuffle ();
230
231 dbgprintf ("Mutator %p before unlock\n", pthread_self_pointer ());
232 ASSERT (pthread_mutex_unlock (&my_reclock) == 0);
233 dbgprintf ("Mutator %p after unlock\n", pthread_self_pointer ());
234 }
235
236 static void *
237 reclock_mutator_thread (void *arg)
238 {
239 int repeat;
240
241 for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
242 {
243 recshuffle ();
244
245 dbgprintf ("Mutator %p before check lock\n", pthread_self_pointer ());
246 ASSERT (pthread_mutex_lock (&my_reclock) == 0);
247 check_accounts ();
248 ASSERT (pthread_mutex_unlock (&my_reclock) == 0);
249 dbgprintf ("Mutator %p after check unlock\n", pthread_self_pointer ());
250
251 yield ();
252 }
253
254 dbgprintf ("Mutator %p dying.\n", pthread_self_pointer ());
255 return NULL;
256 }
257
258 static struct atomic_int reclock_checker_done;
259
260 static void *
261 reclock_checker_thread (void *arg)
262 {
263 while (get_atomic_int_value (&reclock_checker_done) == 0)
264 {
265 dbgprintf ("Checker %p before check lock\n", pthread_self_pointer ());
266 ASSERT (pthread_mutex_lock (&my_reclock) == 0);
267 check_accounts ();
268 ASSERT (pthread_mutex_unlock (&my_reclock) == 0);
269 dbgprintf ("Checker %p after check unlock\n", pthread_self_pointer ());
270
271 yield ();
272 }
273
274 dbgprintf ("Checker %p dying.\n", pthread_self_pointer ());
275 return NULL;
276 }
277
278 static void
279 test_pthread_mutex_recursive (void)
280 {
281 int i;
282 pthread_t checkerthread;
283 pthread_t threads[THREAD_COUNT];
284
285
286 for (i = 0; i < ACCOUNT_COUNT; i++)
287 account[i] = 1000;
288 init_atomic_int (&reclock_checker_done);
289 set_atomic_int_value (&reclock_checker_done, 0);
290
291
292 ASSERT (pthread_create (&checkerthread, NULL, reclock_checker_thread, NULL)
293 == 0);
294 for (i = 0; i < THREAD_COUNT; i++)
295 ASSERT (pthread_create (&threads[i], NULL, reclock_mutator_thread, NULL)
296 == 0);
297
298
299 for (i = 0; i < THREAD_COUNT; i++)
300 ASSERT (pthread_join (threads[i], NULL) == 0);
301 set_atomic_int_value (&reclock_checker_done, 1);
302 ASSERT (pthread_join (checkerthread, NULL) == 0);
303 check_accounts ();
304 }
305
306
307
308
309 int
310 main ()
311 {
312 #if HAVE_DECL_ALARM
313
314
315 int alarm_value = 600;
316 signal (SIGALRM, SIG_DFL);
317 alarm (alarm_value);
318 #endif
319
320 {
321 pthread_mutexattr_t attr;
322
323 ASSERT (pthread_mutexattr_init (&attr) == 0);
324 ASSERT (pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL) == 0);
325 ASSERT (pthread_mutex_init (&my_lock, &attr) == 0);
326 ASSERT (pthread_mutexattr_destroy (&attr) == 0);
327 }
328
329 {
330 pthread_mutexattr_t attr;
331
332 ASSERT (pthread_mutexattr_init (&attr) == 0);
333 ASSERT (pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE) == 0);
334 ASSERT (pthread_mutex_init (&my_reclock, &attr) == 0);
335 ASSERT (pthread_mutexattr_destroy (&attr) == 0);
336 }
337
338 #if DO_TEST_LOCK
339 printf ("Starting test_pthread_mutex_normal ..."); fflush (stdout);
340 test_pthread_mutex_normal ();
341 printf (" OK\n"); fflush (stdout);
342 #endif
343 #if DO_TEST_RECURSIVE_LOCK
344 printf ("Starting test_pthread_mutex_recursive ..."); fflush (stdout);
345 test_pthread_mutex_recursive ();
346 printf (" OK\n"); fflush (stdout);
347 #endif
348
349 return 0;
350 }
351
352 #else
353
354
355
356 #include <stdio.h>
357
358 int
359 main ()
360 {
361 fputs ("Skipping test: multithreading not enabled\n", stderr);
362 return 77;
363 }
364
365 #endif