/* This really exists to check that Thrcheck behaves plausibly with pthread_once calls. Which it appears to. The original source of this program is as shown below, although it has been modified somewhat. See http://www.oreilly.com/pub/a/oreilly/ask_tim/2001/codepolicy.html for OReilly's policy on using bits of their code examples. */ /******************************************************** * An example source module to accompany... * * "Using POSIX Threads: Programming with Pthreads" * by Brad Nichols, Dick Buttlar, Jackie Farrell * O'Reilly & Associates, Inc. * ******************************************************** * once_exam.c * * An example of using the pthreads_once() call to execute an * initialization procedure. * * A program spawns multiple threads and each one tries to * execute the routine welcome() using the once call. Only * the first thread into the once routine will actually * execute welcome(). * * The program's main thread synchronizes its exit with the * exit of the threads using the pthread_join() operation. * */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <assert.h> #include <pthread.h> /* With more than 2 threads, the precise error reports vary between platforms, in terms of the number of races detected. Make life simple and just have 2 threads and so just 1 race. */ #define NUM_THREADS 2 static pthread_once_t welcome_once_block = PTHREAD_ONCE_INIT; static int unprotected1 = 0; static int unprotected2 = 0; /* This is a hack: delay threads except the first enough so as to ensure threads[0] gets to the pthread_once call first. This is so as to ensure that this test produces results which aren't scheduling sensitive. (sigh) */ void maybe_stall ( int myid ) { assert(myid >= 0 && myid < NUM_THREADS); if (myid > 0) sleep(1); } void welcome(void) { printf("welcome: Welcome\n"); unprotected1++; /* this is harmless */ } void* child ( void* argV ) { int r; maybe_stall( *(int*)argV ); r= pthread_once(&welcome_once_block, welcome); assert(!r); printf("child: Hi, I'm thread %d\n", *(int*)argV); unprotected2++; /* whereas this is a race */ return NULL; } int main ( void ) { int *id_arg, i, r; pthread_t threads[NUM_THREADS]; id_arg = (int *)malloc(NUM_THREADS*sizeof(int)); printf("main: Hello\n"); for (i = 0; i < NUM_THREADS; i++) { id_arg[i] = i; r= pthread_create(&threads[i], NULL, child, &id_arg[i]); assert(!r); } for (i = 0; i < NUM_THREADS; i++) { pthread_join(threads[i], NULL); /* printf("main: joined to thread %d\n", i); */ } printf("main: Goodbye\n"); return 0; }