How does the pthread_cond_wait() actually work? - c

So the idea of pthread_cond_wait() is that it will unlock the mutex and wait for the condition.
Lets suppose that you would manually unlock the mutex first and then wait for a condition. Within that timeframe, between those two operations, you have to assume that something bad can happen, another thread will lock the mutex, which is not good. The same goes for if you first wait and then unlock, that is not possible.
So, here comes my question:
how does pthread_cond_wait() actually work?
The thread calls the function and passes a locked mutex and therafter waits on the condition to settle?
How does another thread then modify the variable, if it is already locked by this thread?
My first thought was, that the mutex has to be recursive, however being recursive only allows the same thread to lock the mutex multiple times.

Not sure why I haven't just google the specification for the pthread_cond_wait().
I guess I didn't completely know what my question will turn out to be, when I started.
Anyways the answer to my question can be found here: http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_wait.html

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.

pthread_cond_broadcast before and after one pthread_mutex_unlock

For the code below, the mutex will not available by the time second cond_broadcast is executed(assuming multiple threads already waiting on the condition). In such situation, does the broadcast select the thread(waiting on the condition) to hand the mutex to and wait for the mutex to be unlocked by some other thread or the second cond_broadcast is just ignored?
void* func(void* arg){
pthread_mutex_lock(&m);
while(condition){
pthread_cond_wait(&c,&m);
}
pthread_cond_broadcast(&c);
pthread_mutex_unlock(&m);
pthread_cond_broadcast(&c);
}
For the code below, the mutex will not available by the time second
cond_broadcast is executed(assuming multiple threads already waiting
on the condition).
I think you mean that the mutex will not be available to the thread calling pthread_cond_broadcast() at the second call to that function, but that's irrelevant. Calling pthread_cond_broadcast() is independent of holding any mutex.
Or perhaps you mean that one of the previously blocked threads will have acquired the mutex by the time the second broadcast happens, but (1) that's not certain, and (2) if it does happen, that has no particular significance with respect to the broadcast.
In such situation, does the broadcast select the
thread(waiting on the condition) to hand the mutex to and wait for the
mutex to be unlocked by some other thread or the second cond_broadcast
is just ignored?
Neither. pthread_cond_broadcast() and pthread_cond_signal() have no role in locking or transferring control of any mutex. They just wake threads blocked on the associated CV. That each such thread must acquire the mutex before returning from the call is a separate consideration -- they all contend normally to lock the mutex, and they do not return from pthread_cond_wait() until they do. They also do not go back to waiting without first returning from their wait and then calling pthread_cond_wait() again.
But that does not mean that the second pthread_cond_broadcast() in your code necessarily will have no effect. One of the just-woken threads might loop around and wait on the CV again between the two calls, or some other thread might arrive at the CV. That becomes possible as soon as the first thread releases the mutex, and the fact that the first thing that thread tries to do is another broadcast does not ensure that the broadcast happens before another thread can start waiting.
It is unlikely that you want two broadcasts one after the other like that, but which one you retain has little, if any, effect on the overall semantics of the program.

Why do I get EBUSY when trying to pthread_mutex_destroy?

Right before exiting, I call from the main() in the following order to:
pthread_cancel() other threads uses mtx which are "waiting" (They are waiting for other cond_variable and mutex. Maybe that's the problem?
pthread_cond_destroy(&cnd) (which is "coupled" whith mtx)
pthread_mutex_unlock(&mtx)
pthread_mutex_destroy(&mtx)
However, the last function results EBUSY. Each time another thread uses the mutex it almost immediately release it. Also, as mentioned, I kill all those threads before trying to destroy the mutex.
Why is it happening?
As per man pthread_mutex_destroy:
The pthread_mutex_destroy() function may fail if:
EBUSY
The implementation has detected an attempt to destroy the object referenced by mutex while it is locked or referenced (for example,
while being used in a pthread_cond_timedwait() or pthread_cond_wait())
by another thread.
Check if the mutex is not used by another thread when you try to destroy it.
pthread_cancel() other threads uses mtx which are "waiting" (They are waiting for other cond_variable and mutex.
Cancellation is running asynchronously to the cancelling process, that is pthread_cancel() might very well return before the thread to be cancelled ended.
This results in resources (mutexes, conditions, ...) used by the thread to be cancelled perhaps still being in use when immediately calling pthread_mutex_destroy() afterwards.
The only way to test whether cancellation succeeded it to call pthread_join()on the cancelled thread and expect it to return PTHREAD_CANCELED. This implies that the thread to be cancelled wasn't detached.
Here you see one possible issue with cancelling threads. There are others. Simply avoid all this by not using pthread_cancel(), but implement a proper design ending all threads in well defined manner.

Is it correct to call pthread_cond_wait() and pthread_cond_timedwait() on the same condvar by different threads?

I'm trying to understand how pthread_cond_broadcast() works and whether is possible to "attach" thread to the waiting list (or queue) of event (broadcast signal) that already blocked by another thread.
Let's assume that we have two threads.
Thread #1 in a waiting loop
pthread_mutex_lock();
while(condition_is_false)
pthread_cond_wait();
pthread_mutex_unlock();
And somewhere in the middle of this process when thread #1 already blocked then another thread #2 calls the same or almost the same code in hope to be "attached" to the same condvar:
pthread_mutex_lock();
while(condition_is_false)
pthread_cond_wait(); or pthread_cond_timedwait()
pthread_mutex_unlock();
As I understand thread #2 would not get access to the code locked by mutex until it will unlocked. Am I right?
I'm trying to implement next case: There are some tasks which required a time to be done. During that time another thread(s) not allowed to duplicate the same task that already in a progress but wait until it will finished. And when task will finally finished then all threads must get the same result.
Your scenario is exactly the one for which condition variables are designed.
There is no problem for the second thread to achieve the lock on the mutex, because wait (and derivative) releases the mutex temporarily during wait and re-acquires it when coming back.
You should definitively read more in the abundant documentation about the concept of mutex and condition variables.

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