1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This test program triggers a single race condition on variable s_y. 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Although another variable (s_x) is also modified by both threads, no race 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * condition must be reported on this variable since it is only accessed via 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * atomic instructions. 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Note: for the i386 and x86_64 memory models, thread 2 must print y = 1. 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * On PPC however, both y = 0 and y = 1 are legal results. This is because 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the PPC memory model allows different CPU's to observe stores to variables 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * in different cache lines in a different order. 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _GNU_SOURCE 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h> 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> /* fprintf() */ 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h> /* atoi() */ 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "../../config.h" 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Atomic builtins are only supported by gcc 4.1.0 and later. */ 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef HAVE_BUILTIN_ATOMIC 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#error Sorry, but this test program can only be compiled by a compiler that\ 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownhas built-in functions for atomic memory access. 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint sync_add_and_fetch(int* p, int i) 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return __sync_add_and_fetch(p, i); 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int s_x = 0; 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* g_dummy[] ensures that s_x and s_y are not in the same cache line. */ 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownchar g_dummy[512]; 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int s_y = 0; 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* thread_func_1(void* arg) 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_y = 1; 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void) sync_add_and_fetch(&s_x, 1); 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* thread_func_2(void* arg) 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (sync_add_and_fetch(&s_x, 0) == 0) 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ; 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "y = %d\n", s_y); 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(int argc, char** argv) 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int i; 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const int n_threads = 2; 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t tid[n_threads]; 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "Start of test.\n"); 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create(&tid[0], 0, thread_func_1, 0); 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create(&tid[1], 0, thread_func_2, 0); 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_threads; i++) 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_join(tid[i], 0); 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "Test finished.\n"); 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 67