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