Reputation: 1237
I have a homework where i need to implement thread synchronization. During implementation i was concerned if pthread_cond_wait()
also locks mutex if it spuriously wakes up and not just if it successfully wakes up.
The task is a worker/delivery problem where there are worker threads and management threads which provide orders for the workers. For this purpose there is an order list from which the workers get orders and the management thread deposits orders. The order list is a shared object and needs to be synchronized.
I thought for this problem i need a monitor for the list to protect it from accesses on emptiness or from deposits when its full.
void deposit_order(order_list* ol, order* o){
pthread_mutex_lock(&(ol->mut_order_access));
while(get_count(ol) >= MAX_ORDERS) {
pthread_cond_wait(&(ol->cond_not_full), &(ol->mut_order_access));
}
ol->orders[ol->head] = o;
ol->head = (ol->head+1)%MAX_ORDERS;
ol->count++;
pthread_cond_signal(&(ol->cond_not_empty));
pthread_mutex_unlock(&(ol->mut_order_access));
}
order* get_order(order_list* ol) {
pthread_mutex_lock(&(ol->mut_order_access));
while(get_count(ol) <= 0) {
pthread_cond_wait(&(ol->cond_not_empty), &(ol->mut_order_access));
}
order* o;
o = ol->orders[ol->tail];
ol->tail = (ol->tail+1)%MAX_ORDERS;
ol->count--;
pthread_cond_signal(&(ol->cond_not_full));
pthread_mutex_unlock(&(ol->mut_order_access));
return o;
}
I believe it is not that important what the structures contain since the topic is how to synchronize the access. Obviously the structure order_list
holds a mutex
and two condition variables to signal the other thread. So if a worker removes a task from the list, it signals "not empty" to the management thread so it can deposit an additional order. If the management deposits an order is signals "not empty" to the worker threads so one thread can remove an order from the list.
So far so good but now i think there is that one event where the above solution may be critical and that is a "spurious wakeup". From this thread i learned that a thread can not spuriously wakeup if the corresponding mutex namely mut_order_access
is locked by another thread. But what if there is for example only one order in the list so that get_count(ol) >= MAX_ORDERS
is not fulfilled and a thread spuriously wakes up from the wait, checks the condition and marks it as not true and jumps out of the loop. Then another thread receives the signal and wakes up normally locking the mutex after the previous thread is already in the critical area. So now both threads would be in the critical area which would be a failure.
So the above could only happen if a thread does not lock the mutex when it spuriously wakes up so does it lock the mutex on spurious wakeup or not?
Upvotes: 1
Views: 470
Reputation: 215517
Your understanding of the conditions of spurious wakeup seems incorrect. Spurious wakeup has nothing to do with whether the mutex is locked by another thread. Unless you have a programming error (breaking the contracts of these functions, general memory corruption or other undefined behavior, etc.), pthread_cond_wait
can never return without the mutex being held (locked) by the calling thread. In the event of a spurious wake, it still can't return until the mutex is re-acquired. Even in the event the waiter is cancelled with pthread_cancel
, the cancellation cleanup handler cannot begin running until the mutex is re-acquired.
Upvotes: 4
Reputation: 182837
A function that might return with a mutex locked or unlocked and that gave you no way to tell the difference would be entirely unusable. How could you possibly know whether to unlock the mutex or not?
The pthread_cond_wait
function provides an atomic "unlock and wait" operation. It always re-acquires the mutex before returning. Assuming you don't violate any of its pre-conditions, of course.
You can think of it as a three-step process:
Only when all three steps are accomplished does pthread_cond_wait
return. A spurious wakeup occurs when the wait ends without another thread sending a signal.
Upvotes: 3