When I wake up a thread waiting on a condition variable while holding the corresponding mutex, can I assume that the woken thread will run after I release the mutex and before anyone else (myself included) can lock the mutex again? Or can I only be sure that it will run at some point in the future?
To be precise, assume that I have the following functions.
bool taken = false;
int waiting = 0;
pthread_mutex_t m; // properly initialised elsewhere
pthread_cond_t c;
void enter() {
pthread_mutex_lock(&m);
// Is `taken || (waiting == 0)` guaranteed here?
while (taken) {
++ waiting;
pthread_cond_wait(&c, &m);
-- waiting;
}
taken = true;
pthread_mutex_unlock(&m);
}
void leave() {
pthread_mutex_lock(&m);
taken = false;
if (waiting > 0) {
pthread_cond_signal(&c);
}
pthread_mutex_unlock(&m);
}
(This is a toy example, not meant to be useful.)
Also assume that all threads are using these functions as
enter()
// some work here
leave()
Can I then be sure that directly after acquiring the mutex in enter()
(see comment in the code), if taken
is false waiting
has to be zero? [It seems to me that this should be the case, because the woken thread will assume to find the state that the waking thread has left behind (if the wake-up was not spurious) and this could otherwise not be guaranteed, but I did not find it clearly worded anywhere.]
I am mainly interested in the behaviour on (modern) Linux, but of course knowing whether this is defined by POSIX would also be of interest.
Note: This may have already been asked in another question, but I hope that mine is clearer.
After t0
does pthread_cond_signal
, t1
is no longer waiting for the condition variable, but it is also not running, because t0
still holds the mutex; t1
is instead waiting for the mutex. The thread t2
may also be waiting for the mutex, at the beginning of enter()
. Now t0
releases the mutex. Both t1
and t2
are waiting for it. Is t1
handled in a special way and guaranteed to get it, or could t2
get it instead?