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 48static pthread_once_t welcome_once_block = PTHREAD_ONCE_INIT; 49 50static int unprotected1 = 0; 51static 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) */ 57void maybe_stall ( int myid ) 58{ 59 assert(myid >= 0 && myid < NUM_THREADS); 60 if (myid > 0) 61 sleep(1); 62} 63 64void welcome(void) { 65 printf("welcome: Welcome\n"); 66 unprotected1++; /* this is harmless */ 67} 68 69void* 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 78int 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