forked

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mbed_critical.h Source File

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 /** @}*/