Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:12

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreAtomic
0007  *
0008  * @brief This header file provides the interfaces of the
0009  *   @ref RTEMSScoreAtomic.
0010  */
0011 
0012 /*
0013  * Copyright (C) 2015, 2024 embedded brains GmbH & Co. KG
0014  * COPYRIGHT (c) 2012-2013 Deng Hengyi.
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifndef _RTEMS_SCORE_ATOMIC_H
0039 #define _RTEMS_SCORE_ATOMIC_H
0040 
0041 #include <rtems/score/basedefs.h>
0042 
0043 /**
0044  * @defgroup RTEMSScoreAtomic Atomic Operations
0045  *
0046  * @ingroup RTEMSScore
0047  *
0048  * @brief This group contains the atomic operations implementation.
0049  *
0050  * Atomic operations can be used to implement low-level synchronization
0051  * primitives on SMP systems, like spin locks.  All atomic operations are
0052  * defined in terms of C11 (ISO/IEC 9899:2011) or C++11 (ISO/IEC 14882:2011).
0053  * For documentation use the standard documents.
0054  *
0055  * @{
0056  */
0057 
0058 #ifdef RTEMS_SMP
0059   #if defined(__cplusplus) \
0060     && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))
0061     /*
0062      * The GCC 4.9 ships its own <stdatomic.h> which is not C++ compatible.  The
0063      * suggested solution was to include <atomic> in case C++ is used.  This works
0064      * at least with GCC 4.9.  See also:
0065      *
0066      * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60932
0067      * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60940
0068      */
0069     #include <atomic>
0070     #define _RTEMS_SCORE_ATOMIC_USE_ATOMIC
0071   #else
0072     #include <stdatomic.h>
0073     #define _RTEMS_SCORE_ATOMIC_USE_STDATOMIC
0074   #endif
0075 #else
0076   #include <rtems/score/isrlevel.h>
0077 #endif
0078 
0079 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0080 
0081 typedef unsigned int Atomic_Uint;
0082 
0083 typedef unsigned long Atomic_Ulong;
0084 
0085 typedef uintptr_t Atomic_Uintptr;
0086 
0087 typedef std::atomic_flag Atomic_Flag;
0088 
0089 typedef std::memory_order Atomic_Order;
0090 
0091 #define ATOMIC_ORDER_RELAXED std::memory_order_relaxed
0092 
0093 #define ATOMIC_ORDER_ACQUIRE std::memory_order_acquire
0094 
0095 #define ATOMIC_ORDER_RELEASE std::memory_order_release
0096 
0097 #define ATOMIC_ORDER_ACQ_REL std::memory_order_acq_rel
0098 
0099 #define ATOMIC_ORDER_SEQ_CST std::memory_order_seq_cst
0100 
0101 #define ATOMIC_INITIALIZER_UINT( value ) ATOMIC_VAR_INIT( value )
0102 
0103 #define ATOMIC_INITIALIZER_ULONG( value ) ATOMIC_VAR_INIT( value )
0104 
0105 #define ATOMIC_INITIALIZER_UINTPTR( value ) ATOMIC_VAR_INIT( value )
0106 
0107 #define ATOMIC_INITIALIZER_FLAG ATOMIC_FLAG_INIT
0108 
0109 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0110 
0111 typedef atomic_uint Atomic_Uint;
0112 
0113 typedef atomic_ulong Atomic_Ulong;
0114 
0115 typedef atomic_uintptr_t Atomic_Uintptr;
0116 
0117 typedef atomic_flag Atomic_Flag;
0118 
0119 typedef memory_order Atomic_Order;
0120 
0121 #define ATOMIC_ORDER_RELAXED memory_order_relaxed
0122 
0123 #define ATOMIC_ORDER_ACQUIRE memory_order_acquire
0124 
0125 #define ATOMIC_ORDER_RELEASE memory_order_release
0126 
0127 #define ATOMIC_ORDER_ACQ_REL memory_order_acq_rel
0128 
0129 #define ATOMIC_ORDER_SEQ_CST memory_order_seq_cst
0130 
0131 #define ATOMIC_INITIALIZER_UINT( value ) ATOMIC_VAR_INIT( value )
0132 
0133 #define ATOMIC_INITIALIZER_ULONG( value ) ATOMIC_VAR_INIT( value )
0134 
0135 #define ATOMIC_INITIALIZER_UINTPTR( value ) ATOMIC_VAR_INIT( value )
0136 
0137 #define ATOMIC_INITIALIZER_FLAG ATOMIC_FLAG_INIT
0138 
0139 #else
0140 
0141 typedef unsigned int Atomic_Uint;
0142 
0143 typedef unsigned long Atomic_Ulong;
0144 
0145 typedef uintptr_t Atomic_Uintptr;
0146 
0147 typedef bool Atomic_Flag;
0148 
0149 typedef int Atomic_Order;
0150 
0151 #define ATOMIC_ORDER_RELAXED 0
0152 
0153 #define ATOMIC_ORDER_ACQUIRE 2
0154 
0155 #define ATOMIC_ORDER_RELEASE 3
0156 
0157 #define ATOMIC_ORDER_ACQ_REL 4
0158 
0159 #define ATOMIC_ORDER_SEQ_CST 5
0160 
0161 #define ATOMIC_INITIALIZER_UINT( value ) ( value )
0162 
0163 #define ATOMIC_INITIALIZER_ULONG( value ) ( value )
0164 
0165 #define ATOMIC_INITIALIZER_UINTPTR( value ) ( value )
0166 
0167 #define ATOMIC_INITIALIZER_FLAG false
0168 
0169 #endif
0170 
0171 /**
0172  * @brief Sets up a cpu fence.
0173  *
0174  * @param[out] order The order for the fence.
0175  */
0176 static inline void _Atomic_Fence( Atomic_Order order )
0177 {
0178 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0179   std::atomic_thread_fence( order );
0180 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0181   atomic_thread_fence( order );
0182 #else
0183   (void) order;
0184   RTEMS_COMPILER_MEMORY_BARRIER();
0185 #endif
0186 }
0187 
0188 /**
0189  * @brief Initializes Uint.
0190  *
0191  * @param[out] obj The CPU atomic Uint to initialize.
0192  * @param desired The desired value for @a obj.
0193  */
0194 static inline void _Atomic_Init_uint( Atomic_Uint *obj, unsigned int desired )
0195 {
0196 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0197   reinterpret_cast<std::atomic_uint *>( obj )->store( desired );
0198 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0199   atomic_init( obj, desired );
0200 #else
0201   *obj = desired;
0202 #endif
0203 }
0204 
0205 /**
0206  * @brief Initializes Ulong.
0207  *
0208  * @param[out] obj The CPU atomic Ulong to initialize.
0209  * @param desired The desired value for @a obj.
0210  */
0211 static inline void _Atomic_Init_ulong( Atomic_Ulong *obj, unsigned long desired )
0212 {
0213 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0214   reinterpret_cast<std::atomic_ulong *>( obj )->store( desired );
0215 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0216   atomic_init( obj, desired );
0217 #else
0218   *obj = desired;
0219 #endif
0220 }
0221 
0222 /**
0223  * @brief Initializes Uintptr.
0224  *
0225  * @param[out] obj The CPU atomic Uintptr to initialize.
0226  * @param desired The desired value for @a obj.
0227  */
0228 static inline void _Atomic_Init_uintptr( Atomic_Uintptr *obj, uintptr_t desired )
0229 {
0230 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0231   reinterpret_cast<std::atomic_uintptr_t *>( obj )->store( desired );
0232 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0233   atomic_init( obj, desired );
0234 #else
0235   *obj = desired;
0236 #endif
0237 }
0238 
0239 /**
0240  * @brief Loads value of Uint considering the order.
0241  *
0242  * @param obj The CPU atomic Uint to get the value from.
0243  * @param order The atomic order for getting the value.
0244  *
0245  * @return The value of @a obj considering the @a order.
0246  */
0247 static inline unsigned int _Atomic_Load_uint( const Atomic_Uint *obj, Atomic_Order order )
0248 {
0249 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0250   return reinterpret_cast<const std::atomic_uint *>( obj )->load( order );
0251 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0252   return atomic_load_explicit( obj, order );
0253 #else
0254   unsigned int val;
0255 
0256   (void) order;
0257   val = *obj;
0258   RTEMS_COMPILER_MEMORY_BARRIER();
0259 
0260   return val;
0261 #endif
0262 }
0263 
0264 /**
0265  * @brief Loads value of Ulong considering the order.
0266  *
0267  * @param obj The CPU atomic Ulong to get the value from.
0268  * @param order The atomic order for getting the value.
0269  *
0270  * @return The value of @a obj considering the @a order.
0271  */
0272 static inline unsigned long _Atomic_Load_ulong( const Atomic_Ulong *obj, Atomic_Order order )
0273 {
0274 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0275   return reinterpret_cast<const std::atomic_ulong *>( obj )->load( order );
0276 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0277   return atomic_load_explicit( obj, order );
0278 #else
0279   unsigned long val;
0280 
0281   (void) order;
0282   val = *obj;
0283   RTEMS_COMPILER_MEMORY_BARRIER();
0284 
0285   return val;
0286 #endif
0287 }
0288 
0289 /**
0290  * @brief Loads value of Uintptr considering the order.
0291  *
0292  * @param obj The CPU atomic Uintptr to get the value from.
0293  * @param order The atomic order for getting the value.
0294  *
0295  * @return The value of @a obj considering the @a order.
0296  */
0297 static inline uintptr_t _Atomic_Load_uintptr( const Atomic_Uintptr *obj, Atomic_Order order )
0298 {
0299 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0300   return reinterpret_cast<const std::atomic_uintptr_t *>( obj )->load( order );
0301 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0302   return atomic_load_explicit( obj, order );
0303 #else
0304   uintptr_t val;
0305 
0306   (void) order;
0307   val = *obj;
0308   RTEMS_COMPILER_MEMORY_BARRIER();
0309 
0310   return val;
0311 #endif
0312 }
0313 
0314 /**
0315  * @brief Stores a value to Uint considering the order.
0316  *
0317  * @param[out] obj The CPU atomic Uint to store a value in.
0318  * @param desired The desired value for @a obj.
0319  * @param order The atomic order for storing the value.
0320  */
0321 static inline void _Atomic_Store_uint( Atomic_Uint *obj, unsigned int desired, Atomic_Order order )
0322 {
0323 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0324   reinterpret_cast<std::atomic_uint *>( obj )->store( desired, order );
0325 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0326   atomic_store_explicit( obj, desired, order );
0327 #else
0328   (void) order;
0329   RTEMS_COMPILER_MEMORY_BARRIER();
0330   *obj = desired;
0331 #endif
0332 }
0333 
0334 /**
0335  * @brief Stores a value to Ulong considering the order.
0336  *
0337  * @param[out] obj The CPU atomic Ulong to store a value in.
0338  * @param desired The desired value for @a obj.
0339  * @param order The atomic order for storing the value.
0340  */
0341 static inline void _Atomic_Store_ulong( Atomic_Ulong *obj, unsigned long desired, Atomic_Order order )
0342 {
0343 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0344   reinterpret_cast<std::atomic_ulong *>( obj )->store( desired, order );
0345 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0346   atomic_store_explicit( obj, desired, order );
0347 #else
0348   (void) order;
0349   RTEMS_COMPILER_MEMORY_BARRIER();
0350   *obj = desired;
0351 #endif
0352 }
0353 
0354 /**
0355  * @brief Stores a value to Uintptr considering the order.
0356  *
0357  * @param[out] obj The CPU atomic Uintptr to store a value in.
0358  * @param desired The desired value for @a obj.
0359  * @param order The atomic order for storing the value.
0360  */
0361 static inline void _Atomic_Store_uintptr( Atomic_Uintptr *obj, uintptr_t desired, Atomic_Order order )
0362 {
0363 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0364   reinterpret_cast<std::atomic_uintptr_t *>( obj )->store( desired, order );
0365 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0366   atomic_store_explicit( obj, desired, order );
0367 #else
0368   (void) order;
0369   RTEMS_COMPILER_MEMORY_BARRIER();
0370   *obj = desired;
0371 #endif
0372 }
0373 
0374 /**
0375  * @brief Fetches current value of Uint and adds a value to the stored value.
0376  *
0377  * @param[in, out] obj The CPU atomic Uint to get the value from and add @a arg to.
0378  * @param arg The value to add to @a obj.
0379  * @param order The atomic order for the operation.
0380  *
0381  * @return The value of @a obj prior to the addition of @a arg.
0382  */
0383 static inline unsigned int _Atomic_Fetch_add_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order )
0384 {
0385 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0386   return reinterpret_cast<std::atomic_uint *>( obj )->fetch_add( arg, order );
0387 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0388   return atomic_fetch_add_explicit( obj, arg, order );
0389 #else
0390   unsigned int val;
0391   ISR_Level level;
0392 
0393   (void) order;
0394   _ISR_Local_disable( level );
0395   val = *obj;
0396   *obj = val + arg;
0397   _ISR_Local_enable( level );
0398 
0399   return val;
0400 #endif
0401 }
0402 
0403 /**
0404  * @brief Fetches current value of Ulong and adds a value to the stored value.
0405  *
0406  * @param[in, out] obj The CPU atomic Ulong to get the value from and add @a arg to.
0407  * @param arg The value to add to @a obj.
0408  * @param order The atomic order for the operation.
0409  *
0410  * @return The value of @a obj prior to the addition of @a arg.
0411  */
0412 static inline unsigned long _Atomic_Fetch_add_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order )
0413 {
0414 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0415   return reinterpret_cast<std::atomic_ulong *>( obj )->fetch_add( arg, order );
0416 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0417   return atomic_fetch_add_explicit( obj, arg, order );
0418 #else
0419   unsigned long val;
0420   ISR_Level level;
0421 
0422   (void) order;
0423   _ISR_Local_disable( level );
0424   val = *obj;
0425   *obj = val + arg;
0426   _ISR_Local_enable( level );
0427 
0428   return val;
0429 #endif
0430 }
0431 
0432 /**
0433  * @brief Fetches current value of Uintptr and adds a value to the stored value.
0434  *
0435  * @param[in, out] obj The CPU atomic Uintptr to get the value from and add @a arg to.
0436  * @param arg The value to add to @a obj.
0437  * @param order The atomic order for the operation.
0438  *
0439  * @return The value of @a obj prior to the addition of @a arg.
0440  */
0441 static inline uintptr_t _Atomic_Fetch_add_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order )
0442 {
0443 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0444   return reinterpret_cast<std::atomic_uintptr_t *>( obj )->fetch_add( arg, order );
0445 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0446   return atomic_fetch_add_explicit( obj, arg, order );
0447 #else
0448   uintptr_t val;
0449   ISR_Level level;
0450 
0451   (void) order;
0452   _ISR_Local_disable( level );
0453   val = *obj;
0454   *obj = val + arg;
0455   _ISR_Local_enable( level );
0456 
0457   return val;
0458 #endif
0459 }
0460 
0461 /**
0462  * @brief Fetches current value of Uint and subtracts a value from the stored value.
0463  *
0464  * @param[in, out] obj The CPU atomic Uint to get the value from and subtract @a arg from.
0465  * @param arg The value to subtract from @a obj.
0466  * @param order The atomic order for the operation.
0467  *
0468  * @return The value of @a obj prior to the subtraction of @a arg.
0469  */
0470 static inline unsigned int _Atomic_Fetch_sub_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order )
0471 {
0472 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0473   return reinterpret_cast<std::atomic_uint *>( obj )->fetch_sub( arg, order );
0474 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0475   return atomic_fetch_sub_explicit( obj, arg, order );
0476 #else
0477   unsigned int val;
0478   ISR_Level level;
0479 
0480   (void) order;
0481   _ISR_Local_disable( level );
0482   val = *obj;
0483   *obj = val - arg;
0484   _ISR_Local_enable( level );
0485 
0486   return val;
0487 #endif
0488 }
0489 
0490 /**
0491  * @brief Fetches current value of Ulong and subtracts a value from the stored value.
0492  *
0493  * @param[in, out] obj The CPU atomic Ulong to get the value from and subtract @a arg from.
0494  * @param arg The value to subtract from @a obj.
0495  * @param order The atomic order for the operation.
0496  *
0497  * @return The value of @a obj prior to the subtraction of @a arg.
0498  */
0499 static inline unsigned long _Atomic_Fetch_sub_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order )
0500 {
0501 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0502   return reinterpret_cast<std::atomic_ulong *>( obj )->fetch_sub( arg, order );
0503 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0504   return atomic_fetch_sub_explicit( obj, arg, order );
0505 #else
0506   unsigned long val;
0507   ISR_Level level;
0508 
0509   (void) order;
0510   _ISR_Local_disable( level );
0511   val = *obj;
0512   *obj = val - arg;
0513   _ISR_Local_enable( level );
0514 
0515   return val;
0516 #endif
0517 }
0518 
0519 /**
0520  * @brief Fetches current value of Uintptr and subtracts a value from the stored value.
0521  *
0522  * @param[in, out] obj The CPU atomic Uintptr to get the value from and subtract @a arg from.
0523  * @param arg The value to subtract from @a obj.
0524  * @param order The atomic order for the operation.
0525  *
0526  * @return The value of @a obj prior to the subtraction of @a arg.
0527  */
0528 static inline uintptr_t _Atomic_Fetch_sub_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order )
0529 {
0530 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0531   return reinterpret_cast<std::atomic_uintptr_t *>( obj )->fetch_sub( arg, order );
0532 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0533   return atomic_fetch_sub_explicit( obj, arg, order );
0534 #else
0535   uintptr_t val;
0536   ISR_Level level;
0537 
0538   (void) order;
0539   _ISR_Local_disable( level );
0540   val = *obj;
0541   *obj = val - arg;
0542   _ISR_Local_enable( level );
0543 
0544   return val;
0545 #endif
0546 }
0547 
0548 /**
0549  * @brief Fetches current value of Uint and ORs a value with the stored value.
0550  *
0551  * @param[in, out] obj The CPU atomic Uint to get the value from and OR @a arg to.
0552  * @param arg The value to OR with @a obj.
0553  * @param order The atomic order for the operation.
0554  *
0555  * @return The value of @a obj prior to the OR operation with @a arg.
0556  */
0557 static inline unsigned int _Atomic_Fetch_or_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order )
0558 {
0559 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0560   return reinterpret_cast<std::atomic_uint *>( obj )->fetch_or( arg, order );
0561 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0562   return atomic_fetch_or_explicit( obj, arg, order );
0563 #else
0564   unsigned int val;
0565   ISR_Level level;
0566 
0567   (void) order;
0568   _ISR_Local_disable( level );
0569   val = *obj;
0570   *obj = val | arg;
0571   _ISR_Local_enable( level );
0572 
0573   return val;
0574 #endif
0575 }
0576 
0577 /**
0578  * @brief Fetches current value of Ulong and ORs a value with the stored value.
0579  *
0580  * @param[in, out] obj The CPU atomic Ulong to get the value from and OR @a arg to.
0581  * @param arg The value to OR with @a obj.
0582  * @param order The atomic order for the operation.
0583  *
0584  * @return The value of @a obj prior to the OR operation with @a arg.
0585  */
0586 static inline unsigned long _Atomic_Fetch_or_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order )
0587 {
0588 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0589   return reinterpret_cast<std::atomic_ulong *>( obj )->fetch_or( arg, order );
0590 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0591   return atomic_fetch_or_explicit( obj, arg, order );
0592 #else
0593   unsigned long val;
0594   ISR_Level level;
0595 
0596   (void) order;
0597   _ISR_Local_disable( level );
0598   val = *obj;
0599   *obj = val | arg;
0600   _ISR_Local_enable( level );
0601 
0602   return val;
0603 #endif
0604 }
0605 
0606 /**
0607  * @brief Fetches current value of Uintptr and ORs a value with the stored value.
0608  *
0609  * @param[in, out] obj The CPU atomic Uintptr to get the value from and OR @a arg to.
0610  * @param arg The value to OR with @a obj.
0611  * @param order The atomic order for the operation.
0612  *
0613  * @return The value of @a obj prior to the OR operation with @a arg.
0614  */
0615 static inline uintptr_t _Atomic_Fetch_or_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order )
0616 {
0617 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0618   return reinterpret_cast<std::atomic_uintptr_t *>( obj )->fetch_or( arg, order );
0619 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0620   return atomic_fetch_or_explicit( obj, arg, order );
0621 #else
0622   uintptr_t val;
0623   ISR_Level level;
0624 
0625   (void) order;
0626   _ISR_Local_disable( level );
0627   val = *obj;
0628   *obj = val | arg;
0629   _ISR_Local_enable( level );
0630 
0631   return val;
0632 #endif
0633 }
0634 
0635 /**
0636  * @brief Fetches current value of Uint and ANDs a value with the stored value.
0637  *
0638  * @param[in, out] obj The CPU atomic Uint to get the value from and AND @a arg to.
0639  * @param arg The value to AND with @a obj.
0640  * @param order The atomic order for the operation.
0641  *
0642  * @return The value of @a obj prior to the AND operation with @a arg.
0643  */
0644 static inline unsigned int _Atomic_Fetch_and_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order )
0645 {
0646 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0647   return reinterpret_cast<std::atomic_uint *>( obj )->fetch_and( arg, order );
0648 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0649   return atomic_fetch_and_explicit( obj, arg, order );
0650 #else
0651   unsigned int val;
0652   ISR_Level level;
0653 
0654   (void) order;
0655   _ISR_Local_disable( level );
0656   val = *obj;
0657   *obj = val & arg;
0658   _ISR_Local_enable( level );
0659 
0660   return val;
0661 #endif
0662 }
0663 
0664 /**
0665  * @brief Fetches current value of Ulong and ANDs a value with the stored value.
0666  *
0667  * @param[in, out] obj The CPU atomic Ulong to get the value from and AND @a arg to.
0668  * @param arg The value to AND with @a obj.
0669  * @param order The atomic order for the operation.
0670  *
0671  * @return The value of @a obj prior to the AND operation with @a arg.
0672  */
0673 static inline unsigned long _Atomic_Fetch_and_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order )
0674 {
0675 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0676   return reinterpret_cast<std::atomic_ulong *>( obj )->fetch_and( arg, order );
0677 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0678   return atomic_fetch_and_explicit( obj, arg, order );
0679 #else
0680   unsigned long val;
0681   ISR_Level level;
0682 
0683   (void) order;
0684   _ISR_Local_disable( level );
0685   val = *obj;
0686   *obj = val & arg;
0687   _ISR_Local_enable( level );
0688 
0689   return val;
0690 #endif
0691 }
0692 
0693 /**
0694  * @brief Fetches current value of Uintptr and ANDs a value with the stored value.
0695  *
0696  * @param[in, out] obj The CPU atomic Uintptr to get the value from and AND @a arg to.
0697  * @param arg The value to AND with @a obj.
0698  * @param order The atomic order for the operation.
0699  *
0700  * @return The value of @a obj prior to the AND operation with @a arg.
0701  */
0702 static inline uintptr_t _Atomic_Fetch_and_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order )
0703 {
0704 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0705   return reinterpret_cast<std::atomic_uintptr_t *>( obj )->fetch_and( arg, order );
0706 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0707   return atomic_fetch_and_explicit( obj, arg, order );
0708 #else
0709   uintptr_t val;
0710   ISR_Level level;
0711 
0712   (void) order;
0713   _ISR_Local_disable( level );
0714   val = *obj;
0715   *obj = val & arg;
0716   _ISR_Local_enable( level );
0717 
0718   return val;
0719 #endif
0720 }
0721 
0722 /**
0723  * @brief Fetches current value of Uint and sets its value.
0724  *
0725  * @param[in, out] obj The CPU atomic Uint to get the value from and set the value to @a desired.
0726  * @param arg The value to set for @a obj.
0727  * @param order The atomic order for the operation.
0728  *
0729  * @return The value of @a obj prior to the exchange with @a desired.
0730  */
0731 static inline unsigned int _Atomic_Exchange_uint( Atomic_Uint *obj, unsigned int desired, Atomic_Order order )
0732 {
0733 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0734   return reinterpret_cast<std::atomic_uint *>( obj )->exchange( desired, order );
0735 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0736   return atomic_exchange_explicit( obj, desired, order );
0737 #else
0738   unsigned int val;
0739   ISR_Level level;
0740 
0741   (void) order;
0742   _ISR_Local_disable( level );
0743   val = *obj;
0744   *obj = desired;
0745   _ISR_Local_enable( level );
0746 
0747   return val;
0748 #endif
0749 }
0750 
0751 /**
0752  * @brief Fetches current value of Ulong and sets its value.
0753  *
0754  * @param[in, out] obj The CPU atomic Ulong to get the value from and set the value to @a desired.
0755  * @param arg The value to set for @a obj.
0756  * @param order The atomic order for the operation.
0757  *
0758  * @return The value of @a obj prior to the exchange with @a desired.
0759  */
0760 static inline unsigned long _Atomic_Exchange_ulong( Atomic_Ulong *obj, unsigned long desired, Atomic_Order order )
0761 {
0762 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0763   return reinterpret_cast<std::atomic_ulong *>( obj )->exchange( desired, order );
0764 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0765   return atomic_exchange_explicit( obj, desired, order );
0766 #else
0767   unsigned long val;
0768   ISR_Level level;
0769 
0770   (void) order;
0771   _ISR_Local_disable( level );
0772   val = *obj;
0773   *obj = desired;
0774   _ISR_Local_enable( level );
0775 
0776   return val;
0777 #endif
0778 }
0779 
0780 /**
0781  * @brief Fetches current value of Uintptr and sets its value.
0782  *
0783  * @param[in, out] obj The CPU atomic Uintptr to get the value from and set the value to @a desired.
0784  * @param arg The value to set for @a obj.
0785  * @param order The atomic order for the operation.
0786  *
0787  * @return The value of @a obj prior to the exchange with @a desired.
0788  */
0789 static inline uintptr_t _Atomic_Exchange_uintptr( Atomic_Uintptr *obj, uintptr_t desired, Atomic_Order order )
0790 {
0791 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0792   return reinterpret_cast<std::atomic_uintptr_t *>( obj )->exchange( desired, order );
0793 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0794   return atomic_exchange_explicit( obj, desired, order );
0795 #else
0796   uintptr_t val;
0797   ISR_Level level;
0798 
0799   (void) order;
0800   _ISR_Local_disable( level );
0801   val = *obj;
0802   *obj = desired;
0803   _ISR_Local_enable( level );
0804 
0805   return val;
0806 #endif
0807 }
0808 
0809 /**
0810  * @brief Checks if value of Uint is as expected.
0811  *
0812  * This method checks if the value of @a obj is equal to the value of @a expected.  If
0813  * this is the case, the value of @a obj is changed to @a desired.  Otherwise, the value
0814  * of @a obj is changed to @a expected.
0815  *
0816  * @param[in, out] obj The CPU atomic Uint to operate upon.
0817  * @param[in, out] expected The expected value of @a obj.  If @a obj has a different
0818  *      value, @a expected is changed to the actual value of @a obj.
0819  * @param desired The new value of @a obj if the old value of @a obj was as expected.
0820  * @param succ The order if it is successful.
0821  * @param fail The order if it fails.
0822  *
0823  * @retval true The old value of @a obj was as expected.
0824  * @retval false The old value of @a obj was not as expected.
0825  */
0826 static inline bool _Atomic_Compare_exchange_uint( Atomic_Uint *obj, unsigned int *expected, unsigned int desired, Atomic_Order succ, Atomic_Order fail )
0827 {
0828 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0829   return reinterpret_cast<std::atomic_uint *>( obj )->compare_exchange_strong( *expected, desired, succ, fail );
0830 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0831   return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail );
0832 #else
0833   bool success;
0834   ISR_Level level;
0835   unsigned int actual;
0836 
0837   (void) succ;
0838   (void) fail;
0839   _ISR_Local_disable( level );
0840   actual = *obj;
0841   success = ( actual == *expected );
0842   if ( success ) {
0843     *obj = desired;
0844   } else {
0845     *expected = actual;
0846   }
0847   _ISR_Local_enable( level );
0848 
0849   return success;
0850 #endif
0851 }
0852 
0853 /**
0854  * @brief Checks if value of Ulong is as expected.
0855  *
0856  * This method checks if the value of @a obj is equal to the value of @a expected.  If
0857  * this is the case, the value of @a obj is changed to @a desired.  Otherwise, the value
0858  * of @a obj is changed to @a expected.
0859  *
0860  * @param[in, out] obj The CPU atomic Ulong to operate upon.
0861  * @param[in, out] expected The expected value of @a obj.  If @a obj has a different
0862  *      value, @a expected is changed to the actual value of @a obj.
0863  * @param desired The new value of @a obj if the old value of @a obj was as expected.
0864  * @param succ The order if it is successful.
0865  * @param fail The order if it fails.
0866  *
0867  * @retval true The old value of @a obj was as expected.
0868  * @retval false The old value of @a obj was not as expected.
0869  */
0870 static inline bool _Atomic_Compare_exchange_ulong( Atomic_Ulong *obj, unsigned long *expected, unsigned long desired, Atomic_Order succ, Atomic_Order fail )
0871 {
0872 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0873   return reinterpret_cast<std::atomic_ulong *>( obj )->compare_exchange_strong( *expected, desired, succ, fail );
0874 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0875   return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail );
0876 #else
0877   bool success;
0878   ISR_Level level;
0879   unsigned long actual;
0880 
0881   (void) succ;
0882   (void) fail;
0883   _ISR_Local_disable( level );
0884   actual = *obj;
0885   success = ( actual == *expected );
0886   if ( success ) {
0887     *obj = desired;
0888   } else {
0889     *expected = actual;
0890   }
0891   _ISR_Local_enable( level );
0892 
0893   return success;
0894 #endif
0895 }
0896 
0897 /**
0898  * @brief Checks if value of Uintptr is as expected.
0899  *
0900  * This method checks if the value of @a obj is equal to the value of @a expected.  If
0901  * this is the case, the value of @a obj is changed to @a desired.  Otherwise, the value
0902  * of @a obj is changed to @a expected.
0903  *
0904  * @param[in, out] obj The CPU atomic Uintptr to operate upon.
0905  * @param[in, out] expected The expected value of @a obj.  If @a obj has a different
0906  *      value, @a expected is changed to the actual value of @a obj.
0907  * @param desired The new value of @a obj if the old value of @a obj was as expected.
0908  * @param succ The order if it is successful.
0909  * @param fail The order if it fails.
0910  *
0911  * @retval true The old value of @a obj was as expected.
0912  * @retval false The old value of @a obj was not as expected.
0913  */
0914 static inline bool _Atomic_Compare_exchange_uintptr( Atomic_Uintptr *obj, uintptr_t *expected, uintptr_t desired, Atomic_Order succ, Atomic_Order fail )
0915 {
0916 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0917   return reinterpret_cast<std::atomic_uintptr_t *>( obj )->compare_exchange_strong( *expected, desired, succ, fail );
0918 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0919   return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail );
0920 #else
0921   bool success;
0922   ISR_Level level;
0923   uintptr_t actual;
0924 
0925   (void) succ;
0926   (void) fail;
0927   _ISR_Local_disable( level );
0928   actual = *obj;
0929   success = ( actual == *expected );
0930   if ( success ) {
0931     *obj = desired;
0932   } else {
0933     *expected = actual;
0934   }
0935   _ISR_Local_enable( level );
0936 
0937   return success;
0938 #endif
0939 }
0940 
0941 /**
0942  * @brief Clears the atomic flag.
0943  *
0944  * @param[out] obj The atomic flag to be cleared.
0945  * @param order The atomic order for the operation.
0946  */
0947 static inline void _Atomic_Flag_clear( Atomic_Flag *obj, Atomic_Order order )
0948 {
0949 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0950   obj->clear( order );
0951 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0952   atomic_flag_clear_explicit( obj, order );
0953 #else
0954   (void) order;
0955   *obj = false;
0956 #endif
0957 }
0958 
0959 /**
0960  * @brief Returns current flag state and sets it.
0961  *
0962  * @param[in, out] obj The atomic flag to be set.
0963  * @param order The atomic order for the operation.
0964  *
0965  * @retval true @a obj was set prior to this operation.
0966  * @retval false @a obj was not set prior to this operation.
0967  */
0968 static inline bool _Atomic_Flag_test_and_set( Atomic_Flag *obj, Atomic_Order order )
0969 {
0970 #if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
0971   return obj->test_and_set( order );
0972 #elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
0973   return atomic_flag_test_and_set_explicit( obj, order );
0974 #else
0975   bool flag;
0976   ISR_Level level;
0977 
0978   (void) order;
0979   _ISR_Local_disable( level );
0980   flag = *obj;
0981   *obj = true;
0982   _ISR_Local_enable( level );
0983 
0984   return flag;
0985 #endif
0986 }
0987 
0988 /** @} */
0989 
0990 #endif /* _RTEMS_SCORE_ATOMIC_H */