c++multithreadingpthreadslanguage-lawyermemory-barriers

Does a pthread_cond_signal or pthread_cond_broadcast call imply a write memory barrier?


Condition variables are generally used such that the state they refer to is modified under a mutex. However, when the state is just a single set-only flag, there's no need for a mutex to prevent simultaneous execution. So one might want to do something like this:

flag = 1;
pthread_cond_broadcast(&cvar);

However, this is only safe if pthread_cond_broadcast implies a write memory barrier; otherwise, the waiting thread may see the condition variable broadcast before the flag write. That is, the waiting thread may awaken, consume the cvar signal, but see the flag still 0.

So, my question is: Do the pthread_cond_broadcast and pthread_cond_signal calls imply a write memory barrier? If so, where is this specified in the relevant POSIX (or other) specifications? The spec seemed unclear on this point.

Note: I am aware that, in practice, this does result in a memory barrier (on Linux, because thread awakening implies a full CPU memory barrier, and the cross-library function call implies a compiler memory barrier). However, I'm interested here in what the spec guarentees.


Solution

  • Regardless of whether it implies a memory barrier, the code is still not correct. Consider the read side:

    while (flag == 0)
        pthread_cond_wait(&cvar, &mutex);
    

    If the read side is suspended between testing flag == 0 and executing the wait, the write side can execute the flag = 1; pthread_cond_signal(&cvar);. The read side will then miss the wakeup entirely - it will wait forever. Remember that wakeups are not queued - if there's no waiter when the condition variable is signalled, the signal has no effect. To avoid this, the write side needs to lock the mutex anyway.