Why do we need a condition check before pthread_cond_wait Why do we need a condition check before pthread_cond_wait linux linux

Why do we need a condition check before pthread_cond_wait


You need a while loop because the thread that called pthread_cond_wait might wake up even when the condition you are waiting for isn't reached. This phenomenon is called "spurious wakeup".

This is not a bug, it is the way the conditional variables are implemented.

This can also be found in man pages:

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.

Update regarding the actual code:

void* proc_add(void *name) {    struct vars *my_data = (struct vars*)name;    printf("In thread Addition and my id = %d\n",pthread_self());    while(1) {        pthread_mutex_lock(&mutexattr);        while(!my_data->ipt){  // If no input get in            pthread_cond_wait(&mutexaddr_add,&mutexattr);  // Wait till signalled        }        my_data->opt = my_data->a + my_data->b;        my_data->ipt=1;        pthread_cond_signal(&mutexaddr_opt);        pthread_mutex_unlock(&mutexattr);        if(my_data->end)            pthread_exit((void *)0);        }    }}


You must test the condition under the mutex before waiting because signals of the condition variable are not queued (condition variables are not semaphores). That is, if a thread calls pthread_cond_signal() when no threads are blocked in pthread_cond_wait() on that condition variable, then the signal does nothing.

This means that if you had one thread set the condition:

pthread_mutex_lock(&m);cond = true;pthread_cond_signal(&c);pthread_mutex_unlock(&m);

and then another thread unconditionally waited:

pthread_mutex_lock(&m);pthread_cond_wait(&c, &m);/* cond now true */

this second thread would block forever. This is avoided by having the second thread check for the condition:

pthread_mutex_lock(&m);if (!cond)    pthread_cond_wait(&c, &m);/* cond now true */

Since cond is only modified with the mutex m held, this means that the second thread waits if and only if cond is false.

The reason a while () loop is used in robust code instead of an if () is because pthread_cond_wait() does not guarantee that it will not wake up spuriously. Using a while () also means that signalling the condition variable is always perfectly safe - "extra" signals don't affect the program's correctness, which means that you can do things like move the signal outside of the locked section of code.