source: rtems/cpukit/include/rtems/score/cpustdatomic.h @ 09ddbde2

Last change on this file since 09ddbde2 was 09ddbde2, checked in by Sebastian Huber <sebastian.huber@…>, on 03/15/23 at 14:52:53

score: Add file to Doxygen group

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