mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
mbed_critical.h
00001 00002 /* 00003 * Copyright (c) 2015-2016, ARM Limited, All Rights Reserved 00004 * SPDX-License-Identifier: Apache-2.0 00005 * 00006 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00007 * not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 00019 #ifndef __MBED_UTIL_CRITICAL_H__ 00020 #define __MBED_UTIL_CRITICAL_H__ 00021 00022 #include <stdbool.h> 00023 #include <stdint.h> 00024 #include <stddef.h> 00025 00026 #ifdef __cplusplus 00027 extern "C" { 00028 #endif 00029 00030 /** \addtogroup platform */ 00031 /** @{*/ 00032 /** 00033 * \defgroup platform_critical critical section function 00034 * @{ 00035 */ 00036 00037 /** Determine the current interrupts enabled state 00038 * 00039 * This function can be called to determine whether or not interrupts are currently enabled. 00040 * @note 00041 * NOTE: 00042 * This function works for both cortex-A and cortex-M, although the underlying implementation 00043 * differs. 00044 * @return true if interrupts are enabled, false otherwise 00045 */ 00046 bool core_util_are_interrupts_enabled(void); 00047 00048 /** Determine if this code is executing from an interrupt 00049 * 00050 * This function can be called to determine if the code is running on interrupt context. 00051 * @note 00052 * NOTE: 00053 * This function works for both cortex-A and cortex-M, although the underlying implementation 00054 * differs. 00055 * @return true if in an isr, false otherwise 00056 */ 00057 bool core_util_is_isr_active(void); 00058 00059 /** Mark the start of a critical section 00060 * 00061 * This function should be called to mark the start of a critical section of code. 00062 * @note 00063 * NOTES: 00064 * 1) The use of this style of critical section is targetted at C based implementations. 00065 * 2) These critical sections can be nested. 00066 * 3) The interrupt enable state on entry to the first critical section (of a nested set, or single 00067 * section) will be preserved on exit from the section. 00068 * 4) This implementation will currently only work on code running in privileged mode. 00069 */ 00070 void core_util_critical_section_enter(void); 00071 00072 /** Mark the end of a critical section 00073 * 00074 * This function should be called to mark the end of a critical section of code. 00075 * @note 00076 * NOTES: 00077 * 1) The use of this style of critical section is targetted at C based implementations. 00078 * 2) These critical sections can be nested. 00079 * 3) The interrupt enable state on entry to the first critical section (of a nested set, or single 00080 * section) will be preserved on exit from the section. 00081 * 4) This implementation will currently only work on code running in privileged mode. 00082 */ 00083 void core_util_critical_section_exit(void); 00084 00085 /** 00086 * Determine if we are currently in a critical section 00087 * 00088 * @return true if in a critical section, false otherwise. 00089 */ 00090 bool core_util_in_critical_section(void); 00091 00092 /** 00093 * A lock-free, primitive atomic flag. 00094 * 00095 * Emulate C11's atomic_flag. The flag is initially in an indeterminate state 00096 * unless explicitly initialized with CORE_UTIL_ATOMIC_FLAG_INIT. 00097 */ 00098 typedef struct core_util_atomic_flag { 00099 uint8_t _flag; 00100 } core_util_atomic_flag; 00101 00102 /** 00103 * Initializer for a core_util_atomic_flag. 00104 * 00105 * Example: 00106 * ~~~ 00107 * core_util_atomic_flag in_progress = CORE_UTIL_ATOMIC_FLAG_INIT; 00108 * ~~~ 00109 */ 00110 #define CORE_UTIL_ATOMIC_FLAG_INIT { 0 } 00111 00112 /** 00113 * Atomic test and set. 00114 * 00115 * Atomically tests then sets the flag to true, returning the previous value. 00116 * 00117 * @param flagPtr Target flag being tested and set. 00118 * @return The previous value. 00119 */ 00120 bool core_util_atomic_flag_test_and_set(volatile core_util_atomic_flag *flagPtr); 00121 00122 /** 00123 * Atomic clear. 00124 * 00125 * @param flagPtr Target flag being cleared. 00126 */ 00127 void core_util_atomic_flag_clear(volatile core_util_atomic_flag *flagPtr); 00128 00129 /** 00130 * Atomic compare and set. It compares the contents of a memory location to a 00131 * given value and, only if they are the same, modifies the contents of that 00132 * memory location to a given new value. This is done as a single atomic 00133 * operation. The atomicity guarantees that the new value is calculated based on 00134 * up-to-date information; if the value had been updated by another thread in 00135 * the meantime, the write would fail due to a mismatched expectedCurrentValue. 00136 * 00137 * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect 00138 * you to the article on compare-and swap]. 00139 * 00140 * @param ptr The target memory location. 00141 * @param[in,out] expectedCurrentValue A pointer to some location holding the 00142 * expected current value of the data being set atomically. 00143 * The computed 'desiredValue' should be a function of this current value. 00144 * @note: This is an in-out parameter. In the 00145 * failure case of atomic_cas (where the 00146 * destination isn't set), the pointee of expectedCurrentValue is 00147 * updated with the current value. 00148 * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. 00149 * 00150 * @return true if the memory location was atomically 00151 * updated with the desired value (after verifying 00152 * that it contained the expectedCurrentValue), 00153 * false otherwise. In the failure case, 00154 * exepctedCurrentValue is updated with the new 00155 * value of the target memory location. 00156 * 00157 * pseudocode: 00158 * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { 00159 * if *p != *old { 00160 * *old = *p 00161 * return false 00162 * } 00163 * *p = new 00164 * return true 00165 * } 00166 * 00167 * @note: In the failure case (where the destination isn't set), the value 00168 * pointed to by expectedCurrentValue is instead updated with the current value. 00169 * This property helps writing concise code for the following incr: 00170 * 00171 * function incr(p : pointer to int, a : int) returns int { 00172 * done = false 00173 * value = *p // This fetch operation need not be atomic. 00174 * while not done { 00175 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success 00176 * } 00177 * return value + a 00178 * } 00179 * 00180 * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it 00181 * always succeeds if the current value is expected, as per the pseudocode 00182 * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. 00183 */ 00184 bool core_util_atomic_cas_u8(volatile uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue); 00185 00186 /** 00187 * Atomic compare and set. It compares the contents of a memory location to a 00188 * given value and, only if they are the same, modifies the contents of that 00189 * memory location to a given new value. This is done as a single atomic 00190 * operation. The atomicity guarantees that the new value is calculated based on 00191 * up-to-date information; if the value had been updated by another thread in 00192 * the meantime, the write would fail due to a mismatched expectedCurrentValue. 00193 * 00194 * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect 00195 * you to the article on compare-and swap]. 00196 * 00197 * @param ptr The target memory location. 00198 * @param[in,out] expectedCurrentValue A pointer to some location holding the 00199 * expected current value of the data being set atomically. 00200 * The computed 'desiredValue' should be a function of this current value. 00201 * @note: This is an in-out parameter. In the 00202 * failure case of atomic_cas (where the 00203 * destination isn't set), the pointee of expectedCurrentValue is 00204 * updated with the current value. 00205 * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. 00206 * 00207 * @return true if the memory location was atomically 00208 * updated with the desired value (after verifying 00209 * that it contained the expectedCurrentValue), 00210 * false otherwise. In the failure case, 00211 * exepctedCurrentValue is updated with the new 00212 * value of the target memory location. 00213 * 00214 * pseudocode: 00215 * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { 00216 * if *p != *old { 00217 * *old = *p 00218 * return false 00219 * } 00220 * *p = new 00221 * return true 00222 * } 00223 * 00224 * @note: In the failure case (where the destination isn't set), the value 00225 * pointed to by expectedCurrentValue is instead updated with the current value. 00226 * This property helps writing concise code for the following incr: 00227 * 00228 * function incr(p : pointer to int, a : int) returns int { 00229 * done = false 00230 * value = *p // This fetch operation need not be atomic. 00231 * while not done { 00232 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success 00233 * } 00234 * return value + a 00235 * } 00236 * 00237 * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it 00238 * always succeeds if the current value is expected, as per the pseudocode 00239 * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. 00240 */ 00241 bool core_util_atomic_cas_u16(volatile uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue); 00242 00243 /** 00244 * Atomic compare and set. It compares the contents of a memory location to a 00245 * given value and, only if they are the same, modifies the contents of that 00246 * memory location to a given new value. This is done as a single atomic 00247 * operation. The atomicity guarantees that the new value is calculated based on 00248 * up-to-date information; if the value had been updated by another thread in 00249 * the meantime, the write would fail due to a mismatched expectedCurrentValue. 00250 * 00251 * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect 00252 * you to the article on compare-and swap]. 00253 * 00254 * @param ptr The target memory location. 00255 * @param[in,out] expectedCurrentValue A pointer to some location holding the 00256 * expected current value of the data being set atomically. 00257 * The computed 'desiredValue' should be a function of this current value. 00258 * @note: This is an in-out parameter. In the 00259 * failure case of atomic_cas (where the 00260 * destination isn't set), the pointee of expectedCurrentValue is 00261 * updated with the current value. 00262 * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. 00263 * 00264 * @return true if the memory location was atomically 00265 * updated with the desired value (after verifying 00266 * that it contained the expectedCurrentValue), 00267 * false otherwise. In the failure case, 00268 * exepctedCurrentValue is updated with the new 00269 * value of the target memory location. 00270 * 00271 * pseudocode: 00272 * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { 00273 * if *p != *old { 00274 * *old = *p 00275 * return false 00276 * } 00277 * *p = new 00278 * return true 00279 * } 00280 * 00281 * @note: In the failure case (where the destination isn't set), the value 00282 * pointed to by expectedCurrentValue is instead updated with the current value. 00283 * This property helps writing concise code for the following incr: 00284 * 00285 * function incr(p : pointer to int, a : int) returns int { 00286 * done = false 00287 * value = *p // This fetch operation need not be atomic. 00288 * while not done { 00289 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success 00290 * } 00291 * return value + a 00292 * 00293 * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it 00294 * always succeeds if the current value is expected, as per the pseudocode 00295 * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. 00296 * } 00297 */ 00298 bool core_util_atomic_cas_u32(volatile uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue); 00299 00300 /** 00301 * Atomic compare and set. It compares the contents of a memory location to a 00302 * given value and, only if they are the same, modifies the contents of that 00303 * memory location to a given new value. This is done as a single atomic 00304 * operation. The atomicity guarantees that the new value is calculated based on 00305 * up-to-date information; if the value had been updated by another thread in 00306 * the meantime, the write would fail due to a mismatched expectedCurrentValue. 00307 * 00308 * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect 00309 * you to the article on compare-and swap]. 00310 * 00311 * @param ptr The target memory location. 00312 * @param[in,out] expectedCurrentValue A pointer to some location holding the 00313 * expected current value of the data being set atomically. 00314 * The computed 'desiredValue' should be a function of this current value. 00315 * @note: This is an in-out parameter. In the 00316 * failure case of atomic_cas (where the 00317 * destination isn't set), the pointee of expectedCurrentValue is 00318 * updated with the current value. 00319 * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. 00320 * 00321 * @return true if the memory location was atomically 00322 * updated with the desired value (after verifying 00323 * that it contained the expectedCurrentValue), 00324 * false otherwise. In the failure case, 00325 * exepctedCurrentValue is updated with the new 00326 * value of the target memory location. 00327 * 00328 * pseudocode: 00329 * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { 00330 * if *p != *old { 00331 * *old = *p 00332 * return false 00333 * } 00334 * *p = new 00335 * return true 00336 * } 00337 * 00338 * @note: In the failure case (where the destination isn't set), the value 00339 * pointed to by expectedCurrentValue is instead updated with the current value. 00340 * This property helps writing concise code for the following incr: 00341 * 00342 * function incr(p : pointer to int, a : int) returns int { 00343 * done = false 00344 * value = *p // This fetch operation need not be atomic. 00345 * while not done { 00346 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success 00347 * } 00348 * return value + a 00349 * } 00350 * 00351 * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it 00352 * always succeeds if the current value is expected, as per the pseudocode 00353 * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. 00354 */ 00355 bool core_util_atomic_cas_ptr(void *volatile *ptr, void **expectedCurrentValue, void *desiredValue); 00356 00357 /** 00358 * Atomic increment. 00359 * @param valuePtr Target memory location being incremented. 00360 * @param delta The amount being incremented. 00361 * @return The new incremented value. 00362 */ 00363 uint8_t core_util_atomic_incr_u8(volatile uint8_t *valuePtr, uint8_t delta); 00364 00365 /** 00366 * Atomic increment. 00367 * @param valuePtr Target memory location being incremented. 00368 * @param delta The amount being incremented. 00369 * @return The new incremented value. 00370 */ 00371 uint16_t core_util_atomic_incr_u16(volatile uint16_t *valuePtr, uint16_t delta); 00372 00373 /** 00374 * Atomic increment. 00375 * @param valuePtr Target memory location being incremented. 00376 * @param delta The amount being incremented. 00377 * @return The new incremented value. 00378 */ 00379 uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta); 00380 00381 /** 00382 * Atomic increment. 00383 * @param valuePtr Target memory location being incremented. 00384 * @param delta The amount being incremented in bytes. 00385 * @return The new incremented value. 00386 * 00387 * @note The type of the pointer argument is not taken into account 00388 * and the pointer is incremented by bytes. 00389 */ 00390 void *core_util_atomic_incr_ptr(void *volatile *valuePtr, ptrdiff_t delta); 00391 00392 /** 00393 * Atomic decrement. 00394 * @param valuePtr Target memory location being decremented. 00395 * @param delta The amount being decremented. 00396 * @return The new decremented value. 00397 */ 00398 uint8_t core_util_atomic_decr_u8(volatile uint8_t *valuePtr, uint8_t delta); 00399 00400 /** 00401 * Atomic decrement. 00402 * @param valuePtr Target memory location being decremented. 00403 * @param delta The amount being decremented. 00404 * @return The new decremented value. 00405 */ 00406 uint16_t core_util_atomic_decr_u16(volatile uint16_t *valuePtr, uint16_t delta); 00407 00408 /** 00409 * Atomic decrement. 00410 * @param valuePtr Target memory location being decremented. 00411 * @param delta The amount being decremented. 00412 * @return The new decremented value. 00413 */ 00414 uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta); 00415 00416 /** 00417 * Atomic decrement. 00418 * @param valuePtr Target memory location being decremented. 00419 * @param delta The amount being decremented in bytes. 00420 * @return The new decremented value. 00421 * 00422 * @note The type of the pointer argument is not taken into account 00423 * and the pointer is decremented by bytes 00424 */ 00425 void *core_util_atomic_decr_ptr(void *volatile *valuePtr, ptrdiff_t delta); 00426 00427 #ifdef __cplusplus 00428 } // extern "C" 00429 #endif 00430 /**@}*/ 00431 00432 /**@}*/ 00433 00434 #endif // __MBED_UTIL_CRITICAL_H__ 00435 00436 00437
Generated on Tue Jul 12 2022 20:41:15 by 1.7.2