This source file includes following definitions.
- random_account
- check_accounts
- gl_lock_define_initialized
- lock_checker_thread
- test_lock
- gl_rwlock_define_initialized
- rwlock_checker_thread
- test_rwlock
- gl_recursive_lock_define_initialized
- reclock_mutator_thread
- reclock_checker_thread
- test_recursive_lock
- gl_once_define
- 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 #if USE_ISOC_THREADS
24 # define TEST_ISOC_THREADS 1
25 #endif
26 #if USE_POSIX_THREADS
27 # define TEST_POSIX_THREADS 1
28 #endif
29 #if USE_ISOC_AND_POSIX_THREADS
30 # define TEST_ISOC_AND_POSIX_THREADS 1
31 #endif
32 #if USE_WINDOWS_THREADS
33 # define TEST_WINDOWS_THREADS 1
34 #endif
35
36
37
38
39 #define ENABLE_LOCKING 1
40
41
42
43
44 #define DO_TEST_LOCK 1
45 #define DO_TEST_RWLOCK 1
46 #define DO_TEST_RECURSIVE_LOCK 1
47 #define DO_TEST_ONCE 1
48
49
50
51 #define EXPLICIT_YIELD 1
52
53
54 #define ENABLE_DEBUGGING 0
55
56
57 #define THREAD_COUNT 10
58
59
60
61
62 #define REPEAT_COUNT 50000
63
64 #include <stdint.h>
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <string.h>
68
69 #if !ENABLE_LOCKING
70 # undef USE_ISOC_THREADS
71 # undef USE_POSIX_THREADS
72 # undef USE_ISOC_AND_POSIX_THREADS
73 # undef USE_WINDOWS_THREADS
74 #endif
75 #include "glthread/lock.h"
76
77 #if !ENABLE_LOCKING
78 # if TEST_ISOC_THREADS
79 # define USE_ISOC_THREADS 1
80 # endif
81 # if TEST_POSIX_THREADS
82 # define USE_POSIX_THREADS 1
83 # endif
84 # if TEST_ISOC_AND_POSIX_THREADS
85 # define USE_ISOC_AND_POSIX_THREADS 1
86 # endif
87 # if TEST_WINDOWS_THREADS
88 # define USE_WINDOWS_THREADS 1
89 # endif
90 #endif
91
92 #include "glthread/thread.h"
93 #include "glthread/yield.h"
94
95 #if HAVE_DECL_ALARM
96 # include <signal.h>
97 # include <unistd.h>
98 #endif
99
100 #include "atomic-int-gnulib.h"
101
102 #if ENABLE_DEBUGGING
103 # define dbgprintf printf
104 #else
105 # define dbgprintf if (0) printf
106 #endif
107
108 #if EXPLICIT_YIELD
109 # define yield() gl_thread_yield ()
110 #else
111 # define yield()
112 #endif
113
114 #define ACCOUNT_COUNT 4
115
116 static int account[ACCOUNT_COUNT];
117
118 static int
119 random_account (void)
120 {
121 return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
122 }
123
124 static void
125 check_accounts (void)
126 {
127 int i, sum;
128
129 sum = 0;
130 for (i = 0; i < ACCOUNT_COUNT; i++)
131 sum += account[i];
132 if (sum != ACCOUNT_COUNT * 1000)
133 abort ();
134 }
135
136
137
138
139
140
141
142
143 gl_lock_define_initialized(static, my_lock)
144
145 static void *
146 lock_mutator_thread (void *arg)
147 {
148 int repeat;
149
150 for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
151 {
152 int i1, i2, value;
153
154 dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ());
155 gl_lock_lock (my_lock);
156 dbgprintf ("Mutator %p after lock\n", gl_thread_self_pointer ());
157
158 i1 = random_account ();
159 i2 = random_account ();
160 value = ((unsigned int) rand () >> 3) % 10;
161 account[i1] += value;
162 account[i2] -= value;
163
164 dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
165 gl_lock_unlock (my_lock);
166 dbgprintf ("Mutator %p after unlock\n", gl_thread_self_pointer ());
167
168 dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ());
169 gl_lock_lock (my_lock);
170 check_accounts ();
171 gl_lock_unlock (my_lock);
172 dbgprintf ("Mutator %p after check unlock\n", gl_thread_self_pointer ());
173
174 yield ();
175 }
176
177 dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
178 return NULL;
179 }
180
181 static struct atomic_int lock_checker_done;
182
183 static void *
184 lock_checker_thread (void *arg)
185 {
186 while (get_atomic_int_value (&lock_checker_done) == 0)
187 {
188 dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
189 gl_lock_lock (my_lock);
190 check_accounts ();
191 gl_lock_unlock (my_lock);
192 dbgprintf ("Checker %p after check unlock\n", gl_thread_self_pointer ());
193
194 yield ();
195 }
196
197 dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
198 return NULL;
199 }
200
201 static void
202 test_lock (void)
203 {
204 int i;
205 gl_thread_t checkerthread;
206 gl_thread_t threads[THREAD_COUNT];
207
208
209 for (i = 0; i < ACCOUNT_COUNT; i++)
210 account[i] = 1000;
211 init_atomic_int (&lock_checker_done);
212 set_atomic_int_value (&lock_checker_done, 0);
213
214
215 checkerthread = gl_thread_create (lock_checker_thread, NULL);
216 for (i = 0; i < THREAD_COUNT; i++)
217 threads[i] = gl_thread_create (lock_mutator_thread, NULL);
218
219
220 for (i = 0; i < THREAD_COUNT; i++)
221 gl_thread_join (threads[i], NULL);
222 set_atomic_int_value (&lock_checker_done, 1);
223 gl_thread_join (checkerthread, NULL);
224 check_accounts ();
225 }
226
227
228
229
230
231
232
233
234 gl_rwlock_define_initialized(static, my_rwlock)
235
236 static void *
237 rwlock_mutator_thread (void *arg)
238 {
239 int repeat;
240
241 for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
242 {
243 int i1, i2, value;
244
245 dbgprintf ("Mutator %p before wrlock\n", gl_thread_self_pointer ());
246 gl_rwlock_wrlock (my_rwlock);
247 dbgprintf ("Mutator %p after wrlock\n", gl_thread_self_pointer ());
248
249 i1 = random_account ();
250 i2 = random_account ();
251 value = ((unsigned int) rand () >> 3) % 10;
252 account[i1] += value;
253 account[i2] -= value;
254
255 dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
256 gl_rwlock_unlock (my_rwlock);
257 dbgprintf ("Mutator %p after unlock\n", gl_thread_self_pointer ());
258
259 yield ();
260 }
261
262 dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
263 return NULL;
264 }
265
266 static struct atomic_int rwlock_checker_done;
267
268 static void *
269 rwlock_checker_thread (void *arg)
270 {
271 while (get_atomic_int_value (&rwlock_checker_done) == 0)
272 {
273 dbgprintf ("Checker %p before check rdlock\n", gl_thread_self_pointer ());
274 gl_rwlock_rdlock (my_rwlock);
275 check_accounts ();
276 gl_rwlock_unlock (my_rwlock);
277 dbgprintf ("Checker %p after check unlock\n", gl_thread_self_pointer ());
278
279 yield ();
280 }
281
282 dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
283 return NULL;
284 }
285
286 static void
287 test_rwlock (void)
288 {
289 int i;
290 gl_thread_t checkerthreads[THREAD_COUNT];
291 gl_thread_t threads[THREAD_COUNT];
292
293
294 for (i = 0; i < ACCOUNT_COUNT; i++)
295 account[i] = 1000;
296 init_atomic_int (&rwlock_checker_done);
297 set_atomic_int_value (&rwlock_checker_done, 0);
298
299
300 for (i = 0; i < THREAD_COUNT; i++)
301 checkerthreads[i] = gl_thread_create (rwlock_checker_thread, NULL);
302 for (i = 0; i < THREAD_COUNT; i++)
303 threads[i] = gl_thread_create (rwlock_mutator_thread, NULL);
304
305
306 for (i = 0; i < THREAD_COUNT; i++)
307 gl_thread_join (threads[i], NULL);
308 set_atomic_int_value (&rwlock_checker_done, 1);
309 for (i = 0; i < THREAD_COUNT; i++)
310 gl_thread_join (checkerthreads[i], NULL);
311 check_accounts ();
312 }
313
314
315
316
317
318
319
320
321 gl_recursive_lock_define_initialized(static, my_reclock)
322
323 static void
324 recshuffle (void)
325 {
326 int i1, i2, value;
327
328 dbgprintf ("Mutator %p before lock\n", gl_thread_self_pointer ());
329 gl_recursive_lock_lock (my_reclock);
330 dbgprintf ("Mutator %p after lock\n", gl_thread_self_pointer ());
331
332 i1 = random_account ();
333 i2 = random_account ();
334 value = ((unsigned int) rand () >> 3) % 10;
335 account[i1] += value;
336 account[i2] -= value;
337
338
339 if (((unsigned int) rand () >> 3) % 2)
340 recshuffle ();
341
342 dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
343 gl_recursive_lock_unlock (my_reclock);
344 dbgprintf ("Mutator %p after unlock\n", gl_thread_self_pointer ());
345 }
346
347 static void *
348 reclock_mutator_thread (void *arg)
349 {
350 int repeat;
351
352 for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
353 {
354 recshuffle ();
355
356 dbgprintf ("Mutator %p before check lock\n", gl_thread_self_pointer ());
357 gl_recursive_lock_lock (my_reclock);
358 check_accounts ();
359 gl_recursive_lock_unlock (my_reclock);
360 dbgprintf ("Mutator %p after check unlock\n", gl_thread_self_pointer ());
361
362 yield ();
363 }
364
365 dbgprintf ("Mutator %p dying.\n", gl_thread_self_pointer ());
366 return NULL;
367 }
368
369 static struct atomic_int reclock_checker_done;
370
371 static void *
372 reclock_checker_thread (void *arg)
373 {
374 while (get_atomic_int_value (&reclock_checker_done) == 0)
375 {
376 dbgprintf ("Checker %p before check lock\n", gl_thread_self_pointer ());
377 gl_recursive_lock_lock (my_reclock);
378 check_accounts ();
379 gl_recursive_lock_unlock (my_reclock);
380 dbgprintf ("Checker %p after check unlock\n", gl_thread_self_pointer ());
381
382 yield ();
383 }
384
385 dbgprintf ("Checker %p dying.\n", gl_thread_self_pointer ());
386 return NULL;
387 }
388
389 static void
390 test_recursive_lock (void)
391 {
392 int i;
393 gl_thread_t checkerthread;
394 gl_thread_t threads[THREAD_COUNT];
395
396
397 for (i = 0; i < ACCOUNT_COUNT; i++)
398 account[i] = 1000;
399 init_atomic_int (&reclock_checker_done);
400 set_atomic_int_value (&reclock_checker_done, 0);
401
402
403 checkerthread = gl_thread_create (reclock_checker_thread, NULL);
404 for (i = 0; i < THREAD_COUNT; i++)
405 threads[i] = gl_thread_create (reclock_mutator_thread, NULL);
406
407
408 for (i = 0; i < THREAD_COUNT; i++)
409 gl_thread_join (threads[i], NULL);
410 set_atomic_int_value (&reclock_checker_done, 1);
411 gl_thread_join (checkerthread, NULL);
412 check_accounts ();
413 }
414
415
416
417
418
419
420
421 gl_once_define(static, fresh_once)
422 static int ready[THREAD_COUNT];
423 static gl_lock_t ready_lock[THREAD_COUNT];
424 #if ENABLE_LOCKING
425 static gl_rwlock_t fire_signal[REPEAT_COUNT];
426 #else
427 static volatile int fire_signal_state;
428 #endif
429 static gl_once_t once_control;
430 static int performed;
431 gl_lock_define_initialized(static, performed_lock)
432
433 static void
434 once_execute (void)
435 {
436 gl_lock_lock (performed_lock);
437 performed++;
438 gl_lock_unlock (performed_lock);
439 }
440
441 static void *
442 once_contender_thread (void *arg)
443 {
444 int id = (int) (intptr_t) arg;
445 int repeat;
446
447 for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
448 {
449
450 gl_lock_lock (ready_lock[id]);
451 ready[id] = 1;
452 gl_lock_unlock (ready_lock[id]);
453
454 if (repeat == REPEAT_COUNT)
455 break;
456
457 dbgprintf ("Contender %p waiting for signal for round %d\n",
458 gl_thread_self_pointer (), repeat);
459 #if ENABLE_LOCKING
460
461 gl_rwlock_rdlock (fire_signal[repeat]);
462
463 gl_rwlock_unlock (fire_signal[repeat]);
464 #else
465
466 while (fire_signal_state <= repeat)
467 yield ();
468 #endif
469 dbgprintf ("Contender %p got the signal for round %d\n",
470 gl_thread_self_pointer (), repeat);
471
472
473 gl_once (once_control, once_execute);
474 }
475
476 return NULL;
477 }
478
479 static void
480 test_once (void)
481 {
482 int i, repeat;
483 gl_thread_t threads[THREAD_COUNT];
484
485
486 for (i = 0; i < THREAD_COUNT; i++)
487 {
488 ready[i] = 0;
489 gl_lock_init (ready_lock[i]);
490 }
491 #if ENABLE_LOCKING
492 for (i = 0; i < REPEAT_COUNT; i++)
493 gl_rwlock_init (fire_signal[i]);
494 #else
495 fire_signal_state = 0;
496 #endif
497
498 #if ENABLE_LOCKING
499
500 for (i = REPEAT_COUNT-1; i >= 0; i--)
501 gl_rwlock_wrlock (fire_signal[i]);
502 #endif
503
504
505 for (i = 0; i < THREAD_COUNT; i++)
506 threads[i] =
507 gl_thread_create (once_contender_thread, (void *) (intptr_t) i);
508
509 for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
510 {
511
512 dbgprintf ("Main thread before synchronizing for round %d\n", repeat);
513 for (;;)
514 {
515 int ready_count = 0;
516 for (i = 0; i < THREAD_COUNT; i++)
517 {
518 gl_lock_lock (ready_lock[i]);
519 ready_count += ready[i];
520 gl_lock_unlock (ready_lock[i]);
521 }
522 if (ready_count == THREAD_COUNT)
523 break;
524 yield ();
525 }
526 dbgprintf ("Main thread after synchronizing for round %d\n", repeat);
527
528 if (repeat > 0)
529 {
530
531
532 if (performed != 1)
533 abort ();
534 }
535
536 if (repeat == REPEAT_COUNT)
537 break;
538
539
540 memcpy (&once_control, &fresh_once, sizeof (gl_once_t));
541
542
543 performed = 0;
544
545
546 for (i = 0; i < THREAD_COUNT; i++)
547 {
548 gl_lock_lock (ready_lock[i]);
549 ready[i] = 0;
550 gl_lock_unlock (ready_lock[i]);
551 }
552
553
554 dbgprintf ("Main thread giving signal for round %d\n", repeat);
555 #if ENABLE_LOCKING
556 gl_rwlock_unlock (fire_signal[repeat]);
557 #else
558 fire_signal_state = repeat + 1;
559 #endif
560 }
561
562
563 for (i = 0; i < THREAD_COUNT; i++)
564 gl_thread_join (threads[i], NULL);
565 }
566
567
568
569
570 int
571 main ()
572 {
573 #if HAVE_DECL_ALARM
574
575
576 int alarm_value = 600;
577 signal (SIGALRM, SIG_DFL);
578 alarm (alarm_value);
579 #endif
580
581 #if DO_TEST_LOCK
582 printf ("Starting test_lock ..."); fflush (stdout);
583 test_lock ();
584 printf (" OK\n"); fflush (stdout);
585 #endif
586 #if DO_TEST_RWLOCK
587 printf ("Starting test_rwlock ..."); fflush (stdout);
588 test_rwlock ();
589 printf (" OK\n"); fflush (stdout);
590 #endif
591 #if DO_TEST_RECURSIVE_LOCK
592 printf ("Starting test_recursive_lock ..."); fflush (stdout);
593 test_recursive_lock ();
594 printf (" OK\n"); fflush (stdout);
595 #endif
596 #if DO_TEST_ONCE
597 printf ("Starting test_once ..."); fflush (stdout);
598 test_once ();
599 printf (" OK\n"); fflush (stdout);
600 #endif
601
602 return 0;
603 }
604
605 #else
606
607
608
609 #include <stdio.h>
610
611 int
612 main ()
613 {
614 fputs ("Skipping test: multithreading not enabled\n", stderr);
615 return 77;
616 }
617
618 #endif