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