Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 229
bdonlan Avatar asked Dec 16 '22 10:12

bdonlan


2 Answers

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.

like image 66
caf Avatar answered Feb 01 '23 22:02

caf


Under POSIX, if you write to a variable from one thread and read it from another then you must protect it with a mutex. There is no exception made for pthread_cond_broadcast.

If your platform/compiler offer atomic variables then they may make additional guarantees about those. For example, if flag is a C++11 std::atomic<int> then this code is OK.

like image 42
Anthony Williams Avatar answered Feb 01 '23 22:02

Anthony Williams