blob: 0882b03a16fd9a4887c8ef1de043daaddea5c11a [file] [log] [blame]
sewardjb9622d52008-11-14 19:43:44 +00001
2/* This program checks that Helgrind reports the five degenerate
3 uses of the barrier functions shown. */
sewardja6c82232008-11-16 23:25:43 +00004#define _GNU_SOURCE
sewardjb9622d52008-11-14 19:43:44 +00005#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
Elliott Hughesa0664b92017-04-18 17:46:52 -070018void *sleep1 ( void* arg )
19{
20 /* Long sleep, we hope to never trigger. */
21 sleep (10);
22 pthread_barrier_wait ( (pthread_barrier_t*)arg );
23 return NULL;
24}
25
26void *exit1 ( void* arg )
27{
28 /* Sleep a bit, then exit, we are done. */
29 sleep (1);
30 exit (0);
31 return NULL;
32}
33
sewardjb9622d52008-11-14 19:43:44 +000034int main ( void )
35{
36 pthread_barrier_t *bar1, *bar2, *bar3, *bar4, *bar5;
Elliott Hughesa0664b92017-04-18 17:46:52 -070037 /* int r; unused since pthread_cancel are commented out */
38 pthread_t thr1, thr2, slp1, slp2, ext1;
sewardjb9622d52008-11-14 19:43:44 +000039
40 /* initialise a barrier with a zero count */
41 fprintf(stderr, "\ninitialise a barrier with zero count\n");
42 bar1 = malloc(sizeof(pthread_barrier_t));
43 pthread_barrier_init(bar1, NULL, 0);
44
45 /* initialise a barrier twice */
46 fprintf(stderr, "\ninitialise a barrier twice\n");
47 bar2 = malloc(sizeof(pthread_barrier_t));
48 pthread_barrier_init(bar2, NULL, 1);
49 pthread_barrier_init(bar2, NULL, 1);
50
51 /* initialise a barrier which has threads waiting on it.
52 This isn't too simple. */
53 fprintf(stderr, "\ninitialise a barrier which has threads waiting on it\n");
54 bar3 = malloc(sizeof(pthread_barrier_t));
55 pthread_barrier_init(bar3, NULL, 2);
Elliott Hughesa0664b92017-04-18 17:46:52 -070056 /* create a thread, whose purpose is to "unblock" the barrier after
57 some sleeping in case it keeps being blocked. */
58 pthread_create(&slp1, NULL, sleep1, (void*)bar3);
sewardjb9622d52008-11-14 19:43:44 +000059 /* create a thread, whose only purpose is to block on the barrier */
60 pthread_create(&thr1, NULL, child1, (void*)bar3);
61 /* guarantee that it gets there first */
62 sleep(1);
63 /* and now reinitialise */
64 pthread_barrier_init(bar3, NULL, 3);
65
66 /* destroy a barrier that has threads waiting at it */
67 fprintf(stderr, "\ndestroy a barrier that has waiting threads\n");
68 /* once again, create a thread, whose only purpose is to block. */
69 bar4 = malloc(sizeof(pthread_barrier_t));
70 pthread_barrier_init(bar4, NULL, 2);
Elliott Hughesa0664b92017-04-18 17:46:52 -070071 /* create a thread, whose purpose is to "unblock" the barrier after
72 some sleeping in case it keeps being blocked. We hope it isn't
73 needed, but if it is, because pthread_barier_destroy hangs
74 and we will get an extra warning about the barrier being already
75 destroyed. */
76 pthread_create(&slp2, NULL, sleep1, (void*)bar4);
sewardjb9622d52008-11-14 19:43:44 +000077 /* create a thread, whose only purpose is to block on the barrier */
78 pthread_create(&thr2, NULL, child1, (void*)bar4);
79 /* guarantee that it gets there first */
80 sleep(1);
81 /* and now destroy */
82 pthread_barrier_destroy(bar4);
83
Elliott Hughesed398002017-06-21 14:41:24 -070084 pthread_cancel(slp2);
85
sewardjb9622d52008-11-14 19:43:44 +000086 /* destroy a barrier that was never initialised. This is a bit
87 tricky, in that we have to fill the barrier with bytes which
Elliott Hughesa0664b92017-04-18 17:46:52 -070088 ensure that the pthread_barrier_destroy call doesn't crash for
89 some reason. One-fill seems to work ok on amd64-linux (glibc
sewardjb9622d52008-11-14 19:43:44 +000090 2.8). */
91 fprintf(stderr, "\ndestroy a barrier that was never initialised\n");
Elliott Hughesa0664b92017-04-18 17:46:52 -070092 /* Create a thread that just exits the process after some sleep.
93 We are really done at this point, even if we hang. */
94 pthread_create(&ext1, NULL, exit1, NULL);
sewardjb9622d52008-11-14 19:43:44 +000095 bar5 = malloc(sizeof(pthread_barrier_t));
96 assert(bar5);
Elliott Hughesa0664b92017-04-18 17:46:52 -070097 memset(bar5, 1, sizeof(*bar5));
sewardjb9622d52008-11-14 19:43:44 +000098 pthread_barrier_destroy(bar5);
99
Elliott Hughesa0664b92017-04-18 17:46:52 -0700100 /* now we need to clean up the mess .. But skip canceling threads. */
101 /* r= pthread_cancel(thr1); assert(!r); // drd doesn't like it. Just exit.
102 r= pthread_cancel(thr2); assert(!r); */
sewardjb9622d52008-11-14 19:43:44 +0000103
104 free(bar1); free(bar2); free(bar3); free(bar4); free(bar5);
105
Elliott Hughesa0664b92017-04-18 17:46:52 -0700106 /* Use exit, we want to kill any "sleeper threads". */
107 exit (0);
sewardjb9622d52008-11-14 19:43:44 +0000108}