This is Unofficial EPICS BASE Doxygen Site
epicsAtomicCD.h
Go to the documentation of this file.
1 
2 /*************************************************************************\
3 * Copyright (c) 2011 LANS LLC, as Operator of
4 * Los Alamos National Laboratory.
5 * Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
6 * National Laboratory.
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
13  * johill@lanl.gov
14  */
15 
16 #ifndef epicsAtomicCD_h
17 #define epicsAtomicCD_h
18 
19 #ifndef __GNUC__
20 # error this header is only for use with the gnu compiler
21 #endif
22 
23 #define EPICS_ATOMIC_CMPLR_NAME "GCC"
24 
25 #define GCC_ATOMIC_CONCAT( A, B ) GCC_ATOMIC_CONCATR(A,B)
26 #define GCC_ATOMIC_CONCATR( A, B ) ( A ## B )
27 
28 #define GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
29  GCC_ATOMIC_CONCAT ( \
30  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
31  __SIZEOF_INT__ )
32 
33 #define GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
34  GCC_ATOMIC_CONCAT ( \
35  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_, \
36  __SIZEOF_SIZE_T__ )
37 
38 #define GCC_ATOMIC_INTRINSICS_MIN_X86 \
39  ( defined ( __i486 ) || defined ( __pentium ) || \
40  defined ( __pentiumpro ) || defined ( __MMX__ ) )
41 
42 #define GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER \
43  ( ( __GNUC__ * 100 + __GNUC_MINOR__ ) >= 401 )
44 
45 #define GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER \
46  ( GCC_ATOMIC_INTRINSICS_MIN_X86 && \
47  GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER )
48 
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52 
53 /*
54  * We are optimistic that __sync_synchronize is implemented
55  * in all version four gcc invariant of target. The gnu doc
56  * seems to say that when not supported by architecture a call
57  * to an external function is generated but in practice
58  * this isn`t the case for some of the atomic intrinsics, and
59  * so there is an undefined symbol. So far we have not seen
60  * that with __sync_synchronize, but we can only guess based
61  * on experimental evidence.
62  *
63  * For example we know that when generating object code for
64  * 386 most of the atomic intrinsics are not present and
65  * we see undefined symbols with mingw, but we don`t have
66  * troubles with __sync_synchronize.
67  */
68 #if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER
69 
70 #ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
71 #define EPICS_ATOMIC_READ_MEMORY_BARRIER
73 {
74  __sync_synchronize ();
75 }
76 #endif
77 
78 #ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
79 #define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
81 {
82  __sync_synchronize ();
83 }
84 #endif
85 
86 #else
87 
88 #ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
89 #if GCC_ATOMIC_INTRINSICS_MIN_X86
90 #define EPICS_ATOMIC_READ_MEMORY_BARRIER
92 {
93  asm("mfence;");
94 }
95 #endif
96 #endif
97 
98 #ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
99 #if GCC_ATOMIC_INTRINSICS_MIN_X86
100 #define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
102 {
103  asm("mfence;");
104 }
105 #endif
106 #endif
107 
108 #endif /* if GCC_ATOMIC_INTRINSICS_GCC4_OR_BETTER */
109 
110 #if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T \
111  || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER
112 
113 #define EPICS_ATOMIC_INCR_INTT
115 {
116  return __sync_add_and_fetch ( pTarget, 1 );
117 }
118 
119 #define EPICS_ATOMIC_DECR_INTT
121 {
122  return __sync_sub_and_fetch ( pTarget, 1 );
123 }
124 
125 #define EPICS_ATOMIC_ADD_INTT
126 EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
127 {
128  return __sync_add_and_fetch ( pTarget, delta );
129 }
130 
131 #define EPICS_ATOMIC_CAS_INTT
133  int oldVal, int newVal )
134 {
135  return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
136 }
137 
138 #endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_INT_T */
139 
140 #if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T \
141  || GCC_ATOMIC_INTRINSICS_AVAIL_EARLIER
142 
143 #define EPICS_ATOMIC_INCR_SIZET
144 EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
145 {
146  return __sync_add_and_fetch ( pTarget, 1u );
147 }
148 
149 #define EPICS_ATOMIC_DECR_SIZET
150 EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
151 {
152  return __sync_sub_and_fetch ( pTarget, 1u );
153 }
154 
155 #define EPICS_ATOMIC_ADD_SIZET
156 EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
157 {
158  return __sync_add_and_fetch ( pTarget, delta );
159 }
160 
161 #define EPICS_ATOMIC_SUB_SIZET
162 EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
163 {
164  return __sync_sub_and_fetch ( pTarget, delta );
165 }
166 
167 #define EPICS_ATOMIC_CAS_SIZET
169  size_t oldVal, size_t newVal )
170 {
171  return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
172 }
173 
174 #define EPICS_ATOMIC_CAS_PTRT
176  EpicsAtomicPtrT * pTarget,
177  EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
178 {
179  return __sync_val_compare_and_swap ( pTarget, oldVal, newVal);
180 }
181 
182 #endif /* if GCC_ATOMIC_INTRINSICS_AVAIL_SIZE_T */
183 
184 #ifdef __cplusplus
185 } /* end of extern "C" */
186 #endif
187 
188 /*
189  * if currently unavailable as gcc intrinsics we
190  * will try for an os specific inline solution
191  */
192 #include "epicsAtomicOSD.h"
193 
194 #endif /* epicsAtomicCD_h */
EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT(size_t *pTarget, size_t oldVal, size_t newVal)
EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT(size_t *pTarget, size_t delta)
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier(void)
Definition: epicsAtomicCD.h:91
EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT(int *pTarget, int oldVal, int newVal)
EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT(size_t *pTarget, size_t delta)
EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT(size_t *pTarget)
void * EpicsAtomicPtrT
Definition: epicsAtomic.h:28
#define EPICS_ATOMIC_INLINE
Definition: epicsAtomic.h:22
EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT(EpicsAtomicPtrT *pTarget, EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal)
EPICS_ATOMIC_INLINE int epicsAtomicAddIntT(int *pTarget, int delta)
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier(void)
EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT(int *pTarget)
EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT(int *pTarget)
EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT(size_t *pTarget)