148529bc234eb7497175c99bb727e9bd3c6a229d4bart/** 248529bc234eb7497175c99bb727e9bd3c6a229d4bart * This test program triggers a single race condition on variable s_y. 348529bc234eb7497175c99bb727e9bd3c6a229d4bart * Although another variable (s_x) is also modified by both threads, no race 448529bc234eb7497175c99bb727e9bd3c6a229d4bart * condition must be reported on this variable since it is only accessed via 548529bc234eb7497175c99bb727e9bd3c6a229d4bart * atomic instructions. 648529bc234eb7497175c99bb727e9bd3c6a229d4bart * 748529bc234eb7497175c99bb727e9bd3c6a229d4bart * Note: for the i386 and x86_64 memory models, thread 2 must print y = 1. 848529bc234eb7497175c99bb727e9bd3c6a229d4bart * On PPC however, both y = 0 and y = 1 are legal results. This is because 948529bc234eb7497175c99bb727e9bd3c6a229d4bart * the PPC memory model allows different CPU's to observe stores to variables 1048529bc234eb7497175c99bb727e9bd3c6a229d4bart * in different cache lines in a different order. 11cca440bcba031f0f37b39ad82e840ba693dd6b9dbart */ 12cca440bcba031f0f37b39ad82e840ba693dd6b9dbart 13cca440bcba031f0f37b39ad82e840ba693dd6b9dbart#define _GNU_SOURCE 14cca440bcba031f0f37b39ad82e840ba693dd6b9dbart 15cca440bcba031f0f37b39ad82e840ba693dd6b9dbart#include <pthread.h> 16cca440bcba031f0f37b39ad82e840ba693dd6b9dbart#include <stdio.h> /* fprintf() */ 17cca440bcba031f0f37b39ad82e840ba693dd6b9dbart#include <stdlib.h> /* atoi() */ 18d22e8b216f2dcde66d77dcecfc3a6b03a40db2a7bart#include "../../config.h" 19cca440bcba031f0f37b39ad82e840ba693dd6b9dbart 2048529bc234eb7497175c99bb727e9bd3c6a229d4bart/* Atomic builtins are only supported by gcc 4.1.0 and later. */ 21d45d99553c15a361bb797d21ec6afb9bad22d2d4bart#ifndef HAVE_BUILTIN_ATOMIC 22d45d99553c15a361bb797d21ec6afb9bad22d2d4bart#error Sorry, but this test program can only be compiled by a compiler that\ 23d45d99553c15a361bb797d21ec6afb9bad22d2d4barthas built-in functions for atomic memory access. 24d45d99553c15a361bb797d21ec6afb9bad22d2d4bart#endif 2548529bc234eb7497175c99bb727e9bd3c6a229d4bart 26cca440bcba031f0f37b39ad82e840ba693dd6b9dbartstatic __inline__ 27143eec7c7f7e00e7d60def53097eb18559a1a2fbbartint sync_add_and_fetch(int* p, int i) 28143eec7c7f7e00e7d60def53097eb18559a1a2fbbart{ 29143eec7c7f7e00e7d60def53097eb18559a1a2fbbart return __sync_add_and_fetch(p, i); 30143eec7c7f7e00e7d60def53097eb18559a1a2fbbart} 31cca440bcba031f0f37b39ad82e840ba693dd6b9dbart 32cca440bcba031f0f37b39ad82e840ba693dd6b9dbartstatic int s_x = 0; 3348529bc234eb7497175c99bb727e9bd3c6a229d4bart/* g_dummy[] ensures that s_x and s_y are not in the same cache line. */ 3448529bc234eb7497175c99bb727e9bd3c6a229d4bartchar g_dummy[512]; 35cca440bcba031f0f37b39ad82e840ba693dd6b9dbartstatic int s_y = 0; 36cca440bcba031f0f37b39ad82e840ba693dd6b9dbart 37cca440bcba031f0f37b39ad82e840ba693dd6b9dbartstatic void* thread_func_1(void* arg) 38cca440bcba031f0f37b39ad82e840ba693dd6b9dbart{ 39cca440bcba031f0f37b39ad82e840ba693dd6b9dbart s_y = 1; 40143eec7c7f7e00e7d60def53097eb18559a1a2fbbart (void) sync_add_and_fetch(&s_x, 1); 41cca440bcba031f0f37b39ad82e840ba693dd6b9dbart return 0; 42cca440bcba031f0f37b39ad82e840ba693dd6b9dbart} 43cca440bcba031f0f37b39ad82e840ba693dd6b9dbart 44cca440bcba031f0f37b39ad82e840ba693dd6b9dbartstatic void* thread_func_2(void* arg) 45cca440bcba031f0f37b39ad82e840ba693dd6b9dbart{ 46143eec7c7f7e00e7d60def53097eb18559a1a2fbbart while (sync_add_and_fetch(&s_x, 0) == 0) 47cca440bcba031f0f37b39ad82e840ba693dd6b9dbart ; 48cca440bcba031f0f37b39ad82e840ba693dd6b9dbart fprintf(stderr, "y = %d\n", s_y); 49cca440bcba031f0f37b39ad82e840ba693dd6b9dbart return 0; 50cca440bcba031f0f37b39ad82e840ba693dd6b9dbart} 51cca440bcba031f0f37b39ad82e840ba693dd6b9dbart 52cca440bcba031f0f37b39ad82e840ba693dd6b9dbartint main(int argc, char** argv) 53cca440bcba031f0f37b39ad82e840ba693dd6b9dbart{ 54cca440bcba031f0f37b39ad82e840ba693dd6b9dbart int i; 55cca440bcba031f0f37b39ad82e840ba693dd6b9dbart const int n_threads = 2; 56cca440bcba031f0f37b39ad82e840ba693dd6b9dbart pthread_t tid[n_threads]; 57cca440bcba031f0f37b39ad82e840ba693dd6b9dbart 58cca440bcba031f0f37b39ad82e840ba693dd6b9dbart fprintf(stderr, "Start of test.\n"); 59cca440bcba031f0f37b39ad82e840ba693dd6b9dbart pthread_create(&tid[0], 0, thread_func_1, 0); 60cca440bcba031f0f37b39ad82e840ba693dd6b9dbart pthread_create(&tid[1], 0, thread_func_2, 0); 61cca440bcba031f0f37b39ad82e840ba693dd6b9dbart for (i = 0; i < n_threads; i++) 62cca440bcba031f0f37b39ad82e840ba693dd6b9dbart pthread_join(tid[i], 0); 63cca440bcba031f0f37b39ad82e840ba693dd6b9dbart fprintf(stderr, "Test finished.\n"); 640d84eabef5806ae924bfb05aaf70445135f6e2d5bart 6548529bc234eb7497175c99bb727e9bd3c6a229d4bart return 0; 6648529bc234eb7497175c99bb727e9bd3c6a229d4bart} 67