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
12void* child1 ( void* arg )
13{
14   pthread_barrier_wait( (pthread_barrier_t*)arg );
15   return NULL;
16}
17
18int 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