1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Test data race detection between floating point variables. */ 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h> 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> /* printf() */ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h> 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h> /* sleep() */ 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Local functions declarations. */ 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* thread_func(void*); 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Local variables. */ 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* s_mutex protects s_d3. */ 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic pthread_mutex_t s_mutex; 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic double s_d1; /* accessed before thread creation and in the created */ 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* thread (not a race). */ 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic double s_d2; /* accessed in the created thread and after the join */ 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* (not a race). */ 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic double s_d3; /* accessed simultaneously from both threads (race). */ 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int s_debug = 0; 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int s_do_printf = 0; 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int s_use_mutex = 0; 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Function definitions. */ 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(int argc, char** argv) 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int optchar; 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t threadid; 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ((optchar = getopt(argc, argv, "dmp")) != EOF) 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (optchar) 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 'd': 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_debug = 1; 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 'm': 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_use_mutex = 1; 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 'p': 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_do_printf = 1; 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(0); 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_init(&s_mutex, 0); 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Switch to line-buffered mode, such that timing information can be 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * obtained for each printf() call with strace. 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown setlinebuf(stdout); 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s_debug) 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("&s_d1 = %p; &s_d2 = %p; &s_d3 = %p\n", &s_d1, &s_d2, &s_d3); 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_d1 = 1; 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_d3 = 3; 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create(&threadid, 0, thread_func, 0); 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sleep(1); /* Wait until thread_func() finished. */ 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s_use_mutex) pthread_mutex_lock(&s_mutex); 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_d3++; 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s_use_mutex) pthread_mutex_unlock(&s_mutex); 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Wait until the thread finished. */ 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_join(threadid, 0); 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s_do_printf) printf("s_d2 = %g (should be 2)\n", s_d2); 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s_do_printf) printf("s_d3 = %g (should be 5)\n", s_d3); 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_destroy(&s_mutex); 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* thread_func(void* thread_arg) 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s_do_printf) 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown printf("s_d1 = %g (should be 1)\n", s_d1); 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_d2 = 2; 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s_use_mutex) pthread_mutex_lock(&s_mutex); 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_d3++; 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (s_use_mutex) pthread_mutex_unlock(&s_mutex); 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 105