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