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