• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* This program checks that Helgrind reports the five degenerate
3    uses of the barrier functions shown. */
4 #define _GNU_SOURCE
5 #include <pthread.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <assert.h>
9 #include <unistd.h>
10 #include <string.h>
11 
child1(void * arg)12 void* child1 ( void* arg )
13 {
14    pthread_barrier_wait( (pthread_barrier_t*)arg );
15    return NULL;
16 }
17 
main(void)18 int main ( void )
19 {
20   pthread_barrier_t *bar1, *bar2, *bar3, *bar4, *bar5;
21   pthread_t thr1, thr2;
22   int r;
23 
24   /* possibly set up a watchdog timer thread here. */
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36   /* initialise a barrier with a zero count */
37   fprintf(stderr, "\ninitialise a barrier with zero count\n");
38   bar1 = malloc(sizeof(pthread_barrier_t));
39   pthread_barrier_init(bar1, NULL, 0);
40 
41   /* initialise a barrier twice */
42   fprintf(stderr, "\ninitialise a barrier twice\n");
43   bar2 = malloc(sizeof(pthread_barrier_t));
44   pthread_barrier_init(bar2, NULL, 1);
45   pthread_barrier_init(bar2, NULL, 1);
46 
47   /* initialise a barrier which has threads waiting on it.
48      This isn't too simple. */
49   fprintf(stderr, "\ninitialise a barrier which has threads waiting on it\n");
50   bar3 = malloc(sizeof(pthread_barrier_t));
51   pthread_barrier_init(bar3, NULL, 2);
52   /* create a thread, whose only purpose is to block on the barrier */
53   pthread_create(&thr1, NULL, child1, (void*)bar3);
54   /* guarantee that it gets there first */
55   sleep(1);
56   /* and now reinitialise */
57   pthread_barrier_init(bar3, NULL, 3);
58 
59   /* destroy a barrier that has threads waiting at it */
60   fprintf(stderr, "\ndestroy a barrier that has waiting threads\n");
61   /* once again, create a thread, whose only purpose is to block. */
62   bar4 = malloc(sizeof(pthread_barrier_t));
63   pthread_barrier_init(bar4, NULL, 2);
64   /* create a thread, whose only purpose is to block on the barrier */
65   pthread_create(&thr2, NULL, child1, (void*)bar4);
66   /* guarantee that it gets there first */
67   sleep(1);
68   /* and now destroy */
69   pthread_barrier_destroy(bar4);
70 
71   /* destroy a barrier that was never initialised.  This is a bit
72      tricky, in that we have to fill the barrier with bytes which
73      ensure that the pthread_barrier_destroy call doesn't hang for
74      some reason.  Zero-fill seems to work ok on amd64-linux (glibc
75      2.8). */
76   fprintf(stderr, "\ndestroy a barrier that was never initialised\n");
77   bar5 = malloc(sizeof(pthread_barrier_t));
78   assert(bar5);
79   memset(bar5, 0, sizeof(*bar5));
80   pthread_barrier_destroy(bar5);
81 
82   /* now we need to clean up the mess .. */
83   r= pthread_cancel(thr1); assert(!r);
84   r= pthread_cancel(thr2); assert(!r);
85 
86   free(bar1); free(bar2); free(bar3); free(bar4); free(bar5);
87 
88   return 0;
89 }
90