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