Skip to content

Add functions for atomic access #1843

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 209 additions & 0 deletions hal/api/critical.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#ifndef __MBED_UTIL_CRITICAL_H__
#define __MBED_UTIL_CRITICAL_H__

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -48,6 +50,213 @@ void core_util_critical_section_enter();
*/
void core_util_critical_section_exit();

/**
* Atomic compare and set. It compares the contents of a memory location to a
* given value and, only if they are the same, modifies the contents of that
* memory location to a given new value. This is done as a single atomic
* operation. The atomicity guarantees that the new value is calculated based on
* up-to-date information; if the value had been updated by another thread in
* the meantime, the write would fail due to a mismatched expectedCurrentValue.
*
* Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect
* you to the article on compare-and swap].
*
* @param ptr The target memory location.
* @param[in,out] expectedCurrentValue A pointer to some location holding the
* expected current value of the data being set atomically.
* The computed 'desiredValue' should be a function of this current value.
* @Note: This is an in-out parameter. In the
* failure case of atomic_cas (where the
* destination isn't set), the pointee of expectedCurrentValue is
* updated with the current value.
* @param[in] desiredValue The new value computed based on '*expectedCurrentValue'.
*
* @return true if the memory location was atomically
* updated with the desired value (after verifying
* that it contained the expectedCurrentValue),
* false otherwise. In the failure case,
* exepctedCurrentValue is updated with the new
* value of the target memory location.
*
* pseudocode:
* function cas(p : pointer to int, old : pointer to int, new : int) returns bool {
* if *p != *old {
* *old = *p
* return false
* }
* *p = new
* return true
* }
*
* @Note: In the failure case (where the destination isn't set), the value
* pointed to by expectedCurrentValue is still updated with the current value.
* This property helps writing concise code for the following incr:
*
* function incr(p : pointer to int, a : int) returns int {
* done = false
* *value = *p // This fetch operation need not be atomic.
* while not done {
* done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success
* }
* return value + a
* }
*/
bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue);

/**
* Atomic compare and set. It compares the contents of a memory location to a
* given value and, only if they are the same, modifies the contents of that
* memory location to a given new value. This is done as a single atomic
* operation. The atomicity guarantees that the new value is calculated based on
* up-to-date information; if the value had been updated by another thread in
* the meantime, the write would fail due to a mismatched expectedCurrentValue.
*
* Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect
* you to the article on compare-and swap].
*
* @param ptr The target memory location.
* @param[in,out] expectedCurrentValue A pointer to some location holding the
* expected current value of the data being set atomically.
* The computed 'desiredValue' should be a function of this current value.
* @Note: This is an in-out parameter. In the
* failure case of atomic_cas (where the
* destination isn't set), the pointee of expectedCurrentValue is
* updated with the current value.
* @param[in] desiredValue The new value computed based on '*expectedCurrentValue'.
*
* @return true if the memory location was atomically
* updated with the desired value (after verifying
* that it contained the expectedCurrentValue),
* false otherwise. In the failure case,
* exepctedCurrentValue is updated with the new
* value of the target memory location.
*
* pseudocode:
* function cas(p : pointer to int, old : pointer to int, new : int) returns bool {
* if *p != *old {
* *old = *p
* return false
* }
* *p = new
* return true
* }
*
* @Note: In the failure case (where the destination isn't set), the value
* pointed to by expectedCurrentValue is still updated with the current value.
* This property helps writing concise code for the following incr:
*
* function incr(p : pointer to int, a : int) returns int {
* done = false
* *value = *p // This fetch operation need not be atomic.
* while not done {
* done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success
* }
* return value + a
* }
*/
bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue);

/**
* Atomic compare and set. It compares the contents of a memory location to a
* given value and, only if they are the same, modifies the contents of that
* memory location to a given new value. This is done as a single atomic
* operation. The atomicity guarantees that the new value is calculated based on
* up-to-date information; if the value had been updated by another thread in
* the meantime, the write would fail due to a mismatched expectedCurrentValue.
*
* Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect
* you to the article on compare-and swap].
*
* @param ptr The target memory location.
* @param[in,out] expectedCurrentValue A pointer to some location holding the
* expected current value of the data being set atomically.
* The computed 'desiredValue' should be a function of this current value.
* @Note: This is an in-out parameter. In the
* failure case of atomic_cas (where the
* destination isn't set), the pointee of expectedCurrentValue is
* updated with the current value.
* @param[in] desiredValue The new value computed based on '*expectedCurrentValue'.
*
* @return true if the memory location was atomically
* updated with the desired value (after verifying
* that it contained the expectedCurrentValue),
* false otherwise. In the failure case,
* exepctedCurrentValue is updated with the new
* value of the target memory location.
*
* pseudocode:
* function cas(p : pointer to int, old : pointer to int, new : int) returns bool {
* if *p != *old {
* *old = *p
* return false
* }
* *p = new
* return true
* }
*
* @Note: In the failure case (where the destination isn't set), the value
* pointed to by expectedCurrentValue is still updated with the current value.
* This property helps writing concise code for the following incr:
*
* function incr(p : pointer to int, a : int) returns int {
* done = false
* *value = *p // This fetch operation need not be atomic.
* while not done {
* done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success
* }
* return value + a
* }
*/
bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue);

/**
* Atomic increment.
* @param valuePtr Target memory location being incremented.
* @param delta The amount being incremented.
* @return The new incremented value.
*/
uint8_t core_util_atomic_incr_u8(uint8_t * valuePtr, uint8_t delta);

/**
* Atomic increment.
* @param valuePtr Target memory location being incremented.
* @param delta The amount being incremented.
* @return The new incremented value.
*/
uint16_t core_util_atomic_incr_u16(uint16_t * valuePtr, uint16_t delta);

/**
* Atomic increment.
* @param valuePtr Target memory location being incremented.
* @param delta The amount being incremented.
* @return The new incremented value.
*/
uint32_t core_util_atomic_incr_u32(uint32_t * valuePtr, uint32_t delta);

/**
* Atomic decrement.
* @param valuePtr Target memory location being decremented.
* @param delta The amount being decremented.
* @return The new decremented value.
*/
uint8_t core_util_atomic_decr_u8(uint8_t * valuePtr, uint8_t delta);

/**
* Atomic decrement.
* @param valuePtr Target memory location being decremented.
* @param delta The amount being decremented.
* @return The new decremented value.
*/
uint16_t core_util_atomic_decr_u16(uint16_t * valuePtr, uint16_t delta);

/**
* Atomic decrement.
* @param valuePtr Target memory location being decremented.
* @param delta The amount being decremented.
* @return The new decremented value.
*/
uint32_t core_util_atomic_decr_u32(uint32_t * valuePtr, uint32_t delta);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
Loading