Home | History | Annotate | Download | only in tests
      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