Browse Source

2620 solaris port missing atomics if not using gcc

Shawn Walker 11 years ago
parent
commit
c5812c5511
5 changed files with 53 additions and 3 deletions
  1. 9 1
      include/SDL_atomic.h
  2. 1 1
      include/SDL_platform.h
  3. 26 1
      src/atomic/SDL_atomic.c
  4. 16 0
      src/atomic/SDL_spinlock.c
  5. 1 0
      test/Makefile.in

+ 9 - 1
include/SDL_atomic.h

@@ -122,7 +122,8 @@ extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock);
 void _ReadWriteBarrier(void);
 void _ReadWriteBarrier(void);
 #pragma intrinsic(_ReadWriteBarrier)
 #pragma intrinsic(_ReadWriteBarrier)
 #define SDL_CompilerBarrier()   _ReadWriteBarrier()
 #define SDL_CompilerBarrier()   _ReadWriteBarrier()
-#elif defined(__GNUC__)
+#elif defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
+/* This is correct for all CPUs when using GCC or Solaris Studio 12.1+. */
 #define SDL_CompilerBarrier()   __asm__ __volatile__ ("" : : : "memory")
 #define SDL_CompilerBarrier()   __asm__ __volatile__ ("" : : : "memory")
 #else
 #else
 #define SDL_CompilerBarrier()   \
 #define SDL_CompilerBarrier()   \
@@ -169,10 +170,17 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquire();
 #define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("" : : : "memory")
 #define SDL_MemoryBarrierAcquire()   __asm__ __volatile__ ("" : : : "memory")
 #endif /* __GNUC__ && __arm__ */
 #endif /* __GNUC__ && __arm__ */
 #else
 #else
+#if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
+/* This is correct for all CPUs on Solaris when using Solaris Studio 12.1+. */
+#include <mbarrier.h>
+#define SDL_MemoryBarrierRelease()  __machine_rel_barrier()
+#define SDL_MemoryBarrierAcquire()  __machine_acq_barrier()
+#else
 /* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */
 /* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */
 #define SDL_MemoryBarrierRelease()  SDL_CompilerBarrier()
 #define SDL_MemoryBarrierRelease()  SDL_CompilerBarrier()
 #define SDL_MemoryBarrierAcquire()  SDL_CompilerBarrier()
 #define SDL_MemoryBarrierAcquire()  SDL_CompilerBarrier()
 #endif
 #endif
+#endif
 
 
 /**
 /**
  * \brief A type representing an atomic integer value.  It is a struct
  * \brief A type representing an atomic integer value.  It is a struct

+ 1 - 1
include/SDL_platform.h

@@ -109,7 +109,7 @@
 #undef __RISCOS__
 #undef __RISCOS__
 #define __RISCOS__  1
 #define __RISCOS__  1
 #endif
 #endif
-#if defined(__SVR4)
+#if defined(__sun) && defined(__SVR4)
 #undef __SOLARIS__
 #undef __SOLARIS__
 #define __SOLARIS__ 1
 #define __SOLARIS__ 1
 #endif
 #endif

+ 26 - 1
src/atomic/SDL_atomic.c

@@ -31,6 +31,10 @@
 #include <libkern/OSAtomic.h>
 #include <libkern/OSAtomic.h>
 #endif
 #endif
 
 
+#if !defined(HAVE_GCC_ATOMICS) && defined(__SOLARIS__)
+#include <atomic.h>
+#endif
+
 /*
 /*
   If any of the operations are not provided then we must emulate some
   If any of the operations are not provided then we must emulate some
   of them. That means we need a nice implementation of spin locks
   of them. That means we need a nice implementation of spin locks
@@ -54,7 +58,7 @@
   Contributed by Bob Pendleton, [email protected]
   Contributed by Bob Pendleton, [email protected]
 */
 */
 
 
-#if !defined(HAVE_MSC_ATOMICS) && !defined(HAVE_GCC_ATOMICS) && !defined(__MACOSX__)
+#if !defined(HAVE_MSC_ATOMICS) && !defined(HAVE_GCC_ATOMICS) && !defined(__MACOSX__) && !defined(__SOLARIS__)
 #define EMULATE_CAS 1
 #define EMULATE_CAS 1
 #endif
 #endif
 
 
@@ -88,6 +92,10 @@ SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval)
     return (SDL_bool) OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value);
     return (SDL_bool) OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value);
 #elif defined(HAVE_GCC_ATOMICS)
 #elif defined(HAVE_GCC_ATOMICS)
     return (SDL_bool) __sync_bool_compare_and_swap(&a->value, oldval, newval);
     return (SDL_bool) __sync_bool_compare_and_swap(&a->value, oldval, newval);
+#elif defined(__SOLARIS__) && defined(_LP64)
+    return (SDL_bool) ((int) atomic_cas_64((volatile uint64_t*)&a->value, (uint64_t)oldval, (uint64_t)newval) == oldval);
+#elif defined(__SOLARIS__) && !defined(_LP64)
+    return (SDL_bool) ((int) atomic_cas_32((volatile uint32_t*)&a->value, (uint32_t)oldval, (uint32_t)newval) == oldval);
 #elif EMULATE_CAS
 #elif EMULATE_CAS
     SDL_bool retval = SDL_FALSE;
     SDL_bool retval = SDL_FALSE;
 
 
@@ -117,6 +125,8 @@ SDL_AtomicCASPtr(void **a, void *oldval, void *newval)
     return (SDL_bool) OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t*) a);
     return (SDL_bool) OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t*) a);
 #elif defined(HAVE_GCC_ATOMICS)
 #elif defined(HAVE_GCC_ATOMICS)
     return __sync_bool_compare_and_swap(a, oldval, newval);
     return __sync_bool_compare_and_swap(a, oldval, newval);
+#elif defined(__SOLARIS__)
+    return (SDL_bool) (atomic_cas_ptr(a, oldval, newval) == oldval);
 #elif EMULATE_CAS
 #elif EMULATE_CAS
     SDL_bool retval = SDL_FALSE;
     SDL_bool retval = SDL_FALSE;
 
 
@@ -140,6 +150,10 @@ SDL_AtomicSet(SDL_atomic_t *a, int v)
     return _InterlockedExchange((long*)&a->value, v);
     return _InterlockedExchange((long*)&a->value, v);
 #elif defined(HAVE_GCC_ATOMICS)
 #elif defined(HAVE_GCC_ATOMICS)
     return __sync_lock_test_and_set(&a->value, v);
     return __sync_lock_test_and_set(&a->value, v);
+#elif defined(__SOLARIS__) && defined(_LP64)
+    return (int) atomic_swap_64((volatile uint64_t*)&a->value, (uint64_t)v);
+#elif defined(__SOLARIS__) && !defined(_LP64)
+    return (int) atomic_swap_32((volatile uint32_t*)&a->value, (uint32_t)v);
 #else
 #else
     int value;
     int value;
     do {
     do {
@@ -158,6 +172,8 @@ SDL_AtomicSetPtr(void **a, void *v)
     return _InterlockedExchangePointer(a, v);
     return _InterlockedExchangePointer(a, v);
 #elif defined(HAVE_GCC_ATOMICS)
 #elif defined(HAVE_GCC_ATOMICS)
     return __sync_lock_test_and_set(a, v);
     return __sync_lock_test_and_set(a, v);
+#elif defined(__SOLARIS__)
+    return atomic_swap_ptr(a, v);
 #else
 #else
     void *value;
     void *value;
     do {
     do {
@@ -174,6 +190,15 @@ SDL_AtomicAdd(SDL_atomic_t *a, int v)
     return _InterlockedExchangeAdd((long*)&a->value, v);
     return _InterlockedExchangeAdd((long*)&a->value, v);
 #elif defined(HAVE_GCC_ATOMICS)
 #elif defined(HAVE_GCC_ATOMICS)
     return __sync_fetch_and_add(&a->value, v);
     return __sync_fetch_and_add(&a->value, v);
+#elif defined(__SOLARIS__)
+    int pv = a->value;
+    membar_consumer();
+#if defined(_LP64)
+    atomic_add_64((volatile uint64_t*)&a->value, v);
+#elif !defined(_LP64)
+    atomic_add_32((volatile uint32_t*)&a->value, v);
+#endif
+    return pv;
 #else
 #else
     int value;
     int value;
     do {
     do {

+ 16 - 0
src/atomic/SDL_spinlock.c

@@ -28,6 +28,9 @@
 #include "SDL_mutex.h"
 #include "SDL_mutex.h"
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 
 
+#if !defined(HAVE_GCC_ATOMICS) && defined(__SOLARIS__)
+#include <atomic.h>
+#endif
 
 
 /* This function is where all the magic happens... */
 /* This function is where all the magic happens... */
 SDL_bool
 SDL_bool
@@ -90,6 +93,14 @@ SDL_AtomicTryLock(SDL_SpinLock *lock)
     /* pthread instructions */
     /* pthread instructions */
     return (pthread_spin_trylock(lock) == 0);
     return (pthread_spin_trylock(lock) == 0);
 
 
+#elif defined(__SOLARIS__) && defined(_LP64)
+    /* Used for Solaris with non-gcc compilers. */
+    return (SDL_bool) ((int) atomic_cas_64((volatile uint64_t*)lock, 0, 1) == 0);
+
+#elif defined(__SOLARIS__) && !defined(_LP64)
+    /* Used for Solaris with non-gcc compilers. */
+    return (SDL_bool) ((int) atomic_cas_32((volatile uint32_t*)lock, 0, 1) == 0);
+
 #else
 #else
 #error Please implement for your platform.
 #error Please implement for your platform.
     return SDL_FALSE;
     return SDL_FALSE;
@@ -118,6 +129,11 @@ SDL_AtomicUnlock(SDL_SpinLock *lock)
 #elif HAVE_PTHREAD_SPINLOCK
 #elif HAVE_PTHREAD_SPINLOCK
     pthread_spin_unlock(lock);
     pthread_spin_unlock(lock);
 
 
+#elif defined(__SOLARIS__)
+    /* Used for Solaris when not using gcc. */
+    *lock = 0;
+    membar_producer();
+
 #else
 #else
     *lock = 0;
     *lock = 0;
 #endif
 #endif

+ 1 - 0
test/Makefile.in

@@ -10,6 +10,7 @@ LIBS	= @LIBS@
 TARGETS = \
 TARGETS = \
 	checkkeys$(EXE) \
 	checkkeys$(EXE) \
 	loopwave$(EXE) \
 	loopwave$(EXE) \
+	testatomic$(EXE) \
 	testaudioinfo$(EXE) \
 	testaudioinfo$(EXE) \
 	testautomation$(EXE) \
 	testautomation$(EXE) \
 	testdraw2$(EXE) \
 	testdraw2$(EXE) \