N1964: cnd_wait and cnd_timewait should allow spurious wake-ups


Submitter: Torvald Riegel [email protected], Martin Sebor [email protected]
Submission Date: 2015-09-25

Summary

Both ISO C++ and POSIX allow for spurious wake-ups from their condition variable wait functions. However, C11 has no wording that would allow that. (This applies to both cnd_wait and cnd_timewait, but just cnd_wait is referred to in what follows.)

If spurious wake-ups are allowed, then some implementations become significantly easier; it also allows to implement the C standard on top of POSIX using just a thin wrapper. In contrast, implementing a condition variable that does not allow spurious wake-ups on top of a condition variable implementation that does allow that is likely close to implementing a condition variable from scratch in terms of complexity.

Another reason for allowing spurious wake-ups is that to actually exploit having no spurious wake-ups, a program needs to take quite some care to establish the happens-before relations required to make just the return from cnd_wait mean something that can be used to infer something about the then current state of memory (for example, if the wake-up is supposed to also mean that some state has been initialized).

Specifically, the program must make sure that it actually calls cnd_signal (or cnd_broadcast) after cnd_wait has started to block; this can be ensured by calling cnd_signal from a critical section protected by the same mutex as supplied to the respective cnd_wait, and checking the ordering of the cnd_wait and cnd_signal critical sections in some way (e.g., through access to variables protected by the same mutex, or by not letting the signaling thread enter the cnd_signal critical section before the cnd_wait critical section). Second, cnd_wait is not specified to synchronize with cnd_signal, so either cnd_signal must be in such a critical section (ie, there is a second reason for that), or the signaler and the waiter must establish a happens-before relation through other means such as atomics.

Suggested Technical Corrigendum

Change this sentence from the specification of cnd_wait (7.26.3.6p2):

The cnd_wait function atomically unlocks the mutex pointed to by mtx and endeavors to block until the condition variable pointed to by cond is signaled by a call to cnd_signal or to cnd_broadcast.

to this:

The cnd_wait function atomically unlocks the mutex pointed to by mtx and endeavors to block until the condition variable pointed to by cond is signaled by a call to cnd_signal or to cnd_broadcast, or until it is unblocked due to a spurious, unspecified reason.

Likewise for cnd_timedwait.