blob: 854ee34edee878c5acc404e84583b08123a1554e [file] [log] [blame]
sewardj347eeba2008-01-21 14:19:07 +00001/* 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>
bart7aac06f2011-08-12 15:21:31 +000013#include <limits.h>
sewardj347eeba2008-01-21 14:19:07 +000014#include <pthread.h>
bartde60fe52011-10-05 13:10:30 +000015#include <stdint.h>
sewardj347eeba2008-01-21 14:19:07 +000016#include <stdio.h>
17#include <stdlib.h>
florian4b82d692011-08-12 15:07:10 +000018#include <string.h>
sewardj347eeba2008-01-21 14:19:07 +000019
20
21/*********************/
22/* Type definitions. */
23/*********************/
24
25struct threadinfo
26{
27 pthread_barrier_t* b;
28 pthread_t tid;
bartde60fe52011-10-05 13:10:30 +000029 int8_t* array;
sewardj347eeba2008-01-21 14:19:07 +000030 int iterations;
31};
32
33
34/********************/
35/* Local variables. */
36/********************/
37
38static int s_silent;
39
40
41/*************************/
42/* Function definitions. */
43/*************************/
44
bart546b7712008-02-24 18:18:23 +000045/** Single thread, which touches p->iterations elements of array p->array.
46 * Each modification of an element of p->array is a data race. */
sewardj347eeba2008-01-21 14:19:07 +000047static void* threadfunc(struct threadinfo* p)
48{
49 int i;
florianad2fc772011-10-05 14:49:12 +000050 int8_t* const array = p->array;
sewardj347eeba2008-01-21 14:19:07 +000051 pthread_barrier_t* const b = p->b;
52 if (! s_silent)
53 printf("thread %lx iteration 0\n", 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 pthread_self(), i + 1, &array[i]);
60 array[i] = i;
61 pthread_barrier_wait(b);
62 }
63 return 0;
64}
65
bart546b7712008-02-24 18:18:23 +000066/** Actual test, consisting of nthread threads. */
sewardj347eeba2008-01-21 14:19:07 +000067static void barriers_and_races(const int nthread, const int iterations)
68{
bart7aac06f2011-08-12 15:21:31 +000069 int i, res;
70 pthread_attr_t attr;
sewardj347eeba2008-01-21 14:19:07 +000071 struct threadinfo* t;
72 pthread_barrier_t b;
florianad2fc772011-10-05 14:49:12 +000073 int8_t* array;
sewardj347eeba2008-01-21 14:19:07 +000074
75 t = malloc(nthread * sizeof(struct threadinfo));
76 array = malloc(iterations * sizeof(array[0]));
77
bart546b7712008-02-24 18:18:23 +000078 if (! s_silent)
79 printf("&array[0] = %p\n", array);
80
sewardj347eeba2008-01-21 14:19:07 +000081 pthread_barrier_init(&b, 0, nthread);
82
bart7aac06f2011-08-12 15:21:31 +000083 pthread_attr_init(&attr);
84 res = pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + 4096);
85 assert(res == 0);
86
sewardj347eeba2008-01-21 14:19:07 +000087 for (i = 0; i < nthread; i++)
88 {
89 t[i].b = &b;
90 t[i].array = array;
91 t[i].iterations = iterations;
bart7aac06f2011-08-12 15:21:31 +000092 res = pthread_create(&t[i].tid, &attr, (void*(*)(void*))threadfunc, &t[i]);
93 if (res != 0) {
florian4b82d692011-08-12 15:07:10 +000094 fprintf(stderr, "Could not create thread #%d (of %d): %s\n",
bart7aac06f2011-08-12 15:21:31 +000095 i, nthread, strerror(res));
florian4b82d692011-08-12 15:07:10 +000096 exit(1);
97 }
sewardj347eeba2008-01-21 14:19:07 +000098 }
99
bart7aac06f2011-08-12 15:21:31 +0000100 pthread_attr_destroy(&attr);
101
sewardj347eeba2008-01-21 14:19:07 +0000102 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
113int main(int argc, char** argv)
114{
115 int nthread;
116 int iterations;
117
bart546b7712008-02-24 18:18:23 +0000118 nthread = (argc > 1) ? atoi(argv[1]) : 2;
sewardj347eeba2008-01-21 14:19:07 +0000119 iterations = (argc > 2) ? atoi(argv[2]) : 3;
bart546b7712008-02-24 18:18:23 +0000120 s_silent = (argc > 3) ? atoi(argv[3]) : 0;
sewardj347eeba2008-01-21 14:19:07 +0000121
122 barriers_and_races(nthread, iterations);
123
124 return 0;
125}