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