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