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 <limits.h> 14 #include <pthread.h> 15 #include <stdint.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 20 21 /*********************/ 22 /* Type definitions. */ 23 /*********************/ 24 25 struct threadinfo 26 { 27 pthread_barrier_t* b; 28 pthread_t tid; 29 int8_t* array; 30 int iterations; 31 }; 32 33 34 /********************/ 35 /* Local variables. */ 36 /********************/ 37 38 static int s_silent; 39 40 41 /*************************/ 42 /* Function definitions. */ 43 /*************************/ 44 45 /** Single thread, which touches p->iterations elements of array p->array. 46 * Each modification of an element of p->array is a data race. */ 47 static void* threadfunc(struct threadinfo* p) 48 { 49 int i; 50 int8_t* const array = p->array; 51 pthread_barrier_t* const b = p->b; 52 if (! s_silent) 53 printf("thread %lx iteration 0\n", (long) pthread_self()); 54 pthread_barrier_wait(b); 55 for (i = 0; i < p->iterations; i++) 56 { 57 if (! s_silent) 58 printf("thread %lx iteration %d; writing to %p\n", 59 (long) pthread_self(), i + 1, &array[i]); 60 array[i] = i; 61 pthread_barrier_wait(b); 62 } 63 return 0; 64 } 65 66 /** Actual test, consisting of nthread threads. */ 67 static void barriers_and_races(const int nthread, const int iterations) 68 { 69 int i, res; 70 pthread_attr_t attr; 71 struct threadinfo* t; 72 pthread_barrier_t b; 73 int8_t* array; 74 75 t = malloc(nthread * sizeof(struct threadinfo)); 76 array = malloc(iterations * sizeof(array[0])); 77 78 if (! s_silent) 79 printf("&array[0] = %p\n", array); 80 81 pthread_barrier_init(&b, 0, nthread); 82 83 pthread_attr_init(&attr); 84 res = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 4096); 85 assert(res == 0); 86 87 for (i = 0; i < nthread; i++) 88 { 89 t[i].b = &b; 90 t[i].array = array; 91 t[i].iterations = iterations; 92 res = pthread_create(&t[i].tid, &attr, (void*(*)(void*))threadfunc, &t[i]); 93 if (res != 0) { 94 fprintf(stderr, "Could not create thread #%d (of %d): %s\n", 95 i, nthread, strerror(res)); 96 exit(1); 97 } 98 } 99 100 pthread_attr_destroy(&attr); 101 102 for (i = 0; i < nthread; i++) 103 { 104 pthread_join(t[i].tid, 0); 105 } 106 107 pthread_barrier_destroy(&b); 108 109 free(array); 110 free(t); 111 } 112 113 int main(int argc, char** argv) 114 { 115 int nthread; 116 int iterations; 117 118 nthread = (argc > 1) ? atoi(argv[1]) : 2; 119 iterations = (argc > 2) ? atoi(argv[2]) : 3; 120 s_silent = (argc > 3) ? atoi(argv[3]) : 0; 121 122 barriers_and_races(nthread, iterations); 123 124 return 0; 125 } 126