Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... 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 underlyng 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 underlyng 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 * Atomic compare and set. It compares the contents of a memory location to a 00087 * given value and, only if they are the same, modifies the contents of that 00088 * memory location to a given new value. This is done as a single atomic 00089 * operation. The atomicity guarantees that the new value is calculated based on 00090 * up-to-date information; if the value had been updated by another thread in 00091 * the meantime, the write would fail due to a mismatched expectedCurrentValue. 00092 * 00093 * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect 00094 * you to the article on compare-and swap]. 00095 * 00096 * @param ptr The target memory location. 00097 * @param[in,out] expectedCurrentValue A pointer to some location holding the 00098 * expected current value of the data being set atomically. 00099 * The computed 'desiredValue' should be a function of this current value. 00100 * @note: This is an in-out parameter. In the 00101 * failure case of atomic_cas (where the 00102 * destination isn't set), the pointee of expectedCurrentValue is 00103 * updated with the current value. 00104 * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. 00105 * 00106 * @return true if the memory location was atomically 00107 * updated with the desired value (after verifying 00108 * that it contained the expectedCurrentValue), 00109 * false otherwise. In the failure case, 00110 * exepctedCurrentValue is updated with the new 00111 * value of the target memory location. 00112 * 00113 * pseudocode: 00114 * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { 00115 * if *p != *old { 00116 * *old = *p 00117 * return false 00118 * } 00119 * *p = new 00120 * return true 00121 * } 00122 * 00123 * @note: In the failure case (where the destination isn't set), the value 00124 * pointed to by expectedCurrentValue is instead updated with the current value. 00125 * This property helps writing concise code for the following incr: 00126 * 00127 * function incr(p : pointer to int, a : int) returns int { 00128 * done = false 00129 * value = *p // This fetch operation need not be atomic. 00130 * while not done { 00131 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success 00132 * } 00133 * return value + a 00134 * } 00135 * 00136 * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it 00137 * always succeeds if the current value is expected, as per the pseudocode 00138 * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. 00139 */ 00140 bool core_util_atomic_cas_u8(uint8_t *ptr, uint8_t *expectedCurrentValue, uint8_t desiredValue); 00141 00142 /** 00143 * Atomic compare and set. It compares the contents of a memory location to a 00144 * given value and, only if they are the same, modifies the contents of that 00145 * memory location to a given new value. This is done as a single atomic 00146 * operation. The atomicity guarantees that the new value is calculated based on 00147 * up-to-date information; if the value had been updated by another thread in 00148 * the meantime, the write would fail due to a mismatched expectedCurrentValue. 00149 * 00150 * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect 00151 * you to the article on compare-and swap]. 00152 * 00153 * @param ptr The target memory location. 00154 * @param[in,out] expectedCurrentValue A pointer to some location holding the 00155 * expected current value of the data being set atomically. 00156 * The computed 'desiredValue' should be a function of this current value. 00157 * @note: This is an in-out parameter. In the 00158 * failure case of atomic_cas (where the 00159 * destination isn't set), the pointee of expectedCurrentValue is 00160 * updated with the current value. 00161 * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. 00162 * 00163 * @return true if the memory location was atomically 00164 * updated with the desired value (after verifying 00165 * that it contained the expectedCurrentValue), 00166 * false otherwise. In the failure case, 00167 * exepctedCurrentValue is updated with the new 00168 * value of the target memory location. 00169 * 00170 * pseudocode: 00171 * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { 00172 * if *p != *old { 00173 * *old = *p 00174 * return false 00175 * } 00176 * *p = new 00177 * return true 00178 * } 00179 * 00180 * @note: In the failure case (where the destination isn't set), the value 00181 * pointed to by expectedCurrentValue is instead updated with the current value. 00182 * This property helps writing concise code for the following incr: 00183 * 00184 * function incr(p : pointer to int, a : int) returns int { 00185 * done = false 00186 * value = *p // This fetch operation need not be atomic. 00187 * while not done { 00188 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success 00189 * } 00190 * return value + a 00191 * } 00192 * 00193 * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it 00194 * always succeeds if the current value is expected, as per the pseudocode 00195 * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. 00196 */ 00197 bool core_util_atomic_cas_u16(uint16_t *ptr, uint16_t *expectedCurrentValue, uint16_t desiredValue); 00198 00199 /** 00200 * Atomic compare and set. It compares the contents of a memory location to a 00201 * given value and, only if they are the same, modifies the contents of that 00202 * memory location to a given new value. This is done as a single atomic 00203 * operation. The atomicity guarantees that the new value is calculated based on 00204 * up-to-date information; if the value had been updated by another thread in 00205 * the meantime, the write would fail due to a mismatched expectedCurrentValue. 00206 * 00207 * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect 00208 * you to the article on compare-and swap]. 00209 * 00210 * @param ptr The target memory location. 00211 * @param[in,out] expectedCurrentValue A pointer to some location holding the 00212 * expected current value of the data being set atomically. 00213 * The computed 'desiredValue' should be a function of this current value. 00214 * @note: This is an in-out parameter. In the 00215 * failure case of atomic_cas (where the 00216 * destination isn't set), the pointee of expectedCurrentValue is 00217 * updated with the current value. 00218 * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. 00219 * 00220 * @return true if the memory location was atomically 00221 * updated with the desired value (after verifying 00222 * that it contained the expectedCurrentValue), 00223 * false otherwise. In the failure case, 00224 * exepctedCurrentValue is updated with the new 00225 * value of the target memory location. 00226 * 00227 * pseudocode: 00228 * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { 00229 * if *p != *old { 00230 * *old = *p 00231 * return false 00232 * } 00233 * *p = new 00234 * return true 00235 * } 00236 * 00237 * @note: In the failure case (where the destination isn't set), the value 00238 * pointed to by expectedCurrentValue is instead updated with the current value. 00239 * This property helps writing concise code for the following incr: 00240 * 00241 * function incr(p : pointer to int, a : int) returns int { 00242 * done = false 00243 * value = *p // This fetch operation need not be atomic. 00244 * while not done { 00245 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success 00246 * } 00247 * return value + a 00248 * 00249 * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it 00250 * always succeeds if the current value is expected, as per the pseudocode 00251 * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. 00252 * } 00253 */ 00254 bool core_util_atomic_cas_u32(uint32_t *ptr, uint32_t *expectedCurrentValue, uint32_t desiredValue); 00255 00256 /** 00257 * Atomic compare and set. It compares the contents of a memory location to a 00258 * given value and, only if they are the same, modifies the contents of that 00259 * memory location to a given new value. This is done as a single atomic 00260 * operation. The atomicity guarantees that the new value is calculated based on 00261 * up-to-date information; if the value had been updated by another thread in 00262 * the meantime, the write would fail due to a mismatched expectedCurrentValue. 00263 * 00264 * Refer to https://en.wikipedia.org/wiki/Compare-and-set [which may redirect 00265 * you to the article on compare-and swap]. 00266 * 00267 * @param ptr The target memory location. 00268 * @param[in,out] expectedCurrentValue A pointer to some location holding the 00269 * expected current value of the data being set atomically. 00270 * The computed 'desiredValue' should be a function of this current value. 00271 * @note: This is an in-out parameter. In the 00272 * failure case of atomic_cas (where the 00273 * destination isn't set), the pointee of expectedCurrentValue is 00274 * updated with the current value. 00275 * @param[in] desiredValue The new value computed based on '*expectedCurrentValue'. 00276 * 00277 * @return true if the memory location was atomically 00278 * updated with the desired value (after verifying 00279 * that it contained the expectedCurrentValue), 00280 * false otherwise. In the failure case, 00281 * exepctedCurrentValue is updated with the new 00282 * value of the target memory location. 00283 * 00284 * pseudocode: 00285 * function cas(p : pointer to int, old : pointer to int, new : int) returns bool { 00286 * if *p != *old { 00287 * *old = *p 00288 * return false 00289 * } 00290 * *p = new 00291 * return true 00292 * } 00293 * 00294 * @note: In the failure case (where the destination isn't set), the value 00295 * pointed to by expectedCurrentValue is instead updated with the current value. 00296 * This property helps writing concise code for the following incr: 00297 * 00298 * function incr(p : pointer to int, a : int) returns int { 00299 * done = false 00300 * value = *p // This fetch operation need not be atomic. 00301 * while not done { 00302 * done = atomic_cas(p, &value, value + a) // *value gets updated automatically until success 00303 * } 00304 * return value + a 00305 * } 00306 * 00307 * @note: This corresponds to the C11 "atomic_compare_exchange_strong" - it 00308 * always succeeds if the current value is expected, as per the pseudocode 00309 * above; it will not spuriously fail as "atomic_compare_exchange_weak" may. 00310 */ 00311 bool core_util_atomic_cas_ptr(void **ptr, void **expectedCurrentValue, void *desiredValue); 00312 00313 /** 00314 * Atomic increment. 00315 * @param valuePtr Target memory location being incremented. 00316 * @param delta The amount being incremented. 00317 * @return The new incremented value. 00318 */ 00319 uint8_t core_util_atomic_incr_u8(uint8_t *valuePtr, uint8_t delta); 00320 00321 /** 00322 * Atomic increment. 00323 * @param valuePtr Target memory location being incremented. 00324 * @param delta The amount being incremented. 00325 * @return The new incremented value. 00326 */ 00327 uint16_t core_util_atomic_incr_u16(uint16_t *valuePtr, uint16_t delta); 00328 00329 /** 00330 * Atomic increment. 00331 * @param valuePtr Target memory location being incremented. 00332 * @param delta The amount being incremented. 00333 * @return The new incremented value. 00334 */ 00335 uint32_t core_util_atomic_incr_u32(uint32_t *valuePtr, uint32_t delta); 00336 00337 /** 00338 * Atomic increment. 00339 * @param valuePtr Target memory location being incremented. 00340 * @param delta The amount being incremented in bytes. 00341 * @return The new incremented value. 00342 * 00343 * @note The type of the pointer argument is not taken into account 00344 * and the pointer is incremented by bytes. 00345 */ 00346 void *core_util_atomic_incr_ptr(void **valuePtr, ptrdiff_t delta); 00347 00348 /** 00349 * Atomic decrement. 00350 * @param valuePtr Target memory location being decremented. 00351 * @param delta The amount being decremented. 00352 * @return The new decremented value. 00353 */ 00354 uint8_t core_util_atomic_decr_u8(uint8_t *valuePtr, uint8_t delta); 00355 00356 /** 00357 * Atomic decrement. 00358 * @param valuePtr Target memory location being decremented. 00359 * @param delta The amount being decremented. 00360 * @return The new decremented value. 00361 */ 00362 uint16_t core_util_atomic_decr_u16(uint16_t *valuePtr, uint16_t delta); 00363 00364 /** 00365 * Atomic decrement. 00366 * @param valuePtr Target memory location being decremented. 00367 * @param delta The amount being decremented. 00368 * @return The new decremented value. 00369 */ 00370 uint32_t core_util_atomic_decr_u32(uint32_t *valuePtr, uint32_t delta); 00371 00372 /** 00373 * Atomic decrement. 00374 * @param valuePtr Target memory location being decremented. 00375 * @param delta The amount being decremented in bytes. 00376 * @return The new decremented value. 00377 * 00378 * @note The type of the pointer argument is not taken into account 00379 * and the pointer is decremented by bytes 00380 */ 00381 void *core_util_atomic_decr_ptr(void **valuePtr, ptrdiff_t delta); 00382 00383 #ifdef __cplusplus 00384 } // extern "C" 00385 #endif 00386 /**@}*/ 00387 00388 /**@}*/ 00389 00390 #endif // __MBED_UTIL_CRITICAL_H__ 00391 00392 00393
Generated on Tue Jul 12 2022 13:03:03 by
