SDL  2.0
SDL_atomic.c File Reference
#include "../SDL_internal.h"
#include "SDL_atomic.h"
+ Include dependency graph for SDL_atomic.c:

Go to the source code of this file.

Macros

#define EMULATE_CAS   1
 

Functions

static SDL_INLINE void enterLock (void *a)
 
static SDL_INLINE void leaveLock (void *a)
 
SDL_bool 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. More...
 
SDL_bool SDL_AtomicCASPtr (void **a, void *oldval, void *newval)
 Set a pointer to a new value if it is currently an old value. More...
 
int SDL_AtomicSet (SDL_atomic_t *a, int v)
 Set an atomic variable to a value. More...
 
voidSDL_AtomicSetPtr (void **a, void *v)
 Set a pointer to a value atomically. More...
 
int SDL_AtomicAdd (SDL_atomic_t *a, int v)
 Add to an atomic variable. More...
 
int SDL_AtomicGet (SDL_atomic_t *a)
 Get the value of an atomic variable. More...
 
voidSDL_AtomicGetPtr (void **a)
 Get the value of a pointer atomically. More...
 
void SDL_MemoryBarrierReleaseFunction (void)
 
void SDL_MemoryBarrierAcquireFunction (void)
 

Variables

static SDL_SpinLock locks [32]
 

Macro Definition Documentation

◆ EMULATE_CAS

#define EMULATE_CAS   1

Definition at line 104 of file SDL_atomic.c.

Function Documentation

◆ enterLock()

static SDL_INLINE void enterLock ( void a)
static

Definition at line 111 of file SDL_atomic.c.

References locks, SDL_AtomicLock, and SDL_INLINE.

Referenced by SDL_AtomicCAS(), and SDL_AtomicCASPtr().

112 {
113  uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f);
114 
115  SDL_AtomicLock(&locks[index]);
116 }
#define SDL_AtomicLock
unsigned int uintptr_t
GLuint index
static SDL_SpinLock locks[32]
Definition: SDL_atomic.c:108
GLboolean GLboolean GLboolean GLboolean a

◆ leaveLock()

static SDL_INLINE void leaveLock ( void a)
static

Definition at line 119 of file SDL_atomic.c.

References locks, and SDL_AtomicUnlock.

Referenced by SDL_AtomicCAS(), and SDL_AtomicCASPtr().

120 {
121  uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f);
122 
123  SDL_AtomicUnlock(&locks[index]);
124 }
#define SDL_AtomicUnlock
unsigned int uintptr_t
GLuint index
static SDL_SpinLock locks[32]
Definition: SDL_atomic.c:108
GLboolean GLboolean GLboolean GLboolean a

◆ SDL_AtomicAdd()

int SDL_AtomicAdd ( SDL_atomic_t a,
int  v 
)

Add to an atomic variable.

Returns
The previous value of the atomic variable.
Note
This same style can be used for any number operation

Definition at line 237 of file SDL_atomic.c.

References SDL_AtomicCAS(), and SDL_atomic_t::value.

238 {
239 #ifdef HAVE_MSC_ATOMICS
240  return _InterlockedExchangeAdd((long*)&a->value, v);
241 #elif defined(HAVE_WATCOM_ATOMICS)
242  return _SDL_xadd_watcom(&a->value, v);
243 #elif defined(HAVE_GCC_ATOMICS)
244  return __sync_fetch_and_add(&a->value, v);
245 #elif defined(__SOLARIS__)
246  int pv = a->value;
247  membar_consumer();
248 #if defined(_LP64)
249  atomic_add_64((volatile uint64_t*)&a->value, v);
250 #elif !defined(_LP64)
251  atomic_add_32((volatile uint32_t*)&a->value, v);
252 #endif
253  return pv;
254 #else
255  int value;
256  do {
257  value = a->value;
258  } while (!SDL_AtomicCAS(a, value, (value + v)));
259  return value;
260 #endif
261 }
const GLdouble * v
Definition: SDL_opengl.h:2064
unsigned long long uint64_t
GLsizei const GLfloat * value
unsigned int uint32_t
SDL_bool 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:129

◆ SDL_AtomicCAS()

SDL_bool 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.

Returns
SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise.
Note
If you don't know what this function is for, you shouldn't use it!

Definition at line 129 of file SDL_atomic.c.

References enterLock(), leaveLock(), retval, SDL_FALSE, SDL_TRUE, and SDL_atomic_t::value.

Referenced by SDL_AtomicAdd(), SDL_AtomicGet(), and SDL_AtomicSet().

130 {
131 #ifdef HAVE_MSC_ATOMICS
132  return (_InterlockedCompareExchange((long*)&a->value, (long)newval, (long)oldval) == (long)oldval);
133 #elif defined(HAVE_WATCOM_ATOMICS)
134  return (SDL_bool) _SDL_cmpxchg_watcom(&a->value, newval, oldval);
135 #elif defined(HAVE_GCC_ATOMICS)
136  return (SDL_bool) __sync_bool_compare_and_swap(&a->value, oldval, newval);
137 #elif defined(__MACOSX__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */
138  return (SDL_bool) OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value);
139 #elif defined(__SOLARIS__) && defined(_LP64)
140  return (SDL_bool) ((int) atomic_cas_64((volatile uint64_t*)&a->value, (uint64_t)oldval, (uint64_t)newval) == oldval);
141 #elif defined(__SOLARIS__) && !defined(_LP64)
142  return (SDL_bool) ((int) atomic_cas_32((volatile uint32_t*)&a->value, (uint32_t)oldval, (uint32_t)newval) == oldval);
143 #elif EMULATE_CAS
145 
146  enterLock(a);
147  if (a->value == oldval) {
148  a->value = newval;
149  retval = SDL_TRUE;
150  }
151  leaveLock(a);
152 
153  return retval;
154 #else
155  #error Please define your platform.
156 #endif
157 }
unsigned long long uint64_t
SDL_bool retval
static SDL_INLINE void leaveLock(void *a)
Definition: SDL_atomic.c:119
static SDL_INLINE void enterLock(void *a)
Definition: SDL_atomic.c:111
SDL_bool
Definition: SDL_stdinc.h:139
unsigned int uint32_t

◆ SDL_AtomicCASPtr()

SDL_bool SDL_AtomicCASPtr ( void **  a,
void oldval,
void newval 
)

Set a pointer to a new value if it is currently an old value.

Returns
SDL_TRUE if the pointer was set, SDL_FALSE otherwise.
Note
If you don't know what this function is for, you shouldn't use it!

Definition at line 160 of file SDL_atomic.c.

References enterLock(), leaveLock(), retval, SDL_FALSE, and SDL_TRUE.

Referenced by SDL_AtomicGetPtr(), and SDL_AtomicSetPtr().

161 {
162 #if defined(HAVE_MSC_ATOMICS) && (_M_IX86)
163  return (_InterlockedCompareExchange((long*)a, (long)newval, (long)oldval) == (long)oldval);
164 #elif defined(HAVE_MSC_ATOMICS) && (!_M_IX86)
165  return (_InterlockedCompareExchangePointer(a, newval, oldval) == oldval);
166 #elif defined(HAVE_WATCOM_ATOMICS)
167  return (SDL_bool) _SDL_cmpxchg_watcom((int *)a, (long)newval, (long)oldval);
168 #elif defined(HAVE_GCC_ATOMICS)
169  return __sync_bool_compare_and_swap(a, oldval, newval);
170 #elif defined(__MACOSX__) && defined(__LP64__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */
171  return (SDL_bool) OSAtomicCompareAndSwap64Barrier((int64_t)oldval, (int64_t)newval, (int64_t*) a);
172 #elif defined(__MACOSX__) && !defined(__LP64__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */
173  return (SDL_bool) OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t*) a);
174 #elif defined(__SOLARIS__)
175  return (SDL_bool) (atomic_cas_ptr(a, oldval, newval) == oldval);
176 #elif EMULATE_CAS
178 
179  enterLock(a);
180  if (*a == oldval) {
181  *a = newval;
182  retval = SDL_TRUE;
183  }
184  leaveLock(a);
185 
186  return retval;
187 #else
188  #error Please define your platform.
189 #endif
190 }
signed int int32_t
SDL_bool retval
static SDL_INLINE void leaveLock(void *a)
Definition: SDL_atomic.c:119
static SDL_INLINE void enterLock(void *a)
Definition: SDL_atomic.c:111
SDL_bool
Definition: SDL_stdinc.h:139
GLboolean GLboolean GLboolean GLboolean a
signed long long int64_t

◆ SDL_AtomicGet()

int SDL_AtomicGet ( SDL_atomic_t a)

Get the value of an atomic variable.

Definition at line 264 of file SDL_atomic.c.

References SDL_AtomicCAS(), and SDL_atomic_t::value.

265 {
266 #ifdef HAVE_ATOMIC_LOAD_N
267  return __atomic_load_n(&a->value, __ATOMIC_SEQ_CST);
268 #else
269  int value;
270  do {
271  value = a->value;
272  } while (!SDL_AtomicCAS(a, value, value));
273  return value;
274 #endif
275 }
GLsizei const GLfloat * value
SDL_bool 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:129

◆ SDL_AtomicGetPtr()

void* SDL_AtomicGetPtr ( void **  a)

Get the value of a pointer atomically.

Definition at line 278 of file SDL_atomic.c.

References SDL_AtomicCASPtr().

279 {
280 #ifdef HAVE_ATOMIC_LOAD_N
281  return __atomic_load_n(a, __ATOMIC_SEQ_CST);
282 #else
283  void *value;
284  do {
285  value = *a;
286  } while (!SDL_AtomicCASPtr(a, value, value));
287  return value;
288 #endif
289 }
SDL_bool 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:160
GLsizei const GLfloat * value
GLboolean GLboolean GLboolean GLboolean a

◆ SDL_AtomicSet()

int SDL_AtomicSet ( SDL_atomic_t a,
int  v 
)

Set an atomic variable to a value.

Returns
The previous value of the atomic variable.

Definition at line 193 of file SDL_atomic.c.

References SDL_AtomicCAS(), and SDL_atomic_t::value.

194 {
195 #ifdef HAVE_MSC_ATOMICS
196  return _InterlockedExchange((long*)&a->value, v);
197 #elif defined(HAVE_WATCOM_ATOMICS)
198  return _SDL_xchg_watcom(&a->value, v);
199 #elif defined(HAVE_GCC_ATOMICS)
200  return __sync_lock_test_and_set(&a->value, v);
201 #elif defined(__SOLARIS__) && defined(_LP64)
202  return (int) atomic_swap_64((volatile uint64_t*)&a->value, (uint64_t)v);
203 #elif defined(__SOLARIS__) && !defined(_LP64)
204  return (int) atomic_swap_32((volatile uint32_t*)&a->value, (uint32_t)v);
205 #else
206  int value;
207  do {
208  value = a->value;
209  } while (!SDL_AtomicCAS(a, value, v));
210  return value;
211 #endif
212 }
const GLdouble * v
Definition: SDL_opengl.h:2064
unsigned long long uint64_t
GLsizei const GLfloat * value
unsigned int uint32_t
SDL_bool 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:129

◆ SDL_AtomicSetPtr()

void* SDL_AtomicSetPtr ( void **  a,
void v 
)

Set a pointer to a value atomically.

Returns
The previous value of the pointer.

Definition at line 215 of file SDL_atomic.c.

References SDL_AtomicCASPtr().

216 {
217 #if defined(HAVE_MSC_ATOMICS) && (_M_IX86)
218  return (void *) _InterlockedExchange((long *)a, (long) v);
219 #elif defined(HAVE_MSC_ATOMICS) && (!_M_IX86)
220  return _InterlockedExchangePointer(a, v);
221 #elif defined(HAVE_WATCOM_ATOMICS)
222  return (void *) _SDL_xchg_watcom((int *)a, (long)v);
223 #elif defined(HAVE_GCC_ATOMICS)
224  return __sync_lock_test_and_set(a, v);
225 #elif defined(__SOLARIS__)
226  return atomic_swap_ptr(a, v);
227 #else
228  void *value;
229  do {
230  value = *a;
231  } while (!SDL_AtomicCASPtr(a, value, v));
232  return value;
233 #endif
234 }
const GLdouble * v
Definition: SDL_opengl.h:2064
SDL_bool 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:160
GLsizei const GLfloat * value
GLboolean GLboolean GLboolean GLboolean a

◆ SDL_MemoryBarrierAcquireFunction()

void SDL_MemoryBarrierAcquireFunction ( void  )

Definition at line 298 of file SDL_atomic.c.

References SDL_MemoryBarrierAcquire.

299 {
301 }
#define SDL_MemoryBarrierAcquire()
Definition: SDL_atomic.h:190

◆ SDL_MemoryBarrierReleaseFunction()

void SDL_MemoryBarrierReleaseFunction ( void  )

Memory barriers are designed to prevent reads and writes from being reordered by the compiler and being seen out of order on multi-core CPUs.

A typical pattern would be for thread A to write some data and a flag, and for thread B to read the flag and get the data. In this case you would insert a release barrier between writing the data and the flag, guaranteeing that the data write completes no later than the flag is written, and you would insert an acquire barrier between reading the flag and reading the data, to ensure that all the reads associated with the flag have completed.

In this pattern you should always see a release barrier paired with an acquire barrier and you should gate the data reads/writes with a single flag variable.

For more information on these semantics, take a look at the blog post: http://preshing.com/20120913/acquire-and-release-semantics

Definition at line 292 of file SDL_atomic.c.

References SDL_MemoryBarrierRelease.

293 {
295 }
#define SDL_MemoryBarrierRelease()
Definition: SDL_atomic.h:189

Variable Documentation

◆ locks

SDL_SpinLock locks[32]
static

Definition at line 108 of file SDL_atomic.c.

Referenced by enterLock(), and leaveLock().