From c5812c5511fe8f1569c8a1b569c6a0b19be47b32 Mon Sep 17 00:00:00 2001 From: Shawn Walker Date: Sat, 5 Jul 2014 16:11:23 -0700 Subject: [PATCH] 2620 solaris port missing atomics if not using gcc --- include/SDL_atomic.h | 10 +++++++++- include/SDL_platform.h | 2 +- src/atomic/SDL_atomic.c | 27 ++++++++++++++++++++++++++- src/atomic/SDL_spinlock.c | 16 ++++++++++++++++ test/Makefile.in | 1 + 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/include/SDL_atomic.h b/include/SDL_atomic.h index bb3a9b657dd83..6f308ce8470b8 100644 --- a/include/SDL_atomic.h +++ b/include/SDL_atomic.h @@ -122,7 +122,8 @@ extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock); void _ReadWriteBarrier(void); #pragma intrinsic(_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") #else #define SDL_CompilerBarrier() \ @@ -169,10 +170,17 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquire(); #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory") #endif /* __GNUC__ && __arm__ */ #else +#if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120)) +/* This is correct for all CPUs on Solaris when using Solaris Studio 12.1+. */ +#include +#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. */ #define SDL_MemoryBarrierRelease() SDL_CompilerBarrier() #define SDL_MemoryBarrierAcquire() SDL_CompilerBarrier() #endif +#endif /** * \brief A type representing an atomic integer value. It is a struct diff --git a/include/SDL_platform.h b/include/SDL_platform.h index e6b3e9d916263..adafde5201133 100644 --- a/include/SDL_platform.h +++ b/include/SDL_platform.h @@ -109,7 +109,7 @@ #undef __RISCOS__ #define __RISCOS__ 1 #endif -#if defined(__SVR4) +#if defined(__sun) && defined(__SVR4) #undef __SOLARIS__ #define __SOLARIS__ 1 #endif diff --git a/src/atomic/SDL_atomic.c b/src/atomic/SDL_atomic.c index be3f4002bb91b..c6029c2ca7fd2 100644 --- a/src/atomic/SDL_atomic.c +++ b/src/atomic/SDL_atomic.c @@ -31,6 +31,10 @@ #include #endif +#if !defined(HAVE_GCC_ATOMICS) && defined(__SOLARIS__) +#include +#endif + /* 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 @@ -54,7 +58,7 @@ Contributed by Bob Pendleton, bob@pendleton.com */ -#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 #endif @@ -88,6 +92,10 @@ SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval) return (SDL_bool) OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value); #elif defined(HAVE_GCC_ATOMICS) 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 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); #elif defined(HAVE_GCC_ATOMICS) 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 SDL_bool retval = SDL_FALSE; @@ -140,6 +150,10 @@ SDL_AtomicSet(SDL_atomic_t *a, int v) return _InterlockedExchange((long*)&a->value, v); #elif defined(HAVE_GCC_ATOMICS) 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 int value; do { @@ -158,6 +172,8 @@ SDL_AtomicSetPtr(void **a, void *v) return _InterlockedExchangePointer(a, v); #elif defined(HAVE_GCC_ATOMICS) return __sync_lock_test_and_set(a, v); +#elif defined(__SOLARIS__) + return atomic_swap_ptr(a, v); #else void *value; do { @@ -174,6 +190,15 @@ SDL_AtomicAdd(SDL_atomic_t *a, int v) return _InterlockedExchangeAdd((long*)&a->value, v); #elif defined(HAVE_GCC_ATOMICS) 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 int value; do { diff --git a/src/atomic/SDL_spinlock.c b/src/atomic/SDL_spinlock.c index 2d8446dc58272..11aff019bf602 100644 --- a/src/atomic/SDL_spinlock.c +++ b/src/atomic/SDL_spinlock.c @@ -28,6 +28,9 @@ #include "SDL_mutex.h" #include "SDL_timer.h" +#if !defined(HAVE_GCC_ATOMICS) && defined(__SOLARIS__) +#include +#endif /* This function is where all the magic happens... */ SDL_bool @@ -90,6 +93,14 @@ SDL_AtomicTryLock(SDL_SpinLock *lock) /* pthread instructions */ 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 #error Please implement for your platform. return SDL_FALSE; @@ -118,6 +129,11 @@ SDL_AtomicUnlock(SDL_SpinLock *lock) #elif HAVE_PTHREAD_SPINLOCK pthread_spin_unlock(lock); +#elif defined(__SOLARIS__) + /* Used for Solaris when not using gcc. */ + *lock = 0; + membar_producer(); + #else *lock = 0; #endif diff --git a/test/Makefile.in b/test/Makefile.in index 227bd0eb04ae6..bc988556d13ee 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -10,6 +10,7 @@ LIBS = @LIBS@ TARGETS = \ checkkeys$(EXE) \ loopwave$(EXE) \ + testatomic$(EXE) \ testaudioinfo$(EXE) \ testautomation$(EXE) \ testdraw2$(EXE) \