/* Note: The way in which the threads share information in this program is different from the one I wrote in the "quick guide" handout. In the handout, I used two separate functions, f and g, for two threads. In this program, a single function is used to spin off two threads. But in order for the threads to uniquely identify themselves, they'll need a parameter that'll be different for each thread. This is the purpose of the id variable in struct threadinfo. This is also why in main TWO actual threadinfo structs are created. In the handout program, the two threads do not need to have this unique parameter to identify themselfs (they run from different functions). Thus, only ONE struct was created in main, and a pointer to the struct was passed to both threads. In other words, in the handout version the entire struct and everything inside was shared by the two threads. In this version, pointers to DIFFERENT structs are used because some of the information in the structs are shared (*sum, *turn, and *mutex), but some are not (id). If you take the time to understand carefully how both programs work, and why they're consistent, then you should be in good shape. If you're a bit confused and don't know which example to follow, follow the example here. IMPORTANT SOLARIS NOTE: I wrote this program in class on Linux. In the Solaris implementation of threads there is an appearent bug in dealing with the busy loop: while( *(myinfo->turn) != myinfo->id ) {} This loop will unfortunately tie up the processor. To solve this problem, use the "sleepwait" function I defined in "utils.c", which you used in the first (scheduling) assignment. Inside the busy loop, make the thread sleep for a tiny microsecond. That, is, #include "utils.c" /* at the top of your program */ The busy loop should be changed to while( *(myinfo->turn) != myinfo->id ) { sleepwait(0.000001); } Again, this modification is only needed for Solaris. */ #include #include #define LIMIT 10000 struct threadinfo // info to be passed to thread { int id; // unique int *sum; // shared int *turn; pthread_mutex_t *mutex; }; void * f(void * info) // thread function { int other; struct threadinfo * myinfo; myinfo = (struct threadinfo *) info; if (myinfo->id == 0) other = 1; else other = 0; while ( *(myinfo->sum) < LIMIT ) { // while( *(myinfo->turn) != myinfo->id ) {} // busy loop pthread_mutex_lock(myinfo->mutex); // "lock-and-set" in one step /* critical section */ printf("This is thread %d,",myinfo->id); printf(" the sum == %d\n",*(myinfo->sum)); *(myinfo->sum) += 1; /* critical section */ // *(myinfo->turn) = other; pthread_mutex_unlock(myinfo->mutex); } } // f int main() { pthread_t tid0, tid1; int mysum; // to be shared by threads int myturn; pthread_mutex_t mymutex; struct threadinfo info0; struct threadinfo info1; info0.id = 0; info1.id = 1; info0.sum = &mysum; info1.sum = &mysum; info0.turn = &myturn; info1.turn = &myturn; info0.mutex = &mymutex; info1.mutex = &mymutex; mysum = 0; myturn = 0; pthread_mutex_init(&mymutex,NULL); pthread_create(&tid0,NULL,f,&info0); pthread_create(&tid1,NULL,f,&info1); pthread_join(tid0,NULL); pthread_join(tid1,NULL); exit(0); } // main /* Don't forget to compile with gcc -lpthread */