source: rtems/cpukit/include/rtems/score/atomic.h

Last change on this file was a799809, checked in by Sebastian Huber <sebastian.huber@…>, on 05/26/23 at 05:19:07

score: Remove CPU port atomic operations API

Use the C/C++ standard API directly.

  • Property mode set to 100644
File size: 27.6 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSScoreAtomic
7 *
8 * @brief This header file provides the interfaces of the
9 *   @ref RTEMSScoreAtomic.
10 */
11
12/*
13 * Copyright (C) 2015 embedded brains GmbH & Co. KG
14 * COPYRIGHT (c) 2012-2013 Deng Hengyi.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef _RTEMS_SCORE_ATOMIC_H
39#define _RTEMS_SCORE_ATOMIC_H
40
41#include <rtems/score/basedefs.h>
42
43/**
44 * @defgroup RTEMSScoreAtomic Atomic Operations
45 *
46 * @ingroup RTEMSScore
47 *
48 * @brief This group contains the atomic operations implementation.
49 *
50 * Atomic operations can be used to implement low-level synchronization
51 * primitives on SMP systems, like spin locks.  All atomic operations are
52 * defined in terms of C11 (ISO/IEC 9899:2011) or C++11 (ISO/IEC 14882:2011).
53 * For documentation use the standard documents.
54 *
55 * @{
56 */
57
58#ifdef RTEMS_SMP
59  #if defined(__cplusplus) \
60    && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))
61    /*
62     * The GCC 4.9 ships its own <stdatomic.h> which is not C++ compatible.  The
63     * suggested solution was to include <atomic> in case C++ is used.  This works
64     * at least with GCC 4.9.  See also:
65     *
66     * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60932
67     * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60940
68     */
69    #include <atomic>
70    #define _RTEMS_SCORE_ATOMIC_USE_ATOMIC
71  #else
72    #include <stdatomic.h>
73    #define _RTEMS_SCORE_ATOMIC_USE_STDATOMIC
74  #endif
75#else
76  #include <rtems/score/isrlevel.h>
77#endif
78
79#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
80
81typedef std::atomic_uint Atomic_Uint;
82
83typedef std::atomic_ulong Atomic_Ulong;
84
85typedef std::atomic_uintptr_t Atomic_Uintptr;
86
87typedef std::atomic_flag Atomic_Flag;
88
89typedef std::memory_order Atomic_Order;
90
91#define ATOMIC_ORDER_RELAXED std::memory_order_relaxed
92
93#define ATOMIC_ORDER_ACQUIRE std::memory_order_acquire
94
95#define ATOMIC_ORDER_RELEASE std::memory_order_release
96
97#define ATOMIC_ORDER_ACQ_REL std::memory_order_acq_rel
98
99#define ATOMIC_ORDER_SEQ_CST std::memory_order_seq_cst
100
101#define ATOMIC_INITIALIZER_UINT( value ) ATOMIC_VAR_INIT( value )
102
103#define ATOMIC_INITIALIZER_ULONG( value ) ATOMIC_VAR_INIT( value )
104
105#define ATOMIC_INITIALIZER_UINTPTR( value ) ATOMIC_VAR_INIT( value )
106
107#define ATOMIC_INITIALIZER_FLAG ATOMIC_FLAG_INIT
108
109#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
110
111typedef atomic_uint Atomic_Uint;
112
113typedef atomic_ulong Atomic_Ulong;
114
115typedef atomic_uintptr_t Atomic_Uintptr;
116
117typedef atomic_flag Atomic_Flag;
118
119typedef memory_order Atomic_Order;
120
121#define ATOMIC_ORDER_RELAXED memory_order_relaxed
122
123#define ATOMIC_ORDER_ACQUIRE memory_order_acquire
124
125#define ATOMIC_ORDER_RELEASE memory_order_release
126
127#define ATOMIC_ORDER_ACQ_REL memory_order_acq_rel
128
129#define ATOMIC_ORDER_SEQ_CST memory_order_seq_cst
130
131#define ATOMIC_INITIALIZER_UINT( value ) ATOMIC_VAR_INIT( value )
132
133#define ATOMIC_INITIALIZER_ULONG( value ) ATOMIC_VAR_INIT( value )
134
135#define ATOMIC_INITIALIZER_UINTPTR( value ) ATOMIC_VAR_INIT( value )
136
137#define ATOMIC_INITIALIZER_FLAG ATOMIC_FLAG_INIT
138
139#else
140
141typedef unsigned int Atomic_Uint;
142
143typedef unsigned long Atomic_Ulong;
144
145typedef uintptr_t Atomic_Uintptr;
146
147typedef bool Atomic_Flag;
148
149typedef int Atomic_Order;
150
151#define ATOMIC_ORDER_RELAXED 0
152
153#define ATOMIC_ORDER_ACQUIRE 2
154
155#define ATOMIC_ORDER_RELEASE 3
156
157#define ATOMIC_ORDER_ACQ_REL 4
158
159#define ATOMIC_ORDER_SEQ_CST 5
160
161#define ATOMIC_INITIALIZER_UINT( value ) ( value )
162
163#define ATOMIC_INITIALIZER_ULONG( value ) ( value )
164
165#define ATOMIC_INITIALIZER_UINTPTR( value ) ( value )
166
167#define ATOMIC_INITIALIZER_FLAG false
168
169#endif
170
171/**
172 * @brief Sets up a cpu fence.
173 *
174 * @param[out] order The order for the fence.
175 */
176static inline void _Atomic_Fence( Atomic_Order order )
177{
178#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
179  std::atomic_thread_fence( order );
180#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
181  atomic_thread_fence( order );
182#else
183  (void) order;
184  RTEMS_COMPILER_MEMORY_BARRIER();
185#endif
186}
187
188/**
189 * @brief Initializes Uint.
190 *
191 * @param[out] obj The CPU atomic Uint to initialize.
192 * @param desired The desired value for @a obj.
193 */
194static inline void _Atomic_Init_uint( Atomic_Uint *obj, unsigned int desired )
195{
196#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
197  obj->store( desired );
198#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
199  atomic_init( obj, desired );
200#else
201  *obj = desired;
202#endif
203}
204
205/**
206 * @brief Initializes Ulong.
207 *
208 * @param[out] obj The CPU atomic Ulong to initialize.
209 * @param desired The desired value for @a obj.
210 */
211static inline void _Atomic_Init_ulong( Atomic_Ulong *obj, unsigned long desired )
212{
213#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
214  obj->store( desired );
215#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
216  atomic_init( obj, desired );
217#else
218  *obj = desired;
219#endif
220}
221
222/**
223 * @brief Initializes Uintptr.
224 *
225 * @param[out] obj The CPU atomic Uintptr to initialize.
226 * @param desired The desired value for @a obj.
227 */
228static inline void _Atomic_Init_uintptr( Atomic_Uintptr *obj, uintptr_t desired )
229{
230#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
231  obj->store( desired );
232#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
233  atomic_init( obj, desired );
234#else
235  *obj = desired;
236#endif
237}
238
239/**
240 * @brief Loads value of Uint considering the order.
241 *
242 * @param obj The CPU atomic Uint to get the value from.
243 * @param order The atomic order for getting the value.
244 *
245 * @return The value of @a obj considering the @a order.
246 */
247static inline unsigned int _Atomic_Load_uint( const Atomic_Uint *obj, Atomic_Order order )
248{
249#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
250  return obj->load( order );
251#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
252  return atomic_load_explicit( obj, order );
253#else
254  unsigned int val;
255
256  (void) order;
257  val = *obj;
258  RTEMS_COMPILER_MEMORY_BARRIER();
259
260  return val;
261#endif
262}
263
264/**
265 * @brief Loads value of Ulong considering the order.
266 *
267 * @param obj The CPU atomic Ulong to get the value from.
268 * @param order The atomic order for getting the value.
269 *
270 * @return The value of @a obj considering the @a order.
271 */
272static inline unsigned long _Atomic_Load_ulong( const Atomic_Ulong *obj, Atomic_Order order )
273{
274#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
275  return obj->load( order );
276#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
277  return atomic_load_explicit( obj, order );
278#else
279  unsigned long val;
280
281  (void) order;
282  val = *obj;
283  RTEMS_COMPILER_MEMORY_BARRIER();
284
285  return val;
286#endif
287}
288
289/**
290 * @brief Loads value of Uintptr considering the order.
291 *
292 * @param obj The CPU atomic Uintptr to get the value from.
293 * @param order The atomic order for getting the value.
294 *
295 * @return The value of @a obj considering the @a order.
296 */
297static inline uintptr_t _Atomic_Load_uintptr( const Atomic_Uintptr *obj, Atomic_Order order )
298{
299#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
300  return obj->load( order );
301#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
302  return atomic_load_explicit( obj, order );
303#else
304  uintptr_t val;
305
306  (void) order;
307  val = *obj;
308  RTEMS_COMPILER_MEMORY_BARRIER();
309
310  return val;
311#endif
312}
313
314/**
315 * @brief Stores a value to Uint considering the order.
316 *
317 * @param[out] obj The CPU atomic Uint to store a value in.
318 * @param desired The desired value for @a obj.
319 * @param order The atomic order for storing the value.
320 */
321static inline void _Atomic_Store_uint( Atomic_Uint *obj, unsigned int desired, Atomic_Order order )
322{
323#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
324  obj->store( desired, order );
325#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
326  atomic_store_explicit( obj, desired, order );
327#else
328  (void) order;
329  RTEMS_COMPILER_MEMORY_BARRIER();
330  *obj = desired;
331#endif
332}
333
334/**
335 * @brief Stores a value to Ulong considering the order.
336 *
337 * @param[out] obj The CPU atomic Ulong to store a value in.
338 * @param desired The desired value for @a obj.
339 * @param order The atomic order for storing the value.
340 */
341static inline void _Atomic_Store_ulong( Atomic_Ulong *obj, unsigned long desired, Atomic_Order order )
342{
343#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
344  obj->store( desired, order );
345#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
346  atomic_store_explicit( obj, desired, order );
347#else
348  (void) order;
349  RTEMS_COMPILER_MEMORY_BARRIER();
350  *obj = desired;
351#endif
352}
353
354/**
355 * @brief Stores a value to Uintptr considering the order.
356 *
357 * @param[out] obj The CPU atomic Uintptr to store a value in.
358 * @param desired The desired value for @a obj.
359 * @param order The atomic order for storing the value.
360 */
361static inline void _Atomic_Store_uintptr( Atomic_Uintptr *obj, uintptr_t desired, Atomic_Order order )
362{
363#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
364  obj->store( desired, order );
365#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
366  atomic_store_explicit( obj, desired, order );
367#else
368  (void) order;
369  RTEMS_COMPILER_MEMORY_BARRIER();
370  *obj = desired;
371#endif
372}
373
374/**
375 * @brief Fetches current value of Uint and adds a value to the stored value.
376 *
377 * @param[in, out] obj The CPU atomic Uint to get the value from and add @a arg to.
378 * @param arg The value to add to @a obj.
379 * @param order The atomic order for the operation.
380 *
381 * @return The value of @a obj prior to the addition of @a arg.
382 */
383static inline unsigned int _Atomic_Fetch_add_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order )
384{
385#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
386  return obj->fetch_add( arg, order );
387#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
388  return atomic_fetch_add_explicit( obj, arg, order );
389#else
390  unsigned int val;
391  ISR_Level level;
392
393  (void) order;
394  _ISR_Local_disable( level );
395  val = *obj;
396  *obj = val + arg;
397  _ISR_Local_enable( level );
398
399  return val;
400#endif
401}
402
403/**
404 * @brief Fetches current value of Ulong and adds a value to the stored value.
405 *
406 * @param[in, out] obj The CPU atomic Ulong to get the value from and add @a arg to.
407 * @param arg The value to add to @a obj.
408 * @param order The atomic order for the operation.
409 *
410 * @return The value of @a obj prior to the addition of @a arg.
411 */
412static inline unsigned long _Atomic_Fetch_add_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order )
413{
414#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
415  return obj->fetch_add( arg, order );
416#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
417  return atomic_fetch_add_explicit( obj, arg, order );
418#else
419  unsigned long val;
420  ISR_Level level;
421
422  (void) order;
423  _ISR_Local_disable( level );
424  val = *obj;
425  *obj = val + arg;
426  _ISR_Local_enable( level );
427
428  return val;
429#endif
430}
431
432/**
433 * @brief Fetches current value of Uintptr and adds a value to the stored value.
434 *
435 * @param[in, out] obj The CPU atomic Uintptr to get the value from and add @a arg to.
436 * @param arg The value to add to @a obj.
437 * @param order The atomic order for the operation.
438 *
439 * @return The value of @a obj prior to the addition of @a arg.
440 */
441static inline uintptr_t _Atomic_Fetch_add_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order )
442{
443#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
444  return obj->fetch_add( arg, order );
445#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
446  return atomic_fetch_add_explicit( obj, arg, order );
447#else
448  uintptr_t val;
449  ISR_Level level;
450
451  (void) order;
452  _ISR_Local_disable( level );
453  val = *obj;
454  *obj = val + arg;
455  _ISR_Local_enable( level );
456
457  return val;
458#endif
459}
460
461/**
462 * @brief Fetches current value of Uint and subtracts a value from the stored value.
463 *
464 * @param[in, out] obj The CPU atomic Uint to get the value from and subtract @a arg from.
465 * @param arg The value to subtract from @a obj.
466 * @param order The atomic order for the operation.
467 *
468 * @return The value of @a obj prior to the subtraction of @a arg.
469 */
470static inline unsigned int _Atomic_Fetch_sub_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order )
471{
472#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
473  return obj->fetch_sub( arg, order );
474#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
475  return atomic_fetch_sub_explicit( obj, arg, order );
476#else
477  unsigned int val;
478  ISR_Level level;
479
480  (void) order;
481  _ISR_Local_disable( level );
482  val = *obj;
483  *obj = val - arg;
484  _ISR_Local_enable( level );
485
486  return val;
487#endif
488}
489
490/**
491 * @brief Fetches current value of Ulong and subtracts a value from the stored value.
492 *
493 * @param[in, out] obj The CPU atomic Ulong to get the value from and subtract @a arg from.
494 * @param arg The value to subtract from @a obj.
495 * @param order The atomic order for the operation.
496 *
497 * @return The value of @a obj prior to the subtraction of @a arg.
498 */
499static inline unsigned long _Atomic_Fetch_sub_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order )
500{
501#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
502  return obj->fetch_sub( arg, order );
503#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
504  return atomic_fetch_sub_explicit( obj, arg, order );
505#else
506  unsigned long val;
507  ISR_Level level;
508
509  (void) order;
510  _ISR_Local_disable( level );
511  val = *obj;
512  *obj = val - arg;
513  _ISR_Local_enable( level );
514
515  return val;
516#endif
517}
518
519/**
520 * @brief Fetches current value of Uintptr and subtracts a value from the stored value.
521 *
522 * @param[in, out] obj The CPU atomic Uintptr to get the value from and subtract @a arg from.
523 * @param arg The value to subtract from @a obj.
524 * @param order The atomic order for the operation.
525 *
526 * @return The value of @a obj prior to the subtraction of @a arg.
527 */
528static inline uintptr_t _Atomic_Fetch_sub_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order )
529{
530#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
531  return obj->fetch_sub( arg, order );
532#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
533  return atomic_fetch_sub_explicit( obj, arg, order );
534#else
535  uintptr_t val;
536  ISR_Level level;
537
538  (void) order;
539  _ISR_Local_disable( level );
540  val = *obj;
541  *obj = val - arg;
542  _ISR_Local_enable( level );
543
544  return val;
545#endif
546}
547
548/**
549 * @brief Fetches current value of Uint and ORs a value with the stored value.
550 *
551 * @param[in, out] obj The CPU atomic Uint to get the value from and OR @a arg to.
552 * @param arg The value to OR with @a obj.
553 * @param order The atomic order for the operation.
554 *
555 * @return The value of @a obj prior to the OR operation with @a arg.
556 */
557static inline unsigned int _Atomic_Fetch_or_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order )
558{
559#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
560  return obj->fetch_or( arg, order );
561#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
562  return atomic_fetch_or_explicit( obj, arg, order );
563#else
564  unsigned int val;
565  ISR_Level level;
566
567  (void) order;
568  _ISR_Local_disable( level );
569  val = *obj;
570  *obj = val | arg;
571  _ISR_Local_enable( level );
572
573  return val;
574#endif
575}
576
577/**
578 * @brief Fetches current value of Ulong and ORs a value with the stored value.
579 *
580 * @param[in, out] obj The CPU atomic Ulong to get the value from and OR @a arg to.
581 * @param arg The value to OR with @a obj.
582 * @param order The atomic order for the operation.
583 *
584 * @return The value of @a obj prior to the OR operation with @a arg.
585 */
586static inline unsigned long _Atomic_Fetch_or_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order )
587{
588#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
589  return obj->fetch_or( arg, order );
590#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
591  return atomic_fetch_or_explicit( obj, arg, order );
592#else
593  unsigned long val;
594  ISR_Level level;
595
596  (void) order;
597  _ISR_Local_disable( level );
598  val = *obj;
599  *obj = val | arg;
600  _ISR_Local_enable( level );
601
602  return val;
603#endif
604}
605
606/**
607 * @brief Fetches current value of Uintptr and ORs a value with the stored value.
608 *
609 * @param[in, out] obj The CPU atomic Uintptr to get the value from and OR @a arg to.
610 * @param arg The value to OR with @a obj.
611 * @param order The atomic order for the operation.
612 *
613 * @return The value of @a obj prior to the OR operation with @a arg.
614 */
615static inline uintptr_t _Atomic_Fetch_or_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order )
616{
617#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
618  return obj->fetch_or( arg, order );
619#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
620  return atomic_fetch_or_explicit( obj, arg, order );
621#else
622  uintptr_t val;
623  ISR_Level level;
624
625  (void) order;
626  _ISR_Local_disable( level );
627  val = *obj;
628  *obj = val | arg;
629  _ISR_Local_enable( level );
630
631  return val;
632#endif
633}
634
635/**
636 * @brief Fetches current value of Uint and ANDs a value with the stored value.
637 *
638 * @param[in, out] obj The CPU atomic Uint to get the value from and AND @a arg to.
639 * @param arg The value to AND with @a obj.
640 * @param order The atomic order for the operation.
641 *
642 * @return The value of @a obj prior to the AND operation with @a arg.
643 */
644static inline unsigned int _Atomic_Fetch_and_uint( Atomic_Uint *obj, unsigned int arg, Atomic_Order order )
645{
646#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
647  return obj->fetch_and( arg, order );
648#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
649  return atomic_fetch_and_explicit( obj, arg, order );
650#else
651  unsigned int val;
652  ISR_Level level;
653
654  (void) order;
655  _ISR_Local_disable( level );
656  val = *obj;
657  *obj = val & arg;
658  _ISR_Local_enable( level );
659
660  return val;
661#endif
662}
663
664/**
665 * @brief Fetches current value of Ulong and ANDs a value with the stored value.
666 *
667 * @param[in, out] obj The CPU atomic Ulong to get the value from and AND @a arg to.
668 * @param arg The value to AND with @a obj.
669 * @param order The atomic order for the operation.
670 *
671 * @return The value of @a obj prior to the AND operation with @a arg.
672 */
673static inline unsigned long _Atomic_Fetch_and_ulong( Atomic_Ulong *obj, unsigned long arg, Atomic_Order order )
674{
675#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
676  return obj->fetch_and( arg, order );
677#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
678  return atomic_fetch_and_explicit( obj, arg, order );
679#else
680  unsigned long val;
681  ISR_Level level;
682
683  (void) order;
684  _ISR_Local_disable( level );
685  val = *obj;
686  *obj = val & arg;
687  _ISR_Local_enable( level );
688
689  return val;
690#endif
691}
692
693/**
694 * @brief Fetches current value of Uintptr and ANDs a value with the stored value.
695 *
696 * @param[in, out] obj The CPU atomic Uintptr to get the value from and AND @a arg to.
697 * @param arg The value to AND with @a obj.
698 * @param order The atomic order for the operation.
699 *
700 * @return The value of @a obj prior to the AND operation with @a arg.
701 */
702static inline uintptr_t _Atomic_Fetch_and_uintptr( Atomic_Uintptr *obj, uintptr_t arg, Atomic_Order order )
703{
704#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
705  return obj->fetch_and( arg, order );
706#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
707  return atomic_fetch_and_explicit( obj, arg, order );
708#else
709  uintptr_t val;
710  ISR_Level level;
711
712  (void) order;
713  _ISR_Local_disable( level );
714  val = *obj;
715  *obj = val & arg;
716  _ISR_Local_enable( level );
717
718  return val;
719#endif
720}
721
722/**
723 * @brief Fetches current value of Uint and sets its value.
724 *
725 * @param[in, out] obj The CPU atomic Uint to get the value from and set the value to @a desired.
726 * @param arg The value to set for @a obj.
727 * @param order The atomic order for the operation.
728 *
729 * @return The value of @a obj prior to the exchange with @a desired.
730 */
731static inline unsigned int _Atomic_Exchange_uint( Atomic_Uint *obj, unsigned int desired, Atomic_Order order )
732{
733#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
734  return obj->exchange( desired, order );
735#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
736  return atomic_exchange_explicit( obj, desired, order );
737#else
738  unsigned int val;
739  ISR_Level level;
740
741  (void) order;
742  _ISR_Local_disable( level );
743  val = *obj;
744  *obj = desired;
745  _ISR_Local_enable( level );
746
747  return val;
748#endif
749}
750
751/**
752 * @brief Fetches current value of Ulong and sets its value.
753 *
754 * @param[in, out] obj The CPU atomic Ulong to get the value from and set the value to @a desired.
755 * @param arg The value to set for @a obj.
756 * @param order The atomic order for the operation.
757 *
758 * @return The value of @a obj prior to the exchange with @a desired.
759 */
760static inline unsigned long _Atomic_Exchange_ulong( Atomic_Ulong *obj, unsigned long desired, Atomic_Order order )
761{
762#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
763  return obj->exchange( desired, order );
764#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
765  return atomic_exchange_explicit( obj, desired, order );
766#else
767  unsigned long val;
768  ISR_Level level;
769
770  (void) order;
771  _ISR_Local_disable( level );
772  val = *obj;
773  *obj = desired;
774  _ISR_Local_enable( level );
775
776  return val;
777#endif
778}
779
780/**
781 * @brief Fetches current value of Uintptr and sets its value.
782 *
783 * @param[in, out] obj The CPU atomic Uintptr to get the value from and set the value to @a desired.
784 * @param arg The value to set for @a obj.
785 * @param order The atomic order for the operation.
786 *
787 * @return The value of @a obj prior to the exchange with @a desired.
788 */
789static inline uintptr_t _Atomic_Exchange_uintptr( Atomic_Uintptr *obj, uintptr_t desired, Atomic_Order order )
790{
791#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
792  return obj->exchange( desired, order );
793#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
794  return atomic_exchange_explicit( obj, desired, order );
795#else
796  uintptr_t val;
797  ISR_Level level;
798
799  (void) order;
800  _ISR_Local_disable( level );
801  val = *obj;
802  *obj = desired;
803  _ISR_Local_enable( level );
804
805  return val;
806#endif
807}
808
809/**
810 * @brief Checks if value of Uint is as expected.
811 *
812 * This method checks if the value of @a obj is equal to the value of @a expected.  If
813 * this is the case, the value of @a obj is changed to @a desired.  Otherwise, the value
814 * of @a obj is changed to @a expected.
815 *
816 * @param[in, out] obj The CPU atomic Uint to operate upon.
817 * @param[in, out] expected The expected value of @a obj.  If @a obj has a different
818 *      value, @a expected is changed to the actual value of @a obj.
819 * @param desired The new value of @a obj if the old value of @a obj was as expected.
820 * @param succ The order if it is successful.
821 * @param fail The order if it fails.
822 *
823 * @retval true The old value of @a obj was as expected.
824 * @retval false The old value of @a obj was not as expected.
825 */
826static inline bool _Atomic_Compare_exchange_uint( Atomic_Uint *obj, unsigned int *expected, unsigned int desired, Atomic_Order succ, Atomic_Order fail )
827{
828#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
829  return obj->compare_exchange_strong( *expected, desired, succ, fail );
830#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
831  return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail );
832#else
833  bool success;
834  ISR_Level level;
835  unsigned int actual;
836
837  (void) succ;
838  (void) fail;
839  _ISR_Local_disable( level );
840  actual = *obj;
841  success = ( actual == *expected );
842  if ( success ) {
843    *obj = desired;
844  } else {
845    *expected = actual;
846  }
847  _ISR_Local_enable( level );
848
849  return success;
850#endif
851}
852
853/**
854 * @brief Checks if value of Ulong is as expected.
855 *
856 * This method checks if the value of @a obj is equal to the value of @a expected.  If
857 * this is the case, the value of @a obj is changed to @a desired.  Otherwise, the value
858 * of @a obj is changed to @a expected.
859 *
860 * @param[in, out] obj The CPU atomic Ulong to operate upon.
861 * @param[in, out] expected The expected value of @a obj.  If @a obj has a different
862 *      value, @a expected is changed to the actual value of @a obj.
863 * @param desired The new value of @a obj if the old value of @a obj was as expected.
864 * @param succ The order if it is successful.
865 * @param fail The order if it fails.
866 *
867 * @retval true The old value of @a obj was as expected.
868 * @retval false The old value of @a obj was not as expected.
869 */
870static inline bool _Atomic_Compare_exchange_ulong( Atomic_Ulong *obj, unsigned long *expected, unsigned long desired, Atomic_Order succ, Atomic_Order fail )
871{
872#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
873  return obj->compare_exchange_strong( *expected, desired, succ, fail );
874#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
875  return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail );
876#else
877  bool success;
878  ISR_Level level;
879  unsigned long actual;
880
881  (void) succ;
882  (void) fail;
883  _ISR_Local_disable( level );
884  actual = *obj;
885  success = ( actual == *expected );
886  if ( success ) {
887    *obj = desired;
888  } else {
889    *expected = actual;
890  }
891  _ISR_Local_enable( level );
892
893  return success;
894#endif
895}
896
897/**
898 * @brief Checks if value of Uintptr is as expected.
899 *
900 * This method checks if the value of @a obj is equal to the value of @a expected.  If
901 * this is the case, the value of @a obj is changed to @a desired.  Otherwise, the value
902 * of @a obj is changed to @a expected.
903 *
904 * @param[in, out] obj The CPU atomic Uintptr to operate upon.
905 * @param[in, out] expected The expected value of @a obj.  If @a obj has a different
906 *      value, @a expected is changed to the actual value of @a obj.
907 * @param desired The new value of @a obj if the old value of @a obj was as expected.
908 * @param succ The order if it is successful.
909 * @param fail The order if it fails.
910 *
911 * @retval true The old value of @a obj was as expected.
912 * @retval false The old value of @a obj was not as expected.
913 */
914static inline bool _Atomic_Compare_exchange_uintptr( Atomic_Uintptr *obj, uintptr_t *expected, uintptr_t desired, Atomic_Order succ, Atomic_Order fail )
915{
916#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
917  return obj->compare_exchange_strong( *expected, desired, succ, fail );
918#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
919  return atomic_compare_exchange_strong_explicit( obj, expected, desired, succ, fail );
920#else
921  bool success;
922  ISR_Level level;
923  uintptr_t actual;
924
925  (void) succ;
926  (void) fail;
927  _ISR_Local_disable( level );
928  actual = *obj;
929  success = ( actual == *expected );
930  if ( success ) {
931    *obj = desired;
932  } else {
933    *expected = actual;
934  }
935  _ISR_Local_enable( level );
936
937  return success;
938#endif
939}
940
941/**
942 * @brief Clears the atomic flag.
943 *
944 * @param[out] obj The atomic flag to be cleared.
945 * @param order The atomic order for the operation.
946 */
947static inline void _Atomic_Flag_clear( Atomic_Flag *obj, Atomic_Order order )
948{
949#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
950  obj->clear( order );
951#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
952  atomic_flag_clear_explicit( obj, order );
953#else
954  (void) order;
955  *obj = false;
956#endif
957}
958
959/**
960 * @brief Returns current flag state and sets it.
961 *
962 * @param[in, out] obj The atomic flag to be set.
963 * @param order The atomic order for the operation.
964 *
965 * @retval true @a obj was set prior to this operation.
966 * @retval false @a obj was not set prior to this operation.
967 */
968static inline bool _Atomic_Flag_test_and_set( Atomic_Flag *obj, Atomic_Order order )
969{
970#if defined(_RTEMS_SCORE_ATOMIC_USE_ATOMIC)
971  return obj->test_and_set( order );
972#elif defined(_RTEMS_SCORE_ATOMIC_USE_STDATOMIC)
973  return atomic_flag_test_and_set_explicit( obj, order );
974#else
975  bool flag;
976  ISR_Level level;
977
978  (void) order;
979  _ISR_Local_disable( level );
980  flag = *obj;
981  *obj = true;
982  _ISR_Local_enable( level );
983
984  return flag;
985#endif
986}
987
988/** @} */
989
990#endif /* _RTEMS_SCORE_ATOMIC_H */
Note: See TracBrowser for help on using the repository browser.