blob: 1cc6d32c3492d7c3da42029a1d8c355bb1cab581 [file] [log] [blame]
/* 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;
}