About the usage of pthread_cond_wait - c

I'm trying to wrap my head around pthread condition variables.
I've seen some code examples that use pthread_cond_wait and pthread_cond_signal and all of them look like this:
while (condition)
{
// Assume that the mutex is locked before the following call
pthread_cond_wait(&cond, &mutex);
}
Is there a reason for using a while loop on the condition? why not just use a single if statement?

Spurious wakeups.
See Why does pthread_cond_wait have spurious wakeups? and also https://en.wikipedia.org/wiki/Spurious_wakeup:
Spurious wakeup describes a complication in the use of condition variables as provided by certain multithreading APIs such as POSIX
Threads and the Windows API.
Even after a condition variable appears to have been signaled from a
waiting thread's point of view, the condition that was awaited may
still be false. One of the reasons for this is a spurious wakeup; that
is, a thread might be awoken from its waiting state even though no
thread signaled the condition variable. For correctness it is
necessary, then, to verify that the condition is indeed true after the
thread has finished waiting. Because spurious wakeup can happen
repeatedly, this is achieved by waiting inside a loop that terminates
when the condition is true ...

I believe this is because threads may be spuriously woken up before the condition is met. Man, talk about "gotcha's".
From the Open Group documentation:
"Spurious wakeups from the pthread_cond_wait() or pthread_cond_timedwait() functions may occur."
Source:
http://pubs.opengroup.org/onlinepubs/007908775/xsh/pthread_cond_wait.html

Is there a reason for using a while loop on the condition? why not just use a single if statement?
The idea behind condition variables is to suspend thread execution until a given condition is satisfied. The condition is not built into the variable, however -- it must be provided by the programmer.
If the relevant condition is already satisfied, then there is no need to suspend operation. The key here, however, is that when the thread resumes, the condition might still not be satisfied, either because something changed between the condition variable being signaled and the thread being able to proceed, or because the thread awoke spurriously (this is allowed to happen, though it rarely does). The program therefore checks the condition again upon every wakeup to see whether it must resume waiting.

Related

I can't create a pthread_cond

I'm tryng to do the Dining philosophers, and in my code, after a thread drop the stick, they also send a broadcast to all thread waiting in the while loop, to move foward, but apparently this is not happening and I don't know way
https://github.com/lucizzz/Philosophers/blob/main/dinning.c
Your code has a lot of bugs, but the most fundamental one is that you access shared state without holding the mutex that protects that state. For example, the while loop in routine_1 tests the stick array without holding the mutex. It even calls pthread_cond_wait without holding the mutex.
This is wrong for many reasons, but the most obvious is this -- what if the while loop decides to call pthread_cond_wait, but then before you call pthread_cond_wait, the thread holding the resources releases it. Now, you are calling pthread_cond_wait to wait for something that has already happened -- you will be waiting forever.
You must hold the mutex both when you decide whether to call pthread_cond_wait and when you actually do call pthread_cond_wait or your code will wait forever if a thread releases the resource before you were able to wait for it.
Fundamentally, the whole point of condition variables is to provide an atomic "unlock and wait" operation to avoid this race condition. But your code doesn't use the mutexes correctly.

What will be the behavior of a while loop that encloses pthread_cond_wait?

I would like to know what happens with the while after a waiting thread is waked.
To avoid 'spurious wake-ups', the pthreads documentation points out that you need to use pthread_cond_wait inside a while statement.
So, when the pthread_cond_wait is called, the calling thread is blocked. And after signaled, the thread resume inside the while.
On my code, I'm handling a pthread_cond_wait() this way:
pthread_mutex_lock(&waiting_call_lock);
while(1) {
pthread_cond_wait(&queue_cond[thread_ctx], &waiting_call_lock);
break;
}
pthread_mutex_unlock(&waiting_call_lock);
The question is, it will try to enter the while again or somehow it break the while and go on? Or, in that case, the break after the pthread_cond_wait() is necessary?
To get this right, I think it is best to start with asking yourself: "what is the thread waiting for?"
The answer should not be "it should wait until another thread signals it", because the way condition variables work is assuming you have something else, some kind of mutex-protected information, that the thread is to wait for.
To illustrate this I will invent an example here where the thread is supposed to wait until a variable called counter is larger than 7. The variable counter is accessible by multiple threads and is protected by a mutex that I will call theMutex. Then the code involving the pthread_cond_wait call could look like this:
pthread_mutex_lock(&theMutex);
while(counter <= 7) {
pthread_cond_wait(&cond, &theMutex);
}
pthread_mutex_unlock(&theMutex);
Now, if a "spurious wake-up" were to happen, the program will check the condition (counter <= 7) again and find it is still not satisfied, so it will stay in the loop and call pthread_cond_wait again. So this ensures that the thread will not proceed past the while loop until the condition is satisfied.
Since spurious wake-ups rarely happen in practice, it may be of interest to trigger that to check that your implementation works properly; here is a discussion about that: How to trigger spurious wake-up within a Linux application?

What if a condition variable signals to a locked thread?

In the (pseudo-)code below, cond might wake up while it shouldn't, for whatever reason. So I put a while loop there. When it does wake up, it will still consume the lock, so it is guaranteed that in out() only one thread is doing its job.
But what happens if, while there is a spurious wake-up in out(), at the same time in() signals to out(), however at that very moment out() is already locked because of the spurious wake-up. So what happens if the cond signals to a locked thread?
in()
inLock.lock()
isEmpty = false
cond.signal()
inLock.unlock()
out()
outLock.lock()
while isEmpty
cond.wait(outLock)
isEmpty = true
outLock.unlock()
NOTE
Well, to be 100% safe, I know I can use a single mutex for both in() and out(), but the data structure I'm using is 100% safe when input and output happens at the same time; it is a type of a queue. And I think it is a performance compromise to block anything reading out from the queue while filling in some new data or vice versa.
I did consider using semaphores, but the problems is that so many C and C++ libraries don't implement semaphores for whatever reason.
You have to use the same mutex when the in() thread sets isEmpty = false and the out() thread tests while (isEmpty). Otherwise, this can happen:
out() thread tests isEmpty, finds it is true;
in() thread sets isEmpty to false and signals the condition variable (but no-one wakes up, beacuse no-one is waiting yet);
out() thread calls cond.wait() and blocks forever, despite the fact that the queue is not empty anymore.
Note that in this sequence there hasn't been a spurious wakeup - it's just a plain old race condition.
As long as you update isEmpty with the same mutex held as when you test isEmpty, this interleaving can't happen.
So what happens if the cond signals to a locked thread?
The signal is lost forever. If no threads are waiting for the signal when pthread_cond_signal is called, then pthread_cond_signal does nothing.
Since isEmpty is being read and modified by two different threads, it is an error to access it unprotected. This is essentially what you are doing when you allow in and out to use different lock instances.
Using different lock instances on the same condition variable is a violation of the POSIX API for pthread_cond_wait() (emphasis mine).
The effect of using more than one mutex for concurrent pthread_cond_wait() or pthread_cond_timedwait() operations on the same condition variable is undefined; that is, a condition variable becomes bound to a unique mutex when a thread waits on the condition variable, and this (dynamic) binding ends when the wait returns.

pthread condition loop

The typical pattern I've seen for using pthread_cond_wait is:
pthread_mutex_lock(&lock);
while (!test)
pthread_cond_wait(&condition, &lock);
pthread_mutex_unlock(&lock);
Why can't an if statement be used instead of a while loop.
pthread_mutex_lock(&lock);
if (!test)
pthread_cond_wait(&condition, &lock);
pthread_mutex_unlock(&lock);
http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html
When using condition variables there is always a Boolean predicate involving shared variables associated with each condition wait that is true if the thread should proceed. Spurious wakeups from the pthread_cond_timedwait() or pthread_cond_wait() functions may occur. Since the return from pthread_cond_timedwait() or pthread_cond_wait() does not imply anything about the value of this predicate, the predicate should be re-evaluated upon such return.
The while loop is a very standard way of re-evaluating the predicate, as required by POSIX.
The if is possible but rarely used. You just would have to be sure that the state of your application is as you come out of the wait. Usually you would have to ensure that you'd only use pthread_cond_signal at the other end (and not broadcast), e.g.
There are two reasons. One is spurious wakeups, as mentioned in other answers. The other is real wakeups. Imagine this:
You have two threads, A and B, blocked on the same condition variable that protects a queue, the queue is empty. Some thread puts a job on the queue, waking thread A. Another thread puts a job on the queue, waking thread B. Thread A starts running first, and does the first job. It gets back to the if and sees that the condition is still true (since there's a second job), so it does that job too. Now thread B gets the processor, returning from pthread_cond_wait, but the predicate is not false, since the queue is empty.
You only know that the predicate was true when some other thread asked that you be woken up. You have no way to know that it will still be true when you finally do get scheduled and are able to re-acquire the mutex.

concurrent threads in C programming

I have encountered a problem while implementing wait and signal conditions on multiple threads.
A thread needs to lock a mutex and wait on a condition variable until some other thread signals it. In the meanwhile, another thread locks the same mutex and waits on the same condition variable. Now, the thread which is running concurrently throughout the process signals the condition variable but I want only the first thread that is waiting must be signalled and not the others.
If two threads wait on the same condition variable, they must be prepared to handle the same conditions, or you must carefully construct your program so they are never waiting on the condition variable at the same time.
Why does this notification have to be handled by the first thread and not the second?
You may be better off with two separate condition variables.
Use pthread_cond_signal() to wake up one of the threads.
However, more than one might be awoken; this is termed spurious wakeup. You need a variable to track your application state, as described in the manual page linked above.
Your requirement is impossible. You say "... I want only the first thread that is waiting must be signalled and not the others." But condition variables never, ever provide any way to ensure a thread isn't signaled. So if you have a requirement that a thread must not be signaled, you cannot use condition variables.
You must always use a condition variable like this:
while(NotSupposedToRun)
pthread_cond_wait(...);
So if the thread wakes up when it's not supposed to, the while is still false and the thread just goes back to sleep. This is mandatory because POSIX does not ever provide any guarantee that a thread won't be woken. An implementation is perfectly free to implement pthread_cond_signal as a call to pthread_cond_broadcast and unblock all threads on every signal if it wants to.
Because condition variables are stateless, the implementation never knows whether a thread is supposed to be woken or not for sure. It is your job to call pthread_cond_wait always, and only, when a thread should not be running.
See
http://en.wikipedia.org/wiki/Spurious_wakeup
for more details.
If you cannot precisely specify the wakeup conditions for each thread in a while loop like the one above, you should not be using condition variables.

Resources