Skip to content

Commit 827cc51

Browse files
committed
Assembler atomics
Reimplement atomic code in inline assembly. This can improve optimisation, and avoids potential architectural problems with using LDREX/STREX intrinsics. API further extended: * Bitwise operations (fetch_and/fetch_or/fetch_xor) * fetch_add and fetch_sub (like incr/decr, but returning old value - aligning with C++11) * compare_exchange_weak * Explicit memory order specification * Basic freestanding template overloads for C++ This gives our existing C implementation essentially all the functionality needed by C++11. An actual Atomic<T> template based upon these C functions could follow.
1 parent f1e664b commit 827cc51

File tree

33 files changed

+2272
-1098
lines changed

33 files changed

+2272
-1098
lines changed

components/TARGET_PSA/TARGET_MBED_SPM/COMPONENT_SPE/handles_manager.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#include "psa_defs.h"
2121
#include "cmsis_os2.h"
22-
#include "mbed_critical.h"
22+
#include "mbed_atomic.h"
2323
#include "spm_internal.h"
2424
#include "spm_panic.h"
2525
#include "handles_manager.h"

components/TARGET_PSA/TARGET_MBED_SPM/COMPONENT_SPE/spm_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717

1818
#include "cmsis_os2.h"
19-
#include "mbed_critical.h"
19+
#include "mbed_atomic.h"
2020
#include "psa_defs.h"
2121
#include "spm_internal.h"
2222
#include "spm_panic.h"

components/storage/blockdevice/COMPONENT_DATAFLASH/DataFlashBlockDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
#include "DataFlashBlockDevice.h"
18-
#include "mbed_critical.h"
18+
#include "mbed_atomic.h"
1919

2020
#include <inttypes.h>
2121

components/storage/blockdevice/COMPONENT_FLASHIAP/FlashIAPBlockDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#if DEVICE_FLASH
1818

1919
#include "FlashIAPBlockDevice.h"
20-
#include "mbed_critical.h"
20+
#include "mbed_atomic.h"
2121
#include "mbed_error.h"
2222

2323
using namespace mbed;

components/wifi/esp8266-driver/ESP8266Interface.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include "features/netsocket/nsapi_types.h"
2727
#include "mbed_trace.h"
2828
#include "platform/Callback.h"
29-
#include "platform/mbed_critical.h"
29+
#include "platform/mbed_atomic.h"
3030
#include "platform/mbed_debug.h"
3131
#include "platform/mbed_wait_api.h"
3232

features/lorawan/LoRaWANStack.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
#include <stdint.h>
4444
#include "events/EventQueue.h"
45-
#include "platform/mbed_critical.h"
45+
#include "platform/mbed_atomic.h"
4646
#include "platform/Callback.h"
4747
#include "platform/NonCopyable.h"
4848
#include "platform/ScopedLock.h"

features/netsocket/InternetSocket.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
#include "InternetSocket.h"
18+
#include "platform/mbed_critical.h"
1819
#include "platform/Callback.h"
1920

2021
using namespace mbed;

features/netsocket/InternetSocket.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "rtos/Mutex.h"
2626
#include "rtos/EventFlags.h"
2727
#include "Callback.h"
28-
#include "mbed_critical.h"
28+
#include "mbed_atomic.h"
2929
#include "mbed_toolchain.h"
3030
#include "SocketStats.h"
3131

features/storage/blockdevice/BufferedBlockDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#include "BufferedBlockDevice.h"
1818
#include "platform/mbed_assert.h"
19-
#include "platform/mbed_critical.h"
19+
#include "platform/mbed_atomic.h"
2020
#include <algorithm>
2121
#include <string.h>
2222

features/storage/blockdevice/ChainingBlockDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
#include "ChainingBlockDevice.h"
18-
#include "platform/mbed_critical.h"
18+
#include "platform/mbed_atomic.h"
1919
#include "platform/mbed_assert.h"
2020

2121
namespace mbed {

features/storage/blockdevice/ExhaustibleBlockDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
#include "ExhaustibleBlockDevice.h"
18-
#include "platform/mbed_critical.h"
18+
#include "platform/mbed_atomic.h"
1919
#include "platform/mbed_assert.h"
2020

2121
namespace mbed {

features/storage/blockdevice/FlashSimBlockDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#include "FlashSimBlockDevice.h"
1818
#include "platform/mbed_assert.h"
19-
#include "platform/mbed_critical.h"
19+
#include "platform/mbed_atomic.h"
2020
#include <algorithm>
2121
#include <stdlib.h>
2222
#include <string.h>

features/storage/blockdevice/HeapBlockDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
#include "HeapBlockDevice.h"
18-
#include "platform/mbed_critical.h"
18+
#include "platform/mbed_atomic.h"
1919
#include <stdlib.h>
2020
#include <string.h>
2121

features/storage/blockdevice/MBRBlockDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
#include "MBRBlockDevice.h"
18-
#include "platform/mbed_critical.h"
18+
#include "platform/mbed_atomic.h"
1919
#include "platform/mbed_toolchain.h"
2020
#include "platform/mbed_assert.h"
2121
#include <algorithm>

features/storage/nvstore/source/nvstore.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
#include "FlashIAP.h"
2424
#include "SystemStorage.h"
25-
#include "mbed_critical.h"
25+
#include "mbed_atomic.h"
2626
#include "mbed_assert.h"
2727
#include "mbed_error.h"
2828
#include "mbed_wait_api.h"

mbed.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
#include "drivers/InterruptIn.h"
8787
#include "platform/mbed_wait_api.h"
8888
#include "hal/sleep_api.h"
89+
#include "platform/mbed_atomic.h"
8990
#include "platform/mbed_power_mgmt.h"
9091
#include "platform/mbed_rtc_time.h"
9192
#include "platform/mbed_poll.h"

platform/DeepSleepLock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#include <limits.h>
2121
#include "platform/mbed_power_mgmt.h"
22-
#include "platform/mbed_critical.h"
22+
#include "platform/mbed_atomic.h"
2323

2424
namespace mbed {
2525

platform/SharedPtr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include <stdint.h>
2424
#include <stddef.h>
2525

26-
#include "platform/mbed_critical.h"
26+
#include "platform/mbed_atomic.h"
2727

2828
namespace mbed {
2929

platform/SingletonPtr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#include <stdint.h>
2929
#include <new>
3030
#include "platform/mbed_assert.h"
31-
#include "platform/mbed_critical.h"
31+
#include "platform/mbed_atomic.h"
3232
#ifdef MBED_CONF_RTOS_PRESENT
3333
#include "cmsis_os2.h"
3434
#endif

platform/internal/mbed_atomic_impl.c

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/*
2+
* Copyright (c) 2019, ARM Limited, All Rights Reserved
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
* not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "platform/mbed_assert.h"
19+
#include "platform/mbed_atomic.h"
20+
21+
/* Inline bool implementations in the header use uint8_t versions to manipulate the bool */
22+
MBED_STATIC_ASSERT(sizeof(bool) == sizeof(uint8_t), "Surely bool is a byte");
23+
24+
/* Inline implementations in the header use uint32_t versions to manipulate pointers */
25+
MBED_STATIC_ASSERT(sizeof(void *) == sizeof(uint32_t), "Alas, pointers must be 32-bit");
26+
27+
28+
#define DO_MBED_LOCKED_OP(name, OP, retValue, T, fn_suffix) \
29+
T core_util_atomic_##name##_##fn_suffix(volatile T *valuePtr, T arg) \
30+
{ \
31+
T oldValue, newValue; \
32+
core_util_critical_section_enter(); \
33+
oldValue = *valuePtr; \
34+
newValue = OP; \
35+
*valuePtr = newValue; \
36+
core_util_critical_section_exit(); \
37+
return retValue; \
38+
}
39+
40+
#define DO_MBED_LOCKED_CAS_OP(T, fn_suffix) \
41+
bool core_util_atomic_cas_##fn_suffix(volatile T *ptr, T *expectedCurrentValue, T desiredValue) \
42+
{ \
43+
bool success; \
44+
T currentValue; \
45+
core_util_critical_section_enter(); \
46+
currentValue = *ptr; \
47+
if (currentValue == *expectedCurrentValue) { \
48+
*ptr = desiredValue; \
49+
success = true; \
50+
} else { \
51+
*expectedCurrentValue = currentValue; \
52+
success = false; \
53+
} \
54+
core_util_critical_section_exit(); \
55+
return success; \
56+
} \
57+
\
58+
bool core_util_atomic_compare_exchange_weak_##fn_suffix(volatile T *ptr, \
59+
T *expectedCurrentValue, T desiredValue) \
60+
{ \
61+
return core_util_atomic_cas_##fn_suffix(ptr, expectedCurrentValue, desiredValue); \
62+
}
63+
64+
#if MBED_EXCLUSIVE_ACCESS
65+
/* These are the C99 external definitions for the inline functions */
66+
/* We maintain external definitions rather than using "static inline" for backwards binary compatibility
67+
* and to give the compiler plenty of leeway to choose to not inline in both C and C++ modes
68+
*/
69+
70+
extern inline bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr);
71+
72+
extern inline uint8_t core_util_atomic_exchange_u8(volatile uint8_t *valuePtr, uint8_t newValue);
73+
extern inline uint16_t core_util_atomic_exchange_u16(volatile uint16_t *valuePtr, uint16_t newValue);
74+
extern inline uint32_t core_util_atomic_exchange_u32(volatile uint32_t *valuePtr, uint32_t newValue);
75+
extern inline uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t arg);
76+
extern inline uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t arg);
77+
extern inline uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t arg);
78+
extern inline uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t arg);
79+
extern inline uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t arg);
80+
extern inline uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t arg);
81+
extern inline uint8_t core_util_atomic_fetch_add_u8(volatile uint8_t *valuePtr, uint8_t arg);
82+
extern inline uint16_t core_util_atomic_fetch_add_u16(volatile uint16_t *valuePtr, uint16_t arg);
83+
extern inline uint32_t core_util_atomic_fetch_add_u32(volatile uint32_t *valuePtr, uint32_t arg);
84+
extern inline uint8_t core_util_atomic_fetch_sub_u8(volatile uint8_t *valuePtr, uint8_t arg);
85+
extern inline uint16_t core_util_atomic_fetch_sub_u16(volatile uint16_t *valuePtr, uint16_t arg);
86+
extern inline uint32_t core_util_atomic_fetch_sub_u32(volatile uint32_t *valuePtr, uint32_t arg);
87+
extern inline uint8_t core_util_atomic_fetch_and_u8(volatile uint8_t *valuePtr, uint8_t arg);
88+
extern inline uint16_t core_util_atomic_fetch_and_u16(volatile uint16_t *valuePtr, uint16_t arg);
89+
extern inline uint32_t core_util_atomic_fetch_and_u32(volatile uint32_t *valuePtr, uint32_t arg);
90+
extern inline uint8_t core_util_atomic_fetch_or_u8(volatile uint8_t *valuePtr, uint8_t arg);
91+
extern inline uint16_t core_util_atomic_fetch_or_u16(volatile uint16_t *valuePtr, uint16_t arg);
92+
extern inline uint32_t core_util_atomic_fetch_or_u32(volatile uint32_t *valuePtr, uint32_t arg);
93+
extern inline uint8_t core_util_atomic_fetch_xor_u8(volatile uint8_t *valuePtr, uint8_t arg);
94+
extern inline uint16_t core_util_atomic_fetch_xor_u16(volatile uint16_t *valuePtr, uint16_t arg);
95+
extern inline uint32_t core_util_atomic_fetch_xor_u32(volatile uint32_t *valuePtr, uint32_t arg);
96+
extern inline bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue);
97+
extern inline bool core_util_atomic_cas_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue);
98+
extern inline bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue);
99+
extern inline bool core_util_atomic_compare_exchange_weak_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue);
100+
extern inline bool core_util_atomic_compare_exchange_weak_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue);
101+
extern inline bool core_util_atomic_compare_exchange_weak_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue);
102+
103+
extern inline bool core_util_atomic_flag_test_and_set_relaxed(volatile core_util_atomic_flag *flagPtr);
104+
105+
extern inline uint8_t core_util_atomic_exchange_relaxed_u8(volatile uint8_t *valuePtr, uint8_t newValue);
106+
extern inline uint16_t core_util_atomic_exchange_relaxed_u16(volatile uint16_t *valuePtr, uint16_t newValue);
107+
extern inline uint32_t core_util_atomic_exchange_relaxed_u32(volatile uint32_t *valuePtr, uint32_t newValue);
108+
extern inline uint8_t core_util_atomic_incr_relaxed_u8(volatile uint8_t *valuePtr, uint8_t arg);
109+
extern inline uint16_t core_util_atomic_incr_relaxed_u16(volatile uint16_t *valuePtr, uint16_t arg);
110+
extern inline uint32_t core_util_atomic_incr_relaxed_u32(volatile uint32_t *valuePtr, uint32_t arg);
111+
extern inline uint8_t core_util_atomic_decr_relaxed_u8(volatile uint8_t *valuePtr, uint8_t arg);
112+
extern inline uint16_t core_util_atomic_decr_relaxed_u16(volatile uint16_t *valuePtr, uint16_t arg);
113+
extern inline uint32_t core_util_atomic_decr_relaxed_u32(volatile uint32_t *valuePtr, uint32_t arg);
114+
extern inline uint8_t core_util_atomic_fetch_add_relaxed_u8(volatile uint8_t *valuePtr, uint8_t arg);
115+
extern inline uint16_t core_util_atomic_fetch_add_relaxed_u16(volatile uint16_t *valuePtr, uint16_t arg);
116+
extern inline uint32_t core_util_atomic_fetch_add_relaxed_u32(volatile uint32_t *valuePtr, uint32_t arg);
117+
extern inline uint8_t core_util_atomic_fetch_sub_relaxed_u8(volatile uint8_t *valuePtr, uint8_t arg);
118+
extern inline uint16_t core_util_atomic_fetch_sub_relaxed_u16(volatile uint16_t *valuePtr, uint16_t arg);
119+
extern inline uint32_t core_util_atomic_fetch_sub_relaxed_u32(volatile uint32_t *valuePtr, uint32_t arg);
120+
extern inline uint8_t core_util_atomic_fetch_and_relaxed_u8(volatile uint8_t *valuePtr, uint8_t arg);
121+
extern inline uint16_t core_util_atomic_fetch_and_relaxed_u16(volatile uint16_t *valuePtr, uint16_t arg);
122+
extern inline uint32_t core_util_atomic_fetch_and_relaxed_u32(volatile uint32_t *valuePtr, uint32_t arg);
123+
extern inline uint8_t core_util_atomic_fetch_or_relaxed_u8(volatile uint8_t *valuePtr, uint8_t arg);
124+
extern inline uint16_t core_util_atomic_fetch_or_relaxed_u16(volatile uint16_t *valuePtr, uint16_t arg);
125+
extern inline uint32_t core_util_atomic_fetch_or_relaxed_u32(volatile uint32_t *valuePtr, uint32_t arg);
126+
extern inline uint8_t core_util_atomic_fetch_xor_relaxed_u8(volatile uint8_t *valuePtr, uint8_t arg);
127+
extern inline uint16_t core_util_atomic_fetch_xor_relaxed_u16(volatile uint16_t *valuePtr, uint16_t arg);
128+
extern inline uint32_t core_util_atomic_fetch_xor_relaxed_u32(volatile uint32_t *valuePtr, uint32_t arg);
129+
extern inline bool core_util_atomic_cas_relaxed_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue);
130+
extern inline bool core_util_atomic_cas_relaxed_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue);
131+
extern inline bool core_util_atomic_cas_relaxed_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue);
132+
extern inline bool core_util_atomic_compare_exchange_weak_relaxed_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue);
133+
extern inline bool core_util_atomic_compare_exchange_weak_relaxed_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue);
134+
extern inline bool core_util_atomic_compare_exchange_weak_relaxed_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue);
135+
136+
#else
137+
138+
bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr)
139+
{
140+
core_util_critical_section_enter();
141+
uint8_t currentValue = flagPtr->_flag;
142+
flagPtr->_flag = true;
143+
core_util_critical_section_exit();
144+
return currentValue;
145+
}
146+
#endif
147+
148+
/* No architecture we support has LDREXD/STREXD, so must always disable IRQs for 64-bit operations */
149+
uint64_t core_util_atomic_load_u64(const volatile uint64_t *valuePtr)
150+
{
151+
core_util_critical_section_enter();
152+
uint64_t currentValue = *valuePtr;
153+
core_util_critical_section_exit();
154+
return currentValue;
155+
}
156+
157+
void core_util_atomic_store_u64(volatile uint64_t *valuePtr, uint64_t desiredValue)
158+
{
159+
core_util_critical_section_enter();
160+
*valuePtr = desiredValue;
161+
core_util_critical_section_exit();
162+
}
163+
164+
/* Now locked operations for whichever we don't have lock-free ones for */
165+
#if MBED_EXCLUSIVE_ACCESS
166+
/* Just need 64-bit locked operations */
167+
#define DO_MBED_LOCKED_OPS(name, OP, retValue) \
168+
DO_MBED_LOCKED_OP(name, OP, retValue, uint64_t, u64)
169+
#define DO_MBED_LOCKED_CAS_OPS() \
170+
DO_MBED_LOCKED_CAS_OP(uint64_t, u64)
171+
#else
172+
/* All the operations are locked */
173+
#define DO_MBED_LOCKED_OPS(name, OP, retValue) \
174+
DO_MBED_LOCKED_OP(name, OP, retValue, uint8_t, u8) \
175+
DO_MBED_LOCKED_OP(name, OP, retValue, uint16_t, u16) \
176+
DO_MBED_LOCKED_OP(name, OP, retValue, uint32_t, u32) \
177+
DO_MBED_LOCKED_OP(name, OP, retValue, uint64_t, u64)
178+
#define DO_MBED_LOCKED_CAS_OPS() \
179+
DO_MBED_LOCKED_CAS_OP(uint8_t, u8) \
180+
DO_MBED_LOCKED_CAS_OP(uint16_t, u16) \
181+
DO_MBED_LOCKED_CAS_OP(uint32_t, u32) \
182+
DO_MBED_LOCKED_CAS_OP(uint64_t, u64)
183+
#endif
184+
185+
DO_MBED_LOCKED_OPS(exchange, arg, oldValue)
186+
DO_MBED_LOCKED_OPS(incr, oldValue + arg, newValue)
187+
DO_MBED_LOCKED_OPS(decr, oldValue - arg, newValue)
188+
DO_MBED_LOCKED_OPS(fetch_add, oldValue + arg, oldValue)
189+
DO_MBED_LOCKED_OPS(fetch_sub, oldValue - arg, oldValue)
190+
DO_MBED_LOCKED_OPS(fetch_and, oldValue & arg, oldValue)
191+
DO_MBED_LOCKED_OPS(fetch_or, oldValue | arg, oldValue)
192+
DO_MBED_LOCKED_OPS(fetch_xor, oldValue ^ arg, oldValue)
193+
DO_MBED_LOCKED_CAS_OPS()
194+
195+
/* Similar functions for s32 etc are static inline, but these are extern inline for legacy binary compatibility */
196+
extern inline void *core_util_atomic_exchange_ptr(void *volatile *valuePtr, void *desiredValue);
197+
extern inline void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta);
198+
extern inline void *core_util_atomic_decr_ptr(void *volatile *valuePtr, ptrdiff_t delta);
199+
extern inline bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue);

0 commit comments

Comments
 (0)