EPICS Base  7.0.6.1
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
epicsAtomicGCC.h
1 /*************************************************************************\
2 * Copyright (c) 2011 LANS LLC, as Operator of
3 * Los Alamos National Laboratory.
4 * Copyright (c) 2021 UChicago Argonne LLC, as Operator of Argonne
5 * National Laboratory.
6 * SPDX-License-Identifier: EPICS
7 * EPICS BASE is distributed subject to a Software License Agreement found
8 * in file LICENSE that is included with this distribution.
9 \*************************************************************************/
10 
11 /*
12  * Author Jeffrey O. Hill
14  */
15 
16 /*
17  * These implementations are the same for both GCC and Clang
18  */
19 
20 #ifndef INC_epicsAtomicGCC_H
21 #define INC_epicsAtomicGCC_H
22 
23 /* expands __GCC_HAVE_SYNC_COMPARE_AND_SWAP_ concatenating
24  * the numeric value __SIZEOF_*__
25  */
26 #define GCC_ATOMIC_CONCAT( A, B ) GCC_ATOMIC_CONCATR(A,B)
27 #define GCC_ATOMIC_CONCATR( A, B ) ( A ## B )
28 
29 #define GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
30  GCC_ATOMIC_CONCAT ( \
31  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
32  __SIZEOF_INT__ )
33 
34 /* we assume __SIZEOF_POINTER__ == __SIZEOF_SIZE_T__ */
35 #define GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
36  GCC_ATOMIC_CONCAT ( \
37  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
38  __SIZEOF_SIZE_T__ )
39 
40 /*
41  * As of GCC 8, the __sync_synchronize() is inlined for all
42  * known targets (aarch64, arm, i386, powerpc, and x86_64)
43  * except for arm <=6.
44  * Note that i386 inlines __sync_synchronize() but does not
45  * define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_*
46  */
47 #if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T || \
48  GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T || \
49  defined(__i386)
50 #define GCC_ATOMIC_INTRINSICS_AVAIL_SYNC 1
51 #else
52 #define GCC_ATOMIC_INTRINSICS_AVAIL_SYNC 0
53 #endif
54 /* The above macro is also used in epicsAtomicTest.cpp */
55 
56 #ifdef __cplusplus
57 extern "C" {
58 #endif
59 
60 #if GCC_ATOMIC_INTRINSICS_AVAIL_SYNC
61 
62 #ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
63 #define EPICS_ATOMIC_READ_MEMORY_BARRIER
64 EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier (void)
65 {
66  __sync_synchronize ();
67 }
68 #endif
69 
70 #ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
71 #define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
72 EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier (void)
73 {
74  __sync_synchronize ();
75 }
76 #endif
77 
78 #endif
79 
80 #if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T
81 
82 #define EPICS_ATOMIC_INCR_INTT
83 EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
84 {
85  return __sync_add_and_fetch ( pTarget, 1 );
86 }
87 
88 #define EPICS_ATOMIC_DECR_INTT
89 EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
90 {
91  return __sync_sub_and_fetch ( pTarget, 1 );
92 }
93 
94 #define EPICS_ATOMIC_ADD_INTT
95 EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
96 {
97  return __sync_add_and_fetch ( pTarget, delta );
98 }
99 
100 #define EPICS_ATOMIC_CAS_INTT
101 EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT ( int * pTarget,
102  int oldVal, int newVal )
103 {
104  return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
105 }
106 
107 #endif
108 
109 #if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T
110 
111 #define EPICS_ATOMIC_INCR_SIZET
112 EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
113 {
114  return __sync_add_and_fetch ( pTarget, 1u );
115 }
116 
117 #define EPICS_ATOMIC_DECR_SIZET
118 EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
119 {
120  return __sync_sub_and_fetch ( pTarget, 1u );
121 }
122 
123 #define EPICS_ATOMIC_ADD_SIZET
124 EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
125 {
126  return __sync_add_and_fetch ( pTarget, delta );
127 }
128 
129 #define EPICS_ATOMIC_SUB_SIZET
130 EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
131 {
132  return __sync_sub_and_fetch ( pTarget, delta );
133 }
134 
135 #define EPICS_ATOMIC_CAS_SIZET
136 EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
137  size_t oldVal, size_t newVal )
138 {
139  return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
140 }
141 
142 #define EPICS_ATOMIC_CAS_PTRT
143 EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT (
144  EpicsAtomicPtrT * pTarget,
145  EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
146 {
147  return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
148 }
149 
150 #endif
151 
152 #ifdef __cplusplus
153 } /* end of extern "C" */
154 #endif
155 
156 #endif /* INC_epicsAtomicGCC_H */