source: rtems/cpukit/include/rtems/score/cpustdatomic.h @ 5803f37

5
Last change on this file since 5803f37 was 54733e6, checked in by Andreas Dachsberger <andreas.dachsberger@…>, on 04/08/19 at 10:08:56

doxygen: score: adjust doc in cpustdatomic.h to doxygen guidelines

Update #3706.

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