• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) */
maybe_stall(int myid)57 void maybe_stall ( int myid )
58 {
59    assert(myid >= 0 && myid < NUM_THREADS);
60    if (myid > 0)
61       sleep(1);
62 }
63 
welcome(void)64 void welcome(void) {
65    printf("welcome: Welcome\n");
66    unprotected1++; /* this is harmless */
67 }
68 
child(void * argV)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 
main(void)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