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