mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 08:26:14 +00:00
98 lines
2.7 KiB
C
98 lines
2.7 KiB
C
|
|
/* 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;
|
|
}
|