|
18 | 18 | #ifndef __MBED_UTIL_CRITICAL_H__
|
19 | 19 | #define __MBED_UTIL_CRITICAL_H__
|
20 | 20 |
|
| 21 | +#include <stdbool.h> |
| 22 | + |
21 | 23 | #ifdef __cplusplus
|
22 | 24 | extern "C" {
|
23 | 25 | #endif
|
@@ -48,6 +50,213 @@ void core_util_critical_section_enter();
|
48 | 50 | */
|
49 | 51 | void core_util_critical_section_exit();
|
50 | 52 |
|
| 53 | +/** |
| 54 | + * Atomic compare and set. It compares the contents of a memory location to a |
| 55 | + * given value and, only if they are the same, modifies the contents of that |
| 56 | + * memory location to a given new value. This is done as a single atomic |
| 57 | + * operation. The atomicity guarantees that the new value is calculated based on |
| 58 | + * up-to-date information; if the value had been updated by another thread in |
| 59 | + * the meantime, the write would fail due to a mismatched expectedCurrentValue. |
| 60 | + * |
| 61 | + * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect |
| 62 | + * you to the article on compare-and swap]. |
| 63 | + * |
| 64 | + * @param ptr The target memory location. |
| 65 | + * @param[in,out] expectedCurrentValue A pointer to some location holding the |
| 66 | + * expected current value of the data being set atomically. |
| 67 | + * The computed 'desiredValue' should be a function of this current value. |
| 68 | + * @Note: This is an in-out parameter. In the |
| 69 | + * failure case of atomic_cas (where the |
| 70 | + * destination isn't set), the pointee of expectedCurrentValue is |
| 71 | + * updated with the current value. |
| 72 | + * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. |
| 73 | + * |
| 74 | + * @return true if the memory location was atomically |
| 75 | + * updated with the desired value (after verifying |
| 76 | + * that it contained the expectedCurrentValue), |
| 77 | + * false otherwise. In the failure case, |
| 78 | + * exepctedCurrentValue is updated with the new |
| 79 | + * value of the target memory location. |
| 80 | + * |
| 81 | + * pseudocode: |
| 82 | + * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { |
| 83 | + * if *p != *old { |
| 84 | + * *old = *p |
| 85 | + * return false |
| 86 | + * } |
| 87 | + * *p = new |
| 88 | + * return true |
| 89 | + * } |
| 90 | + * |
| 91 | + * @Note: In the failure case (where the destination isn't set), the value |
| 92 | + * pointed to by expectedCurrentValue is still updated with the current value. |
| 93 | + * This property helps writing concise code for the following incr: |
| 94 | + * |
| 95 | + * function incr(p : pointer to int, a : int) returns int { |
| 96 | + * done = false |
| 97 | + * *value = *p // This fetch operation need not be atomic. |
| 98 | + * while not done { |
| 99 | + * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success |
| 100 | + * } |
| 101 | + * return value + a |
| 102 | + * } |
| 103 | + */ |
| 104 | +bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue); |
| 105 | + |
| 106 | +/** |
| 107 | + * Atomic compare and set. It compares the contents of a memory location to a |
| 108 | + * given value and, only if they are the same, modifies the contents of that |
| 109 | + * memory location to a given new value. This is done as a single atomic |
| 110 | + * operation. The atomicity guarantees that the new value is calculated based on |
| 111 | + * up-to-date information; if the value had been updated by another thread in |
| 112 | + * the meantime, the write would fail due to a mismatched expectedCurrentValue. |
| 113 | + * |
| 114 | + * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect |
| 115 | + * you to the article on compare-and swap]. |
| 116 | + * |
| 117 | + * @param ptr The target memory location. |
| 118 | + * @param[in,out] expectedCurrentValue A pointer to some location holding the |
| 119 | + * expected current value of the data being set atomically. |
| 120 | + * The computed 'desiredValue' should be a function of this current value. |
| 121 | + * @Note: This is an in-out parameter. In the |
| 122 | + * failure case of atomic_cas (where the |
| 123 | + * destination isn't set), the pointee of expectedCurrentValue is |
| 124 | + * updated with the current value. |
| 125 | + * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. |
| 126 | + * |
| 127 | + * @return true if the memory location was atomically |
| 128 | + * updated with the desired value (after verifying |
| 129 | + * that it contained the expectedCurrentValue), |
| 130 | + * false otherwise. In the failure case, |
| 131 | + * exepctedCurrentValue is updated with the new |
| 132 | + * value of the target memory location. |
| 133 | + * |
| 134 | + * pseudocode: |
| 135 | + * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { |
| 136 | + * if *p != *old { |
| 137 | + * *old = *p |
| 138 | + * return false |
| 139 | + * } |
| 140 | + * *p = new |
| 141 | + * return true |
| 142 | + * } |
| 143 | + * |
| 144 | + * @Note: In the failure case (where the destination isn't set), the value |
| 145 | + * pointed to by expectedCurrentValue is still updated with the current value. |
| 146 | + * This property helps writing concise code for the following incr: |
| 147 | + * |
| 148 | + * function incr(p : pointer to int, a : int) returns int { |
| 149 | + * done = false |
| 150 | + * *value = *p // This fetch operation need not be atomic. |
| 151 | + * while not done { |
| 152 | + * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success |
| 153 | + * } |
| 154 | + * return value + a |
| 155 | + * } |
| 156 | + */ |
| 157 | +bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue); |
| 158 | + |
| 159 | +/** |
| 160 | + * Atomic compare and set. It compares the contents of a memory location to a |
| 161 | + * given value and, only if they are the same, modifies the contents of that |
| 162 | + * memory location to a given new value. This is done as a single atomic |
| 163 | + * operation. The atomicity guarantees that the new value is calculated based on |
| 164 | + * up-to-date information; if the value had been updated by another thread in |
| 165 | + * the meantime, the write would fail due to a mismatched expectedCurrentValue. |
| 166 | + * |
| 167 | + * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect |
| 168 | + * you to the article on compare-and swap]. |
| 169 | + * |
| 170 | + * @param ptr The target memory location. |
| 171 | + * @param[in,out] expectedCurrentValue A pointer to some location holding the |
| 172 | + * expected current value of the data being set atomically. |
| 173 | + * The computed 'desiredValue' should be a function of this current value. |
| 174 | + * @Note: This is an in-out parameter. In the |
| 175 | + * failure case of atomic_cas (where the |
| 176 | + * destination isn't set), the pointee of expectedCurrentValue is |
| 177 | + * updated with the current value. |
| 178 | + * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. |
| 179 | + * |
| 180 | + * @return true if the memory location was atomically |
| 181 | + * updated with the desired value (after verifying |
| 182 | + * that it contained the expectedCurrentValue), |
| 183 | + * false otherwise. In the failure case, |
| 184 | + * exepctedCurrentValue is updated with the new |
| 185 | + * value of the target memory location. |
| 186 | + * |
| 187 | + * pseudocode: |
| 188 | + * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { |
| 189 | + * if *p != *old { |
| 190 | + * *old = *p |
| 191 | + * return false |
| 192 | + * } |
| 193 | + * *p = new |
| 194 | + * return true |
| 195 | + * } |
| 196 | + * |
| 197 | + * @Note: In the failure case (where the destination isn't set), the value |
| 198 | + * pointed to by expectedCurrentValue is still updated with the current value. |
| 199 | + * This property helps writing concise code for the following incr: |
| 200 | + * |
| 201 | + * function incr(p : pointer to int, a : int) returns int { |
| 202 | + * done = false |
| 203 | + * *value = *p // This fetch operation need not be atomic. |
| 204 | + * while not done { |
| 205 | + * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success |
| 206 | + * } |
| 207 | + * return value + a |
| 208 | + * } |
| 209 | + */ |
| 210 | +bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue); |
| 211 | + |
| 212 | +/** |
| 213 | + * Atomic increment. |
| 214 | + * @param valuePtr Target memory location being incremented. |
| 215 | + * @param delta The amount being incremented. |
| 216 | + * @return The new incremented value. |
| 217 | + */ |
| 218 | +uint8_t core_util_atomic_incr_u8(uint8_t * valuePtr, uint8_t delta); |
| 219 | + |
| 220 | +/** |
| 221 | + * Atomic increment. |
| 222 | + * @param valuePtr Target memory location being incremented. |
| 223 | + * @param delta The amount being incremented. |
| 224 | + * @return The new incremented value. |
| 225 | + */ |
| 226 | +uint16_t core_util_atomic_incr_u16(uint16_t * valuePtr, uint16_t delta); |
| 227 | + |
| 228 | +/** |
| 229 | + * Atomic increment. |
| 230 | + * @param valuePtr Target memory location being incremented. |
| 231 | + * @param delta The amount being incremented. |
| 232 | + * @return The new incremented value. |
| 233 | + */ |
| 234 | +uint32_t core_util_atomic_incr_u32(uint32_t * valuePtr, uint32_t delta); |
| 235 | + |
| 236 | +/** |
| 237 | + * Atomic decrement. |
| 238 | + * @param valuePtr Target memory location being decremented. |
| 239 | + * @param delta The amount being decremented. |
| 240 | + * @return The new decremented value. |
| 241 | + */ |
| 242 | +uint8_t core_util_atomic_decr_u8(uint8_t * valuePtr, uint8_t delta); |
| 243 | + |
| 244 | +/** |
| 245 | + * Atomic decrement. |
| 246 | + * @param valuePtr Target memory location being decremented. |
| 247 | + * @param delta The amount being decremented. |
| 248 | + * @return The new decremented value. |
| 249 | + */ |
| 250 | +uint16_t core_util_atomic_decr_u16(uint16_t * valuePtr, uint16_t delta); |
| 251 | + |
| 252 | +/** |
| 253 | + * Atomic decrement. |
| 254 | + * @param valuePtr Target memory location being decremented. |
| 255 | + * @param delta The amount being decremented. |
| 256 | + * @return The new decremented value. |
| 257 | + */ |
| 258 | +uint32_t core_util_atomic_decr_u32(uint32_t * valuePtr, uint32_t delta); |
| 259 | + |
51 | 260 | #ifdef __cplusplus
|
52 | 261 | } // extern "C"
|
53 | 262 | #endif
|
|
0 commit comments