Skip to content

Commit 0fb2870

Browse files
author
Cruz Monrreal
authored
Merge pull request #9530 from kjbracey-arm/atomic_singletonptr
Use atomics for double-checked locks (SingletonPtr + __cxa_guard)
2 parents c9e00cf + 6e3c492 commit 0fb2870

File tree

2 files changed

+23
-16
lines changed

2 files changed

+23
-16
lines changed

platform/SingletonPtr.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <stdint.h>
2929
#include <new>
3030
#include "platform/mbed_assert.h"
31+
#include "platform/mbed_critical.h"
3132
#ifdef MBED_CONF_RTOS_PRESENT
3233
#include "cmsis_os2.h"
3334
#endif
@@ -92,17 +93,20 @@ struct SingletonPtr {
9293
*/
9394
T *get() const
9495
{
95-
if (NULL == _ptr) {
96+
T *p = static_cast<T *>(core_util_atomic_load_ptr(&_ptr));
97+
if (p == NULL) {
9698
singleton_lock();
97-
if (NULL == _ptr) {
98-
_ptr = new (_data) T();
99+
p = static_cast<T *>(_ptr);
100+
if (p == NULL) {
101+
p = new (_data) T();
102+
core_util_atomic_store_ptr(&_ptr, p);
99103
}
100104
singleton_unlock();
101105
}
102106
// _ptr was not zero initialized or was
103107
// corrupted if this assert is hit
104-
MBED_ASSERT(_ptr == (T *)&_data);
105-
return _ptr;
108+
MBED_ASSERT(p == reinterpret_cast<T *>(&_data));
109+
return p;
106110
}
107111

108112
/** Get a pointer to the underlying singleton
@@ -126,7 +130,7 @@ struct SingletonPtr {
126130
}
127131

128132
// This is zero initialized when in global scope
129-
mutable T *_ptr;
133+
mutable void *_ptr;
130134
#if __cplusplus >= 201103L
131135
// Align data appropriately
132136
alignas(T) mutable char _data[sizeof(T)];

platform/mbed_retarget.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,7 @@ extern "C" void __env_unlock(struct _reent *_r)
14171417

14181418
#endif
14191419

1420-
#if defined (__GNUC__) || defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
1420+
#if defined (__GNUC__) || defined (__ARMCC_VERSION)
14211421

14221422
#define CXA_GUARD_INIT_DONE (1 << 0)
14231423
#define CXA_GUARD_INIT_IN_PROGRESS (1 << 1)
@@ -1426,38 +1426,41 @@ extern "C" void __env_unlock(struct _reent *_r)
14261426
extern "C" int __cxa_guard_acquire(int *guard_object_p)
14271427
{
14281428
uint8_t *guard_object = (uint8_t *)guard_object_p;
1429-
if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
1429+
if ((core_util_atomic_load_u8(guard_object) & CXA_GUARD_MASK) == CXA_GUARD_INIT_DONE) {
14301430
return 0;
14311431
}
14321432
singleton_lock();
1433-
if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
1433+
uint8_t guard = *guard_object;
1434+
if ((guard & CXA_GUARD_MASK) == CXA_GUARD_INIT_DONE) {
14341435
singleton_unlock();
14351436
return 0;
14361437
}
1437-
MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK));
1438-
*guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS;
1438+
MBED_ASSERT((guard & CXA_GUARD_MASK) == 0);
1439+
core_util_atomic_store_u8(guard_object, guard | CXA_GUARD_INIT_IN_PROGRESS);
14391440
return 1;
14401441
}
14411442

14421443
extern "C" void __cxa_guard_release(int *guard_object_p)
14431444
{
14441445
uint8_t *guard_object = (uint8_t *)guard_object_p;
1445-
MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
1446-
*guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE;
1446+
uint8_t guard = *guard_object;
1447+
MBED_ASSERT((guard & CXA_GUARD_MASK) == CXA_GUARD_INIT_IN_PROGRESS);
1448+
core_util_atomic_store_u8(guard_object, (guard & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE);
14471449
singleton_unlock();
14481450
}
14491451

14501452
extern "C" void __cxa_guard_abort(int *guard_object_p)
14511453
{
14521454
uint8_t *guard_object = (uint8_t *)guard_object_p;
1453-
MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
1454-
*guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS;
1455+
uint8_t guard = *guard_object;
1456+
MBED_ASSERT((guard & CXA_GUARD_MASK) == CXA_GUARD_INIT_IN_PROGRESS);
1457+
core_util_atomic_store_u8(guard_object, guard & ~CXA_GUARD_INIT_IN_PROGRESS);
14551458
singleton_unlock();
14561459
}
14571460

14581461
#endif
14591462

1460-
#if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)))
1463+
#if defined(MBED_MEM_TRACING_ENABLED) && (defined(__ARMCC_VERSION) || defined(__ICCARM__))
14611464

14621465
// If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp
14631466
// provide the implementation for these. Note: this needs to use the wrappers

0 commit comments

Comments
 (0)