Use atomics in __cxa_guard functions

Similar to SingletonPtr, use atomic accesses when loading the guard word
outside the lock, and when storing, to ensure no races for threads that
don't take the lock.

Lack of atomics unlikely to be a problem in current builds, but code
could conceivably be subject to reordering if link-time optimisation was
enabled.
pull/9530/head
Kevin Bracey 2019-01-29 11:48:40 +02:00
parent 6e41d6cdb7
commit c55329157a
1 changed files with 11 additions and 8 deletions

View File

@ -1426,32 +1426,35 @@ extern "C" void __env_unlock(struct _reent *_r)
extern "C" int __cxa_guard_acquire(int *guard_object_p)
{
uint8_t *guard_object = (uint8_t *)guard_object_p;
if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
if ((core_util_atomic_load_u8(guard_object) & CXA_GUARD_MASK) == CXA_GUARD_INIT_DONE) {
return 0;
}
singleton_lock();
if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
uint8_t guard = *guard_object;
if ((guard & CXA_GUARD_MASK) == CXA_GUARD_INIT_DONE) {
singleton_unlock();
return 0;
}
MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK));
*guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS;
MBED_ASSERT((guard & CXA_GUARD_MASK) == 0);
core_util_atomic_store_u8(guard_object, guard | CXA_GUARD_INIT_IN_PROGRESS);
return 1;
}
extern "C" void __cxa_guard_release(int *guard_object_p)
{
uint8_t *guard_object = (uint8_t *)guard_object_p;
MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
*guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE;
uint8_t guard = *guard_object;
MBED_ASSERT((guard & CXA_GUARD_MASK) == CXA_GUARD_INIT_IN_PROGRESS);
core_util_atomic_store_u8(guard_object, (guard & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE);
singleton_unlock();
}
extern "C" void __cxa_guard_abort(int *guard_object_p)
{
uint8_t *guard_object = (uint8_t *)guard_object_p;
MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
*guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS;
uint8_t guard = *guard_object;
MBED_ASSERT((guard & CXA_GUARD_MASK) == CXA_GUARD_INIT_IN_PROGRESS);
core_util_atomic_store_u8(guard_object, guard & ~CXA_GUARD_INIT_IN_PROGRESS);
singleton_unlock();
}