Home | History | Annotate | Download | only in tests
      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    printf("main: Hello\n");
     85    for (i = 0; i < NUM_THREADS; i++) {
     86       id_arg[i] = i;
     87       r= pthread_create(&threads[i], NULL, child, &id_arg[i]);
     88       assert(!r);
     89    }
     90 
     91    for (i = 0; i < NUM_THREADS; i++) {
     92       pthread_join(threads[i], NULL);
     93       /* printf("main: joined to thread %d\n", i); */
     94    }
     95    printf("main: Goodbye\n");
     96    return 0;
     97 }
     98