Created
June 16, 2012 19:57
-
-
Save anonymous/2942375 to your computer and use it in GitHub Desktop.
stdin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* \file | |
* Author: Markus J. Kusano | |
* | |
* A small program recreating a bug found in SPLASH-2 | |
* | |
* See README for more information | |
*/ | |
#include <pthread.h> | |
#include <stdio.h> | |
/* Comment out to remove debugging messages and calls to sleep() to attempt to | |
* force the bug */ | |
#define DEBUG | |
#ifdef DEBUG | |
#include <unistd.h> | |
#endif | |
/*! | |
* ID ``pool''. Threads in the worker() function obtain their local id from | |
* this variable. | |
* | |
* \sa worker() | |
*/ | |
int gid; | |
/*! | |
* Variable where the result is stored. The program does not do any actual | |
* work. Result is initialized to zero by main(). The thread with myid == 0 in | |
* the worker() function will store the variable local to worker() data into | |
* result. | |
* | |
* \sa worker() | |
*/ | |
int result; | |
/*! | |
* Lock that synchronizes read/write access to gid variable. | |
*/ | |
pthread_mutex_t gidLock = PTHREAD_MUTEX_INITIALIZER; | |
/*! | |
* A function that emulates work being done from SPLASH-2. Each thread is given | |
* local id, myid. myid is generated by assigning the current value of gid to | |
* myid and then incrementing gid. The operation is protected by gidLock. | |
* | |
* \param arg Unused | |
*/ | |
void *worker(void *arg); | |
void *worker(void *arg) { | |
#ifdef DEBUG | |
printf("Entered worker function\n"); | |
#endif | |
int myid; | |
int data = 999; | |
pthread_mutex_lock(&gidLock); | |
myid = gid; | |
gid++; | |
#ifdef DEBUG | |
printf("myid == %d\n", myid); | |
#endif | |
pthread_mutex_unlock(&gidLock); | |
/* work */ | |
if (myid == 0) { | |
#ifdef DEBUG | |
printf("Sleeping since myid == 0\n"); | |
sleep(3); | |
#endif | |
result = data; | |
} | |
return NULL; | |
} | |
/*! | |
* Globals (gid and result) are initialized to 0. Two threads are created (t1 | |
* and t2) that spawn in the worker() function. The main() thread then waits | |
* for the second thread to return by calling pthread_join(). | |
* | |
* It was first attempted to have the main thread enter the worker function | |
* after creating one child worker() thread. This seemed to stall the main() | |
* thread for some reason. It was not discovered why this occured. | |
* | |
* After thread2 (t2) returns, the main thread stores the value of global | |
* variable result into local variable tmp and then prints temp using printf(). | |
* | |
* There is assumed atomicity in one of the worker functions (the one with myid | |
* == 0) will have stored the data into result. If t2 finishes before t1 and | |
* main prints out the result, there is a chance that result will still have | |
* the initialized value of 0. | |
* | |
* The thread with myid == 0 sets result to 999 to simulate doing work. | |
*/ | |
int main() { | |
pthread_t t1; | |
int tmp; | |
/* initialize globals */ | |
gid = 0; | |
result = 0; | |
pthread_create(&t1, NULL, worker, NULL); | |
worker(NULL); | |
#ifdef DEBUG | |
printf("Parent thread exited worker function\n"); | |
#endif | |
tmp = result; | |
printf("%d\n", tmp); | |
pthread_exit((void *) 0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment