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