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 void *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 
     26 void *exit1 ( void* arg )
     27 {
     28    /* Sleep a bit, then exit, we are done. */
     29    sleep (1);
     30    exit (0);
     31    return NULL;
     32 }
     33 
     34 int main ( void )
     35 {
     36   pthread_barrier_t *bar1, *bar2, *bar3, *bar4, *bar5;
     37   /* int r; unused since pthread_cancel are commented out */
     38   pthread_t thr1, thr2, slp1, slp2, ext1;
     39 
     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);
     56   /* 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);
     59   /* 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);
     71   /* 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);
     77   /* 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 
     84   pthread_cancel(slp2);
     85 
     86   /* destroy a barrier that was never initialised.  This is a bit
     87      tricky, in that we have to fill the barrier with bytes which
     88      ensure that the pthread_barrier_destroy call doesn't crash for
     89      some reason.  One-fill seems to work ok on amd64-linux (glibc
     90      2.8). */
     91   fprintf(stderr, "\ndestroy a barrier that was never initialised\n");
     92   /* 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);
     95   bar5 = malloc(sizeof(pthread_barrier_t));
     96   assert(bar5);
     97   memset(bar5, 1, sizeof(*bar5));
     98   pthread_barrier_destroy(bar5);
     99 
    100   /* 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); */
    103 
    104   free(bar1); free(bar2); free(bar3); free(bar4); free(bar5);
    105 
    106   /* Use exit, we want to kill any "sleeper threads". */
    107   exit (0);
    108 }
    109