source: rtems/cpukit/include/rtems/score/cpustdatomic.h @ 7ebce359

Last change on this file since 7ebce359 was 7ebce359, checked in by Joel Sherrill <joel@…>, on 02/16/22 at 21:15:58

cpukit/include/rtems/score/[a-r]*.h: Change license to BSD-2

Updates #3053.

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