So, I’m writing a program for class that runs 4 threads concurrently. I’ve got the program working perfectly, except for the fact that it’s stopping during run-time. I’m not sure if it’s related to the way I have my pthread_cond_wait’s set up, or if its something else. I’ve traced through the program by hand multiple times, and can’t find an explanation.
Here’s my code:
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <stdlib.h>
//#define TENP .1
//#define FIFTP .15
void *tenPercentA();
void *tenPercentB();
void *fiftPercentC();
void *fiftPercentD();
pthread_cond_t aPirate;
pthread_cond_t bPirate;
pthread_cond_t cPirate;
pthread_cond_t dPirate;
pthread_mutex_t mutex;
int pearls = 1000;
int main()
{
pthread_t tid;
pthread_setconcurrency(4);
pthread_create(&tid, NULL, (void *(*)(void *))tenPercentA, NULL);
pthread_create(&tid, NULL, (void *(*)(void *))tenPercentB, NULL);
pthread_create(&tid, NULL, (void *(*)(void *))fiftPercentC, NULL);
pthread_create(&tid, NULL, (void *(*)(void *))fiftPercentD, NULL);
pthread_exit(0);
}
void *tenPercentA(){
int totalA = 0;
double tempA = 0;
while(pearls > 0){
pthread_mutex_lock(&mutex);
if(pearls > 0){
tempA = pearls * .1;
tempA = ceil(tempA);
totalA = totalA + tempA;
pearls = pearls - tempA;
printf("Pirate A stole %1.1f pearls.\n", tempA);
printf("Pirate A's total: %d\n", totalA);
sleep(1);
pthread_cond_broadcast (&bPirate);
pthread_cond_broadcast (&cPirate);
pthread_cond_broadcast (&dPirate);
tempA = 0.0;
}
else{
printf("No more pearls!\n");
exit(0);
}
pthread_mutex_unlock(&mutex);
pthread_cond_wait (&aPirate, &mutex);
}
}
void *tenPercentB(){
int totalB = 0;
double tempB = 0;
while(pearls > 0){
pthread_mutex_lock(&mutex);
if(pearls > 0){
tempB = pearls * .1;
tempB = ceil(tempB);
totalB = totalB + tempB;
pearls = pearls - tempB;
printf("Pirate B stole %1.1f pearls.\n", tempB);
printf("Pirate B's total: %d\n", totalB);
sleep(1);
pthread_cond_broadcast (&aPirate);
pthread_cond_broadcast (&cPirate);
pthread_cond_broadcast (&dPirate);
tempB = 0.0;
}
else{
printf("No more pearls!\n");
exit(0);
}
pthread_mutex_unlock(&mutex);
pthread_cond_wait (&bPirate, &mutex);
}
}
void *fiftPercentC(){
int totalC = 0;
double tempC = 0;
while(pearls > 0){
pthread_mutex_lock(&mutex);
if(pearls > 0){
tempC = pearls * .15;
tempC = ceil(tempC);
totalC = totalC + tempC;
pearls = pearls - tempC;
printf("Pirate C stole %1.1f pearls.\n", tempC);
printf("Pirate C's total: %d\n", totalC);
sleep(1);
pthread_cond_broadcast (&bPirate);
pthread_cond_broadcast (&aPirate);
pthread_cond_broadcast (&dPirate);
tempC = 0.0;
}
else{
printf("No more pearls!\n");
exit(0);
}
pthread_mutex_unlock(&mutex);
pthread_cond_wait (&cPirate, &mutex);
}
}
void *fiftPercentD(){
int totalD = 0;
double tempD = 0;
while(pearls > 0){
pthread_mutex_lock(&mutex);
if(pearls > 0){
tempD = pearls * .15;
tempD = ceil(tempD);
totalD = totalD + tempD;
pearls = pearls - tempD;
printf("Pirate D stole %1.1f pearls.\n", tempD);
printf("Pirate D's total: %d\n", totalD);
sleep(1);
pthread_cond_broadcast (&bPirate);
pthread_cond_broadcast (&cPirate);
pthread_cond_broadcast (&aPirate);
tempD = 0.0;
}
else{
printf("No more pearls!\n");
exit(0);
}
pthread_mutex_unlock(&mutex);
pthread_cond_wait (&dPirate, &mutex);
}
}
And here’s some sample output that it does during run-time:
Pirate A stole 100.0 pearls.
Pirate A's total: 100
Pirate B stole 90.0 pearls.
Pirate B's total: 90
Pirate C stole 122.0 pearls.
Pirate C's total: 122
The only idea I have that might explain it is that the program is getting stuck when the CPU scheduler has two threads ready to run back to back. For example (in the schedule queue): A | B | C | C | D. Any suggestions?
So if all the pirates wait at pthread_condition_wait then when the last pirate steals the last pearls you might find that pearls == 0 and exit the loop. Now you’ll never print your all done condition. And you’ll exit without anything being printed by falling off the end of the program.
That’s why your program is stopping and not printing anything.
Edit: (the above is still true, but isn’t the problem you are seeing at the moment)
From http://linux.die.net/man/3/pthread_cond_wait: