1 2 /* This really exists to check that Thrcheck behaves plausibly 3 with pthread_once calls. Which it appears to. 4 5 The original source of this program is as shown below, although it 6 has been modified somewhat. See 7 http://www.oreilly.com/pub/a/oreilly/ask_tim/2001/codepolicy.html 8 for OReilly's policy on using bits of their code examples. 9 */ 10 11 12 /******************************************************** 13 * An example source module to accompany... 14 * 15 * "Using POSIX Threads: Programming with Pthreads" 16 * by Brad Nichols, Dick Buttlar, Jackie Farrell 17 * O'Reilly & Associates, Inc. 18 * 19 ******************************************************** 20 * once_exam.c 21 * 22 * An example of using the pthreads_once() call to execute an 23 * initialization procedure. 24 * 25 * A program spawns multiple threads and each one tries to 26 * execute the routine welcome() using the once call. Only 27 * the first thread into the once routine will actually 28 * execute welcome(). 29 * 30 * The program's main thread synchronizes its exit with the 31 * exit of the threads using the pthread_join() operation. 32 * 33 */ 34 35 #include <stdlib.h> 36 #include <stdio.h> 37 #include <unistd.h> 38 #include <sys/types.h> 39 #include <assert.h> 40 41 #include <pthread.h> 42 43 /* With more than 2 threads, the precise error reports vary between 44 platforms, in terms of the number of races detected. Make life 45 simple and just have 2 threads and so just 1 race. */ 46 #define NUM_THREADS 2 47 48 static pthread_once_t welcome_once_block = PTHREAD_ONCE_INIT; 49 50 static int unprotected1 = 0; 51 static int unprotected2 = 0; 52 53 /* This is a hack: delay threads except the first enough so as to 54 ensure threads[0] gets to the pthread_once call first. This is so 55 as to ensure that this test produces results which aren't 56 scheduling sensitive. (sigh) */ 57 void maybe_stall ( int myid ) 58 { 59 assert(myid >= 0 && myid < NUM_THREADS); 60 if (myid > 0) 61 sleep(1); 62 } 63 64 void welcome(void) { 65 printf("welcome: Welcome\n"); 66 unprotected1++; /* this is harmless */ 67 } 68 69 void* child ( void* argV ) { 70 int r; 71 maybe_stall( *(int*)argV ); 72 r= pthread_once(&welcome_once_block, welcome); assert(!r); 73 printf("child: Hi, I'm thread %d\n", *(int*)argV); 74 unprotected2++; /* whereas this is a race */ 75 return NULL; 76 } 77 78 int main ( void ) { 79 int *id_arg, i, r; 80 pthread_t threads[NUM_THREADS]; 81 82 id_arg = (int *)malloc(NUM_THREADS*sizeof(int)); 83 84 for (i = 0; i < NUM_THREADS; i++) { 85 id_arg[i] = i; 86 r= pthread_create(&threads[i], NULL, child, &id_arg[i]); 87 assert(!r); 88 } 89 90 for (i = 0; i < NUM_THREADS; i++) { 91 pthread_join(threads[i], NULL); 92 /* printf("main: joined to thread %d\n", i); */ 93 } 94 printf("main: Goodbye\n"); 95 return 0; 96 } 97