Cheers,
I have 2 threads causing logical deadlock => d_santa and d_patuljak (sorry some pieces are written in Croatian and I didn't have the time to translate)
d_santa does this
void d_santa(){ //dodati join!!!
int j;
pthread_mutex_lock(&m);
while(1){
pthread_cond_wait(&u_santa,&m);
if ((br_sob==10)&&(br_patuljak)){
printf ("Dajem poklone i rijesavam se sobova\n");
pthread_cond_broadcast(&u_sob);
sleep(2);
for (j=2; j<=11; j++){
printf ("Pokusavam brisat sob na %d\n",j);
pthread_join(thred[j],NULL);
br_sob--;
printf ("broj sobova=%d\n",br_sob);
}
}
if (br_sob==10){
printf("Hrani nezahvalnu bagru\n");
sleep(2);
}
if ((br_patuljak%3)==0){
pthread_cond_broadcast(&u_patuljak);
printf ("Rijesi problem patuljaka\n");
sleep(1);
for (j=0; j<3; j++){
br_ulaz++;
printf("Oslobađam dretvu %d\n",H_ULAZ);
pthread_join(thred[H_ULAZ],NULL);
br_patuljak--;
}
}
}
pthread_mutex_unlock(&m);
}
and d_patuljak does this
void d_patuljak(){ //zavrsi implementaciju proizvodac potrosac
pthread_mutex_lock(&m);
br_patuljak++;
printf ("Nastao je patuljak %d\n",br_patuljak);
while(br_patuljak<3){
pthread_cond_wait(&u_patuljak,&m);
}
printf ("Patuljak se oslobodio\n");
if (br_patuljak==3){
pthread_cond_signal(&u_santa);
}
pthread_mutex_unlock(&m);
}
Here's also d_sob if it helps
void d_sob(){ //dobar
int id;
pthread_mutex_lock(&m);
id=br_sob+2;
br_sob++;
printf ("Nastao je sob %d\n",br_sob);
while(br_sob<10){
pthread_cond_wait(&u_sob,&m);
}
pthread_cond_signal(&u_santa);
printf ("Sob ceka slobodu %d, a za analizu br_sob=%d\n",id,br_sob);
pthread_mutex_unlock(&m);
}
The task: d_santa is created only once and always remains sleeping or doing something "useful" while d_patuljak keeps being created and when a group 3 is created they wake up santa so he could help them solve all their problems (note if d_patuljak is created fast there can be more than 3 patuljaks but santa takes only a group of 3!!). Similiar for sob they keep being created until they reach a number of 10 afterwards they can be broadcasted (there can't be 11 of them)
My solution (thoughts): I'll create 1,2,3 patuljaks each having their own location in an array. When patuljak 3 is created he will wake up santa (also bypass pthread_cond_wait)! Santa will wake up and call 3 consecutive pthread_cond_signals to release patuljak 1, patuljak 2 then patuljak 3 => note: patuljak 1 is released to end his thread then be 'destroyed' by pthread_join which I placed right below pthread_cond_signal!!
The problem: pthread_join(patuljak 1) keeps waiting for patuljak 1 which means pthread_cond_signal didn't manage to release patuljak 1 (perhaps patuljak 2 or 3)? I don't know a way to solve this problem is there a way of knowing what will be released or maybe how to release exactly patuljak 1,2,3? I'd use broadcast but I can't patuljak 4 will be released and santa should take only groups of 3. EDIT: I switched pthread_cond_signal with pthread_cond_broadcast for patuljaks the problem didn't go away.
Anyway the programme is hell bigger than this I have a similiar problem with raindeers(=sob) which I can and tried to broadcast but they also get stuck at pthread_join, I have a feeling if the problem with patuljaks is solved the same will follow for raindeers (patuljak=>dwarf) xd.
Two rules will resolve these kinds of problems:
Only call
pthread_cond_signal
when any thread that might be waiting on the condition variable can do whatever it is that needs to get done. Otherwise, always callpthread_cond_broadcast
. When in doubt, callpthread_cond_broadcast
, as it is always safe.Always call
pthread_cond_wait
inside a loop that callspthread_cond_wait
again in the event of a spurious wakeup. You must design your code so that "extra" wakeups are harmless and threads just go back to sleep if they wake up when they "shouldn't".