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