1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h>
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Simple test program, no race: parent only modifies x after child
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   has modified it and then joined with the parent.  Tests simple
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   thread lifetime segment handling. */
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A simple function to "use" a value, so that gcc can't
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   possibly optimise it into nothing. */
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void use ( int x ) {
13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   __asm__ __volatile__( "" : : "r"(x) : "cc","memory" );
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* worker_thread ( void* argV )
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int* arg = (int*)argV;
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  use(arg[5]); /* read access */
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return NULL;
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main ( void )
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pthread_t thread_id;
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   volatile int* x = malloc(10 * sizeof(int));
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x[5] = 1;
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* x[5] is Excl(parent) */
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pthread_create(&thread_id, 0, worker_thread, (void*)x);
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   use(x[5]); /* read access */
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Just before the threads join, x[5] is ShR (read by both parent
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and child) */
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pthread_join(thread_id, 0);
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* x[5] is Excl(parent), because only parent and child accessed it
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and child has merged to parent.  So now it's ok for parent to
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      access it without locking. */
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x[5] = 0; /* write access */
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return x[5];
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
45