Home | History | Annotate | Download | only in tests
      1 /* Test whether all data races are detected in a multithreaded program with
      2  * barriers.
      3  */
      4 
      5 
      6 #define _GNU_SOURCE
      7 
      8 /***********************/
      9 /* Include directives. */
     10 /***********************/
     11 
     12 #include <assert.h>
     13 #include <pthread.h>
     14 #include <stdio.h>
     15 #include <stdlib.h>
     16 
     17 
     18 /*********************/
     19 /* Type definitions. */
     20 /*********************/
     21 
     22 struct threadinfo
     23 {
     24   pthread_barrier_t* b;
     25   pthread_t          tid;
     26   int*               array;
     27   int                iterations;
     28 };
     29 
     30 
     31 /********************/
     32 /* Local variables. */
     33 /********************/
     34 
     35 static int s_silent;
     36 
     37 
     38 /*************************/
     39 /* Function definitions. */
     40 /*************************/
     41 
     42 /** Single thread, which touches p->iterations elements of array p->array.
     43  * Each modification of an element of p->array is a data race. */
     44 static void* threadfunc(struct threadinfo* p)
     45 {
     46   int i;
     47   int* const array = p->array;
     48   pthread_barrier_t* const b = p->b;
     49   if (! s_silent)
     50     printf("thread %lx iteration 0\n", pthread_self());
     51   pthread_barrier_wait(b);
     52   for (i = 0; i < p->iterations; i++)
     53   {
     54     if (! s_silent)
     55       printf("thread %lx iteration %d; writing to %p\n",
     56              pthread_self(), i + 1, &array[i]);
     57     array[i] = i;
     58     pthread_barrier_wait(b);
     59   }
     60   return 0;
     61 }
     62 
     63 /** Actual test, consisting of nthread threads. */
     64 static void barriers_and_races(const int nthread, const int iterations)
     65 {
     66   int i;
     67   struct threadinfo* t;
     68   pthread_barrier_t b;
     69   int* array;
     70 
     71   t = malloc(nthread * sizeof(struct threadinfo));
     72   array = malloc(iterations * sizeof(array[0]));
     73 
     74   if (! s_silent)
     75     printf("&array[0] = %p\n", array);
     76 
     77   pthread_barrier_init(&b, 0, nthread);
     78 
     79   for (i = 0; i < nthread; i++)
     80   {
     81     t[i].b = &b;
     82     t[i].array = array;
     83     t[i].iterations = iterations;
     84     pthread_create(&t[i].tid, 0, (void*(*)(void*))threadfunc, &t[i]);
     85   }
     86 
     87   for (i = 0; i < nthread; i++)
     88   {
     89     pthread_join(t[i].tid, 0);
     90   }
     91 
     92   pthread_barrier_destroy(&b);
     93 
     94   free(array);
     95   free(t);
     96 }
     97 
     98 int main(int argc, char** argv)
     99 {
    100   int nthread;
    101   int iterations;
    102 
    103   nthread    = (argc > 1) ? atoi(argv[1]) : 2;
    104   iterations = (argc > 2) ? atoi(argv[2]) : 3;
    105   s_silent   = (argc > 3) ? atoi(argv[3]) : 0;
    106 
    107   barriers_and_races(nthread, iterations);
    108 
    109   return 0;
    110 }
    111