1919#define __MBED_UTIL_CRITICAL_H__
2020
2121#include <stdbool.h>
22+ #include <stdint.h>
23+ #include <stddef.h>
2224
2325#ifdef __cplusplus
2426extern "C" {
@@ -47,7 +49,7 @@ bool core_util_are_interrupts_enabled(void);
4749 * section) will be preserved on exit from the section.
4850 * 4) This implementation will currently only work on code running in privileged mode.
4951 */
50- void core_util_critical_section_enter ();
52+ void core_util_critical_section_enter (void );
5153
5254/** Mark the end of a critical section
5355 *
@@ -60,7 +62,7 @@ void core_util_critical_section_enter();
6062 * section) will be preserved on exit from the section.
6163 * 4) This implementation will currently only work on code running in privileged mode.
6264 */
63- void core_util_critical_section_exit ();
65+ void core_util_critical_section_exit (void );
6466
6567/**
6668 * Atomic compare and set. It compares the contents of a memory location to a
@@ -106,7 +108,7 @@ void core_util_critical_section_exit();
106108 *
107109 * function incr(p : pointer to int, a : int) returns int {
108110 * done = false
109- * * value = *p // This fetch operation need not be atomic.
111+ * value = *p // This fetch operation need not be atomic.
110112 * while not done {
111113 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success
112114 * }
@@ -159,7 +161,7 @@ bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_
159161 *
160162 * function incr(p : pointer to int, a : int) returns int {
161163 * done = false
162- * * value = *p // This fetch operation need not be atomic.
164+ * value = *p // This fetch operation need not be atomic.
163165 * while not done {
164166 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success
165167 * }
@@ -212,7 +214,7 @@ bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uin
212214 *
213215 * function incr(p : pointer to int, a : int) returns int {
214216 * done = false
215- * * value = *p // This fetch operation need not be atomic.
217+ * value = *p // This fetch operation need not be atomic.
216218 * while not done {
217219 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success
218220 * }
@@ -221,53 +223,128 @@ bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uin
221223 */
222224bool core_util_atomic_cas_u32 (uint32_t * ptr , uint32_t * expectedCurrentValue , uint32_t desiredValue );
223225
226+ /**
227+ * Atomic compare and set. It compares the contents of a memory location to a
228+ * given value and, only if they are the same, modifies the contents of that
229+ * memory location to a given new value. This is done as a single atomic
230+ * operation. The atomicity guarantees that the new value is calculated based on
231+ * up-to-date information; if the value had been updated by another thread in
232+ * the meantime, the write would fail due to a mismatched expectedCurrentValue.
233+ *
234+ * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect
235+ * you to the article on compare-and swap].
236+ *
237+ * @param ptr The target memory location.
238+ * @param[in,out] expectedCurrentValue A pointer to some location holding the
239+ * expected current value of the data being set atomically.
240+ * The computed 'desiredValue' should be a function of this current value.
241+ * @Note: This is an in-out parameter. In the
242+ * failure case of atomic_cas (where the
243+ * destination isn't set), the pointee of expectedCurrentValue is
244+ * updated with the current value.
245+ * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'.
246+ *
247+ * @return true if the memory location was atomically
248+ * updated with the desired value (after verifying
249+ * that it contained the expectedCurrentValue),
250+ * false otherwise. In the failure case,
251+ * exepctedCurrentValue is updated with the new
252+ * value of the target memory location.
253+ *
254+ * pseudocode:
255+ * function cas(p : pointer to int, old : pointer to int, new : int) returns bool {
256+ * if *p != *old {
257+ * *old = *p
258+ * return false
259+ * }
260+ * *p = new
261+ * return true
262+ * }
263+ *
264+ * @Note: In the failure case (where the destination isn't set), the value
265+ * pointed to by expectedCurrentValue is still updated with the current value.
266+ * This property helps writing concise code for the following incr:
267+ *
268+ * function incr(p : pointer to int, a : int) returns int {
269+ * done = false
270+ * value = *p // This fetch operation need not be atomic.
271+ * while not done {
272+ * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success
273+ * }
274+ * return value + a
275+ * }
276+ */
277+ bool core_util_atomic_cas_ptr (void * * ptr , void * * expectedCurrentValue , void * desiredValue );
278+
224279/**
225280 * Atomic increment.
226281 * @param valuePtr Target memory location being incremented.
227282 * @param delta The amount being incremented.
228283 * @return The new incremented value.
229284 */
230- uint8_t core_util_atomic_incr_u8 (uint8_t * valuePtr , uint8_t delta );
285+ uint8_t core_util_atomic_incr_u8 (uint8_t * valuePtr , uint8_t delta );
231286
232287/**
233288 * Atomic increment.
234289 * @param valuePtr Target memory location being incremented.
235290 * @param delta The amount being incremented.
236291 * @return The new incremented value.
237292 */
238- uint16_t core_util_atomic_incr_u16 (uint16_t * valuePtr , uint16_t delta );
293+ uint16_t core_util_atomic_incr_u16 (uint16_t * valuePtr , uint16_t delta );
239294
240295/**
241296 * Atomic increment.
242297 * @param valuePtr Target memory location being incremented.
243298 * @param delta The amount being incremented.
244299 * @return The new incremented value.
245300 */
246- uint32_t core_util_atomic_incr_u32 (uint32_t * valuePtr , uint32_t delta );
301+ uint32_t core_util_atomic_incr_u32 (uint32_t * valuePtr , uint32_t delta );
302+
303+ /**
304+ * Atomic increment.
305+ * @param valuePtr Target memory location being incremented.
306+ * @param delta The amount being incremented in bytes.
307+ * @return The new incremented value.
308+ *
309+ * @note The type of the pointer argument is not taken into account
310+ * and the pointer is incremented by bytes.
311+ */
312+ void * core_util_atomic_incr_ptr (void * * valuePtr , ptrdiff_t delta );
247313
248314/**
249315 * Atomic decrement.
250316 * @param valuePtr Target memory location being decremented.
251317 * @param delta The amount being decremented.
252318 * @return The new decremented value.
253319 */
254- uint8_t core_util_atomic_decr_u8 (uint8_t * valuePtr , uint8_t delta );
320+ uint8_t core_util_atomic_decr_u8 (uint8_t * valuePtr , uint8_t delta );
255321
256322/**
257323 * Atomic decrement.
258324 * @param valuePtr Target memory location being decremented.
259325 * @param delta The amount being decremented.
260326 * @return The new decremented value.
261327 */
262- uint16_t core_util_atomic_decr_u16 (uint16_t * valuePtr , uint16_t delta );
328+ uint16_t core_util_atomic_decr_u16 (uint16_t * valuePtr , uint16_t delta );
263329
264330/**
265331 * Atomic decrement.
266332 * @param valuePtr Target memory location being decremented.
267333 * @param delta The amount being decremented.
268334 * @return The new decremented value.
269335 */
270- uint32_t core_util_atomic_decr_u32 (uint32_t * valuePtr , uint32_t delta );
336+ uint32_t core_util_atomic_decr_u32 (uint32_t * valuePtr , uint32_t delta );
337+
338+ /**
339+ * Atomic decrement.
340+ * @param valuePtr Target memory location being decremented.
341+ * @param delta The amount being decremented in bytes.
342+ * @return The new decremented value.
343+ *
344+ * @note The type of the pointer argument is not taken into account
345+ * and the pointer is decremented by bytes
346+ */
347+ void * core_util_atomic_decr_ptr (void * * valuePtr , ptrdiff_t delta );
271348
272349#ifdef __cplusplus
273350} // extern "C"
0 commit comments