This is Unofficial EPICS BASE Doxygen Site
epicsAtomicOSD.h
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2011 LANS LLC, as Operator of
3 * Los Alamos National Laboratory.
4 * Copyright (c) 2011 UChicago Argonne, LLC, as Operator of
5 * Argonne National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 
10 /*
11  * Author Jeffrey O. Hill
12  * johill@lanl.gov
13  */
14 
15 #ifndef epicsAtomicOSD_h
16 #define epicsAtomicOSD_h
17 
18 /* This is needed for vxWorks 6.8 to prevent an obnoxious compiler warning */
19 #ifndef _VSB_CONFIG_FILE
20 # define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h>
21 #endif
22 
23 #include "vxWorks.h" /* obtain the version of vxWorks */
24 #include "epicsAssert.h"
25 
26 /*
27  * With vxWorks 6.6 and later we need to use vxAtomicLib
28  * to implement this functionality correctly on SMP systems
29  */
30 #if _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606
31 
32 #include <limits.h>
33 #include <vxAtomicLib.h>
34 
35 #define EPICS_ATOMIC_OS_NAME "VX-ATOMICLIB"
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif /* __cplusplus */
40 
41 #ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
42 #define EPICS_ATOMIC_READ_MEMORY_BARRIER
44 {
46 }
47 #endif
48 
49 #ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
50 #define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
52 {
54 }
55 #endif
56 
57 /*
58  * we make the probably correct guess that if ULONG_MAX
59  * is the same as UINT_MAX then sizeof ( atomic_t )
60  * will be the same as sizeof ( size_t )
61  *
62  * if ULONG_MAX != UINT_MAX then its 64 bit vxWorks and
63  * WRS doesnt not supply at this time the atomic interface
64  * for 8 byte integers that is needed - so that architecture
65  * receives the lock synchronized version
66  */
67 #if ULONG_MAX == UINT_MAX
68 
69 STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( size_t ) );
70 STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( EpicsAtomicPtrT ) );
71 
72 
73 #ifndef EPICS_ATOMIC_INCR_SIZET
74 #define EPICS_ATOMIC_INCR_SIZET
75 EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT ( size_t * pTarget )
76 {
77  atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
78  const atomic_t oldVal = vxAtomicInc ( pTarg );
79  return 1 + ( size_t ) ( oldVal );
80 }
81 #endif
82 
83 #ifndef EPICS_ATOMIC_DECR_SIZET
84 #define EPICS_ATOMIC_DECR_SIZET
85 EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT ( size_t * pTarget )
86 {
87  atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
88  const atomic_t oldVal = vxAtomicDec ( pTarg );
89  return ( ( size_t ) oldVal ) - 1u;
90 }
91 #endif
92 
93 #ifndef EPICS_ATOMIC_ADD_SIZET
94 #define EPICS_ATOMIC_ADD_SIZET
95 EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT ( size_t * pTarget, size_t delta )
96 {
97  /*
98  * vxAtomicLib doc indicates that vxAtomicAdd is
99  * implemented using signed arithmetic, but it
100  * does not change the end result because twos
101  * complement addition is used in either case
102  */
103  atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
104  const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta );
105  return delta + ( size_t ) oldVal;
106 }
107 #endif
108 
109 #ifndef EPICS_ATOMIC_SUB_SIZET
110 #define EPICS_ATOMIC_SUB_SIZET
111 EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT ( size_t * pTarget, size_t delta )
112 {
113  /*
114  * vxAtomicLib doc indicates that vxAtomicSub is
115  * implemented using signed arithmetic, but it
116  * does not change the end result because twos
117  * complement subtraction is used in either case
118  */
119  atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
120  const atomic_t oldVal = vxAtomicSub ( pTarg, (atomic_t) delta );
121  return ( ( size_t ) oldVal ) - delta;
122 }
123 #endif
124 
125 #ifndef EPICS_ATOMIC_CAS_SIZET
126 #define EPICS_ATOMIC_CAS_SIZET
127 EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT ( size_t * pTarget,
128  size_t oldVal, size_t newVal )
129 {
130  atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
131  return ( size_t ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
132 }
133 #endif
134 
135 #ifndef EPICS_ATOMIC_CAS_PTRT
136 #define EPICS_ATOMIC_CAS_PTRT
138  EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal )
139 {
140  atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
141  return (EpicsAtomicPtrT) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
142 }
143 #endif
144 
145 #else /* ULONG_MAX == UINT_MAX */
146 
147 /*
148  * if its 64 bit SMP vxWorks and the compiler doesnt
149  * have an intrinsic then maybe there isnt any way to
150  * implement these without using a global lock because
151  * size_t is maybe bigger than atomic_t
152  *
153  * I dont yet have access to vxWorks manuals for
154  * 64 bit systems so this is still undecided, but is
155  * defaulting now to a global lock
156  */
157 
158 #endif /* ULONG_MAX == UINT_MAX */
159 
160 STATIC_ASSERT ( sizeof ( atomic_t ) == sizeof ( int ) );
161 
162 #ifndef EPICS_ATOMIC_INCR_INTT
163 #define EPICS_ATOMIC_INCR_INTT
164 EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT ( int * pTarget )
165 {
166  atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
167  const atomic_t oldVal = vxAtomicInc ( pTarg );
168  return 1 + ( int ) oldVal;
169 }
170 #endif
171 
172 #ifndef EPICS_ATOMIC_DECR_INTT
173 #define EPICS_ATOMIC_DECR_INTT
174 EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT ( int * pTarget )
175 {
176  atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
177  const atomic_t oldVal = vxAtomicDec ( pTarg );
178  return ( ( int ) oldVal ) - 1;
179 }
180 #endif
181 
182 #ifndef EPICS_ATOMIC_ADD_INTT
183 #define EPICS_ATOMIC_ADD_INTT
184 EPICS_ATOMIC_INLINE int epicsAtomicAddIntT ( int * pTarget, int delta )
185 {
186  atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
187  const atomic_t oldVal = vxAtomicAdd ( pTarg, (atomic_t) delta );
188  return delta + ( int ) oldVal;
189 }
190 #endif
191 
192 #ifndef EPICS_ATOMIC_CAS_INTT
193 #define EPICS_ATOMIC_CAS_INTT
195  int oldVal, int newVal )
196 {
197  atomic_t * const pTarg = ( atomic_t * ) ( pTarget );
198  return ( int ) vxCas ( pTarg, (atomic_t) oldVal, (atomic_t) newVal );
199 }
200 #endif
201 
202 #ifdef __cplusplus
203 } /* end of extern "C" */
204 #endif /* __cplusplus */
205 
206 #else /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */
207 
208 #include "vxLib.h"
209 #include "intLib.h"
210 
211 #define EPICS_ATOMIC_OS_NAME "VX-INTLIB"
212 
213 #ifdef __cplusplus
214 extern "C" {
215 #endif /* __cplusplus */
216 
217 #ifndef EPICS_ATOMIC_LOCK
218 #define EPICS_ATOMIC_LOCK
219 
221 
223 {
224  pKey->m_key = intLock ();
225 }
226 
228 {
229  intUnlock ( pKey->m_key );
230 }
231 #endif
232 
233 #ifndef EPICS_ATOMIC_READ_MEMORY_BARRIER
234 #define EPICS_ATOMIC_READ_MEMORY_BARRIER
235 /*
236  * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system
237  * (we are not protecting against multiple access to memory mapped IO)
238  */
240 #endif
241 
242 #ifndef EPICS_ATOMIC_WRITE_MEMORY_BARRIER
243 #define EPICS_ATOMIC_WRITE_MEMORY_BARRIER
244 /*
245  * no need for memory barrior since prior to vxWorks 6.6 it is a single cpu system
246  * (we are not protecting against multiple access to memory mapped IO)
247  */
249 #endif
250 
251 #ifdef __cplusplus
252 } /* end of extern "C" */
253 #endif /* __cplusplus */
254 
255 #endif /* _WRS_VXWORKS_MAJOR * 100 + _WRS_VXWORKS_MINOR >= 606 */
256 
257 #include "epicsAtomicDefault.h"
258 
259 #endif /* epicsAtomicOSD_h */
260 
EPICS_ATOMIC_INLINE size_t epicsAtomicCmpAndSwapSizeT(size_t *pTarget, size_t oldVal, size_t newVal)
An EPICS-specific replacement for ANSI C&#39;s assert.
EPICS_ATOMIC_INLINE size_t epicsAtomicSubSizeT(size_t *pTarget, size_t delta)
struct EpicsAtomicLockKey EpicsAtomicLockKey
EPICS_ATOMIC_INLINE int epicsAtomicCmpAndSwapIntT(int *pTarget, int oldVal, int newVal)
#define VX_MEM_BARRIER_R()
Definition: epicsMMIO.h:160
EPICS_ATOMIC_INLINE size_t epicsAtomicAddSizeT(size_t *pTarget, size_t delta)
EPICS_ATOMIC_INLINE size_t epicsAtomicDecrSizeT(size_t *pTarget)
LIBCOM_API void epicsAtomicLock(struct EpicsAtomicLockKey *)
void * EpicsAtomicPtrT
Definition: epicsAtomic.h:28
#define EPICS_ATOMIC_INLINE
Definition: epicsAtomic.h:22
#define STATIC_ASSERT(expr)
Declare a condition that should be true at compile-time.
Definition: epicsAssert.h:86
EPICS_ATOMIC_INLINE void epicsAtomicWriteMemoryBarrier(void)
EPICS_ATOMIC_INLINE EpicsAtomicPtrT epicsAtomicCmpAndSwapPtrT(EpicsAtomicPtrT *pTarget, EpicsAtomicPtrT oldVal, EpicsAtomicPtrT newVal)
EPICS_ATOMIC_INLINE int epicsAtomicAddIntT(int *pTarget, int delta)
LIBCOM_API void epicsAtomicUnlock(struct EpicsAtomicLockKey *)
EPICS_ATOMIC_INLINE int epicsAtomicDecrIntT(int *pTarget)
EPICS_ATOMIC_INLINE int epicsAtomicIncrIntT(int *pTarget)
EPICS_ATOMIC_INLINE size_t epicsAtomicIncrSizeT(size_t *pTarget)
#define VX_MEM_BARRIER_W()
Definition: epicsMMIO.h:163
EPICS_ATOMIC_INLINE void epicsAtomicReadMemoryBarrier(void)