mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #9530 from kjbracey-arm/atomic_singletonptr
Use atomics for double-checked locks (SingletonPtr + __cxa_guard)pull/9021/head
commit
0fb2870cfc
|
@ -28,6 +28,7 @@
|
|||
#include <stdint.h>
|
||||
#include <new>
|
||||
#include "platform/mbed_assert.h"
|
||||
#include "platform/mbed_critical.h"
|
||||
#ifdef MBED_CONF_RTOS_PRESENT
|
||||
#include "cmsis_os2.h"
|
||||
#endif
|
||||
|
@ -92,17 +93,20 @@ struct SingletonPtr {
|
|||
*/
|
||||
T *get() const
|
||||
{
|
||||
if (NULL == _ptr) {
|
||||
T *p = static_cast<T *>(core_util_atomic_load_ptr(&_ptr));
|
||||
if (p == NULL) {
|
||||
singleton_lock();
|
||||
if (NULL == _ptr) {
|
||||
_ptr = new (_data) T();
|
||||
p = static_cast<T *>(_ptr);
|
||||
if (p == NULL) {
|
||||
p = new (_data) T();
|
||||
core_util_atomic_store_ptr(&_ptr, p);
|
||||
}
|
||||
singleton_unlock();
|
||||
}
|
||||
// _ptr was not zero initialized or was
|
||||
// corrupted if this assert is hit
|
||||
MBED_ASSERT(_ptr == (T *)&_data);
|
||||
return _ptr;
|
||||
MBED_ASSERT(p == reinterpret_cast<T *>(&_data));
|
||||
return p;
|
||||
}
|
||||
|
||||
/** Get a pointer to the underlying singleton
|
||||
|
@ -126,7 +130,7 @@ struct SingletonPtr {
|
|||
}
|
||||
|
||||
// This is zero initialized when in global scope
|
||||
mutable T *_ptr;
|
||||
mutable void *_ptr;
|
||||
#if __cplusplus >= 201103L
|
||||
// Align data appropriately
|
||||
alignas(T) mutable char _data[sizeof(T)];
|
||||
|
|
|
@ -1417,7 +1417,7 @@ extern "C" void __env_unlock(struct _reent *_r)
|
|||
|
||||
#endif
|
||||
|
||||
#if defined (__GNUC__) || defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
|
||||
#if defined (__GNUC__) || defined (__ARMCC_VERSION)
|
||||
|
||||
#define CXA_GUARD_INIT_DONE (1 << 0)
|
||||
#define CXA_GUARD_INIT_IN_PROGRESS (1 << 1)
|
||||
|
@ -1426,38 +1426,41 @@ 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();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)))
|
||||
#if defined(MBED_MEM_TRACING_ENABLED) && (defined(__ARMCC_VERSION) || defined(__ICCARM__))
|
||||
|
||||
// If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp
|
||||
// provide the implementation for these. Note: this needs to use the wrappers
|
||||
|
|
Loading…
Reference in New Issue