src/atomic/SDL_atomic.c
changeset 8088 e5d77d5e0fe2
parent 7860 2b0bcdea3a79
child 8092 46fb898f098d
     1.1 --- a/src/atomic/SDL_atomic.c	Sun Nov 24 21:15:58 2013 -0500
     1.2 +++ b/src/atomic/SDL_atomic.c	Sun Nov 24 21:04:51 2013 -0500
     1.3 @@ -22,13 +22,14 @@
     1.4  
     1.5  #include "SDL_atomic.h"
     1.6  
     1.7 -/* Note that we undefine the atomic operations here, in case they are
     1.8 -   defined as compiler intrinsics while building SDL but the library user
     1.9 -   doesn't have that compiler.  That way we always have a working set of
    1.10 -   atomic operations built into the library.
    1.11 -*/
    1.12 -#undef SDL_AtomicCAS
    1.13 -#undef SDL_AtomicCASPtr
    1.14 +#if defined(_MSC_VER) && (_MSC_VER >= 1500)
    1.15 +#include <intrin.h>
    1.16 +#define HAVE_MSC_ATOMICS 1
    1.17 +#endif
    1.18 +
    1.19 +#if defined(__MACOSX__)  /* !!! FIXME: should we favor gcc atomics? */
    1.20 +#include <libkern/OSAtomic.h>
    1.21 +#endif
    1.22  
    1.23  /*
    1.24    If any of the operations are not provided then we must emulate some
    1.25 @@ -53,6 +54,11 @@
    1.26    Contributed by Bob Pendleton, bob@pendleton.com
    1.27  */
    1.28  
    1.29 +#if !defined(HAVE_MSC_ATOMICS) && !defined(HAVE_GCC_ATOMICS) && !defined(__MACOSX__)
    1.30 +#define EMULATE_CAS 1
    1.31 +#endif
    1.32 +
    1.33 +#if EMULATE_CAS
    1.34  static SDL_SpinLock locks[32];
    1.35  
    1.36  static SDL_INLINE void
    1.37 @@ -70,10 +76,19 @@
    1.38  
    1.39      SDL_AtomicUnlock(&locks[index]);
    1.40  }
    1.41 +#endif
    1.42  
    1.43 -DECLSPEC SDL_bool SDLCALL
    1.44 +
    1.45 +SDL_bool
    1.46  SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval)
    1.47  {
    1.48 +#ifdef HAVE_MSC_ATOMICS
    1.49 +    return (_InterlockedCompareExchange((long*)&a->value, (long)newval, (long)oldval) == (long)oldval);
    1.50 +#elif defined(__MACOSX__)  /* !!! FIXME: should we favor gcc atomics? */
    1.51 +    return (SDL_bool) OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value);
    1.52 +#elif defined(HAVE_GCC_ATOMICS)
    1.53 +    return (SDL_bool) __sync_bool_compare_and_swap(&a->value, oldval, newval);
    1.54 +#elif EMULATE_CAS
    1.55      SDL_bool retval = SDL_FALSE;
    1.56  
    1.57      enterLock(a);
    1.58 @@ -84,11 +99,25 @@
    1.59      leaveLock(a);
    1.60  
    1.61      return retval;
    1.62 +#else
    1.63 +    #error Please define your platform.
    1.64 +#endif
    1.65  }
    1.66  
    1.67 -DECLSPEC SDL_bool SDLCALL
    1.68 +SDL_bool
    1.69  SDL_AtomicCASPtr(void **a, void *oldval, void *newval)
    1.70  {
    1.71 +#if defined(HAVE_MSC_ATOMICS) && (_M_IX86)
    1.72 +    return (_InterlockedCompareExchange((long*)a, (long)newval, (long)oldval) == (long)oldval);
    1.73 +#elif defined(HAVE_MSC_ATOMICS) && (!_M_IX86)
    1.74 +    return (_InterlockedCompareExchangePointer(a, newval, oldval) == oldval);
    1.75 +#elif defined(__MACOSX__) && defined(__LP64__)   /* !!! FIXME: should we favor gcc atomics? */
    1.76 +    return (SDL_bool) OSAtomicCompareAndSwap64Barrier((int64_t)oldval, (int64_t)newval, (int64_t*) a);
    1.77 +#elif defined(__MACOSX__) && !defined(__LP64__)  /* !!! FIXME: should we favor gcc atomics? */
    1.78 +    return (SDL_bool) OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t*) a);
    1.79 +#elif defined(HAVE_GCC_ATOMICS)
    1.80 +    return __sync_bool_compare_and_swap(a, oldval, newval);
    1.81 +#elif EMULATE_CAS
    1.82      SDL_bool retval = SDL_FALSE;
    1.83  
    1.84      enterLock(a);
    1.85 @@ -99,10 +128,80 @@
    1.86      leaveLock(a);
    1.87  
    1.88      return retval;
    1.89 +#else
    1.90 +    #error Please define your platform.
    1.91 +#endif
    1.92  }
    1.93  
    1.94 -#if defined(__GNUC__) && defined(__arm__) && \
    1.95 -   (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__))
    1.96 +int
    1.97 +SDL_AtomicSet(SDL_atomic_t *a, int v)
    1.98 +{
    1.99 +#ifdef HAVE_MSC_ATOMICS
   1.100 +    return _InterlockedExchange((long*)&a->value, v);
   1.101 +#elif defined(HAVE_GCC_ATOMICS)
   1.102 +    return __sync_lock_test_and_set(&a->value, v);
   1.103 +#else
   1.104 +    int value;
   1.105 +    do {
   1.106 +        value = a->value;
   1.107 +    } while (!SDL_AtomicCAS(a, value, v));
   1.108 +    return value;
   1.109 +#endif
   1.110 +}
   1.111 +
   1.112 +void*
   1.113 +SDL_AtomicSetPtr(void **a, void *v)
   1.114 +{
   1.115 +#ifdef HAVE_MSC_ATOMICS
   1.116 +    return _InterlockedExchangePointer(a, v);
   1.117 +#elif defined(HAVE_GCC_ATOMICS)
   1.118 +    return __sync_lock_test_and_set(a, v);
   1.119 +#else
   1.120 +    void *value;
   1.121 +    do {
   1.122 +        value = *a;
   1.123 +    } while (!SDL_AtomicCASPtr(a, value, v));
   1.124 +    return value;
   1.125 +#endif
   1.126 +}
   1.127 +
   1.128 +int
   1.129 +SDL_AtomicAdd(SDL_atomic_t *a, int v)
   1.130 +{
   1.131 +#ifdef HAVE_MSC_ATOMICS
   1.132 +    return _InterlockedExchangeAdd((long*)&a->value, v);
   1.133 +#elif defined(HAVE_GCC_ATOMICS)
   1.134 +    return __sync_fetch_and_add(&a->value, v);
   1.135 +#else
   1.136 +    int value;
   1.137 +    do {
   1.138 +        value = a->value;
   1.139 +    } while (!SDL_AtomicCAS(a, value, (value + v)));
   1.140 +    return value;
   1.141 +#endif
   1.142 +}
   1.143 +
   1.144 +int
   1.145 +SDL_AtomicGet(SDL_atomic_t *a)
   1.146 +{
   1.147 +    int value;
   1.148 +    do {
   1.149 +        value = a->value;
   1.150 +    } while (!SDL_AtomicCAS(a, value, value));
   1.151 +    return value;
   1.152 +}
   1.153 +
   1.154 +void *
   1.155 +SDL_AtomicGetPtr(void **a)
   1.156 +{
   1.157 +    void *value;
   1.158 +    do {
   1.159 +        value = *a;
   1.160 +    } while (!SDL_AtomicCASPtr(a, value, value));
   1.161 +    return value;
   1.162 +}
   1.163 +
   1.164 +#ifdef __thumb__
   1.165  __asm__(
   1.166  "   .align 2\n"
   1.167  "   .globl _SDL_MemoryBarrierRelease\n"
   1.168 @@ -113,6 +212,6 @@
   1.169  "   mcr p15, 0, r0, c7, c10, 5\n"
   1.170  "   bx lr\n"
   1.171  );
   1.172 -#endif /* __GNUC__ && __arm__ && ARMV6 */
   1.173 +#endif
   1.174  
   1.175  /* vi: set ts=4 sw=4 expandtab: */