zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_atomic.h
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 
59 #ifndef _SDL_atomic_h_
60 #define _SDL_atomic_h_
61 
62 #include "SDL_stdinc.h"
63 #include "SDL_platform.h"
64 
65 #include "begin_code.h"
66 
67 /* Need to do this here because intrin.h has C++ code in it */
68 /* Visual Studio 2005 has a bug where intrin.h conflicts with winnt.h */
69 #if defined(_MSC_VER) && (_MSC_VER >= 1500)
70 #include <intrin.h>
71 #define HAVE_MSC_ATOMICS 1
72 #endif
73 
74 /* Set up for C function definitions, even when using C++ */
75 #ifdef __cplusplus
76 extern "C" {
77 #endif
78 
94 /* @{ */
95 
96 typedef int SDL_SpinLock;
97 
105 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock);
106 
112 extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock);
113 
119 extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock);
120 
121 /* @} *//* SDL AtomicLock */
122 
123 
128 #if defined(_MSC_VER) && (_MSC_VER > 1200)
129 void _ReadWriteBarrier(void);
130 #pragma intrinsic(_ReadWriteBarrier)
131 #define SDL_CompilerBarrier() _ReadWriteBarrier()
132 #elif defined(__GNUC__)
133 #define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory")
134 #else
135 #define SDL_CompilerBarrier() \
136 { SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); }
137 #endif
138 
158 #if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
159 #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("lwsync" : : : "memory")
160 #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("lwsync" : : : "memory")
161 #elif defined(__GNUC__) && defined(__arm__)
162 #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
163 #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
164 #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
165 #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
166 #ifdef __thumb__
167 /* The mcr instruction isn't available in thumb mode, use real functions */
170 #else
171 #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
172 #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
173 #endif /* __thumb__ */
174 #else
175 #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory")
176 #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory")
177 #endif /* __GNUC__ && __arm__ */
178 #else
179 /* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */
180 #define SDL_MemoryBarrierRelease() SDL_CompilerBarrier()
181 #define SDL_MemoryBarrierAcquire() SDL_CompilerBarrier()
182 #endif
183 
184 
185 /* Platform specific optimized versions of the atomic functions,
186  * you can disable these by defining SDL_DISABLE_ATOMIC_INLINE
187  */
188 #if defined(SDL_ATOMIC_DISABLED) && SDL_ATOMIC_DISABLED
189 #define SDL_DISABLE_ATOMIC_INLINE
190 #endif
191 #ifndef SDL_DISABLE_ATOMIC_INLINE
192 
193 #ifdef HAVE_MSC_ATOMICS
194 
195 #define SDL_AtomicSet(a, v) _InterlockedExchange((long*)&(a)->value, (v))
196 #define SDL_AtomicAdd(a, v) _InterlockedExchangeAdd((long*)&(a)->value, (v))
197 #define SDL_AtomicCAS(a, oldval, newval) (_InterlockedCompareExchange((long*)&(a)->value, (newval), (oldval)) == (oldval))
198 #define SDL_AtomicSetPtr(a, v) _InterlockedExchangePointer((a), (v))
199 #if _M_IX86
200 #define SDL_AtomicCASPtr(a, oldval, newval) (_InterlockedCompareExchange((long*)(a), (long)(newval), (long)(oldval)) == (long)(oldval))
201 #else
202 #define SDL_AtomicCASPtr(a, oldval, newval) (_InterlockedCompareExchangePointer((a), (newval), (oldval)) == (oldval))
203 #endif
204 
205 #elif defined(__MACOSX__)
206 #include <libkern/OSAtomic.h>
207 
208 #define SDL_AtomicCAS(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((oldval), (newval), &(a)->value)
209 #ifdef __LP64__
210 #define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap64Barrier((int64_t)(oldval), (int64_t)(newval), (int64_t*)(a))
211 #else
212 #define SDL_AtomicCASPtr(a, oldval, newval) OSAtomicCompareAndSwap32Barrier((int32_t)(oldval), (int32_t)(newval), (int32_t*)(a))
213 #endif
214 
215 #elif defined(HAVE_GCC_ATOMICS)
216 
217 #define SDL_AtomicSet(a, v) __sync_lock_test_and_set(&(a)->value, v)
218 #define SDL_AtomicAdd(a, v) __sync_fetch_and_add(&(a)->value, v)
219 #define SDL_AtomicSetPtr(a, v) __sync_lock_test_and_set(a, v)
220 #define SDL_AtomicCAS(a, oldval, newval) __sync_bool_compare_and_swap(&(a)->value, oldval, newval)
221 #define SDL_AtomicCASPtr(a, oldval, newval) __sync_bool_compare_and_swap(a, oldval, newval)
222 
223 #endif
224 
225 #endif /* !SDL_DISABLE_ATOMIC_INLINE */
226 
227 
232 #ifndef SDL_atomic_t_defined
233 typedef struct { int value; } SDL_atomic_t;
234 #endif
235 
243 #ifndef SDL_AtomicCAS
244 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval);
245 #endif
246 
252 #ifndef SDL_AtomicSet
254 {
255  int value;
256  do {
257  value = a->value;
258  } while (!SDL_AtomicCAS(a, value, v));
259  return value;
260 }
261 #endif
262 
266 #ifndef SDL_AtomicGet
268 {
269  int value = a->value;
271  return value;
272 }
273 #endif
274 
282 #ifndef SDL_AtomicAdd
284 {
285  int value;
286  do {
287  value = a->value;
288  } while (!SDL_AtomicCAS(a, value, (value + v)));
289  return value;
290 }
291 #endif
292 
296 #ifndef SDL_AtomicIncRef
297 #define SDL_AtomicIncRef(a) SDL_AtomicAdd(a, 1)
298 #endif
299 
306 #ifndef SDL_AtomicDecRef
307 #define SDL_AtomicDecRef(a) (SDL_AtomicAdd(a, -1) == 1)
308 #endif
309 
317 #ifndef SDL_AtomicCASPtr
318 extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void* *a, void *oldval, void *newval);
319 #endif
320 
326 #ifndef SDL_AtomicSetPtr
327 SDL_FORCE_INLINE void* SDL_AtomicSetPtr(void* *a, void* v)
328 {
329  void* value;
330  do {
331  value = *a;
332  } while (!SDL_AtomicCASPtr(a, value, v));
333  return value;
334 }
335 #endif
336 
340 #ifndef SDL_AtomicGetPtr
342 {
343  void* value = *a;
345  return value;
346 }
347 #endif
348 
349 
350 /* Ends C function definitions when using C++ */
351 #ifdef __cplusplus
352 }
353 #endif
354 
355 #include "close_code.h"
356 
357 #endif /* _SDL_atomic_h_ */
358 
359 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_CompilerBarrier()
Definition: SDL_atomic.h:135
DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock)
Unlock a spin lock by setting it to 0. Always returns immediately.
Definition: SDL_spinlock.c:109
#define SDL_MemoryBarrierRelease()
Definition: SDL_atomic.h:180
A type representing an atomic integer value. It is a struct so people don&#39;t accidentally use numeric ...
Definition: SDL_atomic.h:233
DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock)
Try to lock a spin lock by setting it to a non-zero value.
Definition: SDL_spinlock.c:34
SDL_bool
Definition: SDL_stdinc.h:116
SDL_FORCE_INLINE int SDL_AtomicAdd(SDL_atomic_t *a, int v)
Add to an atomic variable.
Definition: SDL_atomic.h:283
SDL_FORCE_INLINE int SDL_AtomicGet(SDL_atomic_t *a)
Get the value of an atomic variable.
Definition: SDL_atomic.h:267
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
#define DECLSPEC
Definition: begin_code.h:62
#define SDLCALL
Definition: begin_code.h:72
#define SDL_FORCE_INLINE
Definition: begin_code.h:141
#define SDL_MemoryBarrierAcquire()
Definition: SDL_atomic.h:181
SDL_FORCE_INLINE void * SDL_AtomicGetPtr(void **a)
Get the value of a pointer atomically.
Definition: SDL_atomic.h:341
SDL_FORCE_INLINE void * SDL_AtomicSetPtr(void **a, void *v)
Set a pointer to a value atomically.
Definition: SDL_atomic.h:327
DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock)
Lock a spin lock by setting it to a non-zero value.
Definition: SDL_spinlock.c:100
const GLdouble * v
Definition: glew.h:1377
DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval)
Set a pointer to a new value if it is currently an old value.
Definition: SDL_atomic.c:90
DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval)
Set an atomic variable to a new value if it is currently an old value.
Definition: SDL_atomic.c:75
EGLSurface EGLint void ** value
Definition: eglext.h:301
SDL_mutex * lock
Definition: SDL_events.c:75
SDL_FORCE_INLINE int SDL_AtomicSet(SDL_atomic_t *a, int v)
Set an atomic variable to a value.
Definition: SDL_atomic.h:253
int SDL_SpinLock
Definition: SDL_atomic.h:96