Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mbed_critical.h Source File

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