Home | History | Annotate | Download | only in tests
      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