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.
Fork of OmniWheels by
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 Fri Jul 22 2022 04:53:56 by
