Reputation: 1811
Is it possible (in theory) for a thread to execute an acquire
on one CPU, then immediately get preempted and resumed on another CPU for which the acquire
was never executed (and therefore never synchronized per the release-acquire semantics)?
For ex. consider the following code which uses C++11 atomics and release-acquire
memory-ordering to perform a lock-free thread-safe initialization:
if ( false == _initFlag.load(memory_order_acquire) ) {
_foo = ...; // initialize global
_bar = ...; // initialize global
... = ...; // initialize more globals
_initFlag.store(true, memory_order_release);
}
// use the initialized values ...
If _initFlag.load(memory_order_acquire)
returns true, then the calling thread will know that the initialized values of _foo
, _bar
, etc... are visible (propagated) to the CPU on which it is currently executing. But what if the thread is preempted immediately afterward and moved to another CPU?..
Does the C++11 standard guarantee the new CPU will be synchronized? Are there any implementations or architectures that might be vulnerable to this type of race condition?
Upvotes: 4
Views: 182
Reputation: 9354
It is possible for it to get pre-empted and moved to another CPU after the acquire, but as far as I'm aware, the O/S has to ensure that any explicit memory ordering is preserved (this is probably something it keeps in the thread state). Otherwise, there'd be very little chance of anything running reliably in a multi-cpu environment.
I think the standard assumes that to be the case, on the basis it has to.
Upvotes: 6