diff --git a/configure.in b/configure.in index fdcbfa92b..c03f2cf04 100644 --- a/configure.in +++ b/configure.in @@ -217,6 +217,12 @@ SOURCES="$SOURCES $srcdir/src/video/*.c" dnl Enable/disable various subsystems of the SDL library +AC_ARG_ENABLE(atomic, +AC_HELP_STRING([--enable-atomic], [Enable the atomic operations subsystem [[default=yes]]]), + , enable_atomic=yes) +if test x$enable_atomic != xyes; then + AC_DEFINE(SDL_ATOMIC_DISABLED) +fi AC_ARG_ENABLE(audio, AC_HELP_STRING([--enable-audio], [Enable the audio subsystem [[default=yes]]]), , enable_audio=yes) @@ -2433,6 +2439,16 @@ case "$host" in ;; esac fi + # Set up files for the atomic operations library + if test x$enable_atomic = xyes; then + case $ARCH in + linux) + AC_DEFINE(SDL_ATOMIC_LINUX) + SOURCES="$SOURCES $srcdir/src/atomic/linux/*.c" + have_atomic=yes + ;; + esac + fi # Set up files for the joystick library if test x$enable_joystick = xyes; then case $ARCH in diff --git a/include/SDL_atomic.h b/include/SDL_atomic.h index ce98c82ab..3b044be79 100644 --- a/include/SDL_atomic.h +++ b/include/SDL_atomic.h @@ -23,7 +23,7 @@ /** * \file SDL_atomic.h * - * Atomic int and pointer magic + * Atomic operations. */ #ifndef _SDL_atomic_h_ @@ -42,628 +42,232 @@ extern "C" { /* *INDENT-ON* */ #endif -/* indent is really bad at handling assembly */ /* *INDENT-OFF* */ +/** + * \def SDL_AtomicBusyWait32 (ptr) + * + * \brief Implements a simple busy wait for use with + * SDL_AtomicTestThenSet and SDL_AtomicClear. + * + * Note: This can be an infinite loop. + * + */ +#define SDL_AtomicBusyWait32(ptr) \ + { \ + while (!SDL_AtomicTestThenSet32(ptr) \ + { \ + }; \ + }; -#if defined(__GNUC__) && (defined(i386) || defined(__i386__) || defined(__x86_64__)) -static __inline__ void -SDL_atomic_int_add(volatile int* atomic, int value) -{ - __asm__ __volatile__("lock;" - "addl %1, %0" - : "=m" (*atomic) - : "ir" (value), - "m" (*atomic)); -} +/** + * \def SDL_AtomicWait32(ptr) + * + * \brief A safer way to wait for a test-then-set lock to be cleared. + * + * This assumes that the SDL_Sleep(0) call acts as a thread_yeild + * operation. + * + */ +#define SDL_AtomicWait32(ptr) \ + { \ + while (!SDL_AtomicTestThenSet32(ptr) \ + { \ + SDL_Sleep(0); \ + }; \ + }; -static __inline__ int -SDL_atomic_int_xchg_add(volatile int* atomic, int value) -{ - int rv; - __asm__ __volatile__("lock;" - "xaddl %0, %1" - : "=r" (rv), - "=m" (*atomic) - : "0" (value), - "m" (*atomic)); - return rv; -} +/** + * \def SDL_AtomicBusyWait64(ptr) + * + * \brief 64 bit version of busy wait + * + * \sa SDL_AtomicBusyWait32 + */ +#define SDL_AtomicBusyWait64(ptr) \ + { \ + while (!SDL_AtomicTestThenSet64(ptr) \ + { \ + }; \ + }; -static __inline__ SDL_bool -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) -{ - int rv; - __asm__ __volatile__("lock;" - "cmpxchgl %2, %1" - : "=a" (rv), - "=m" (*atomic) - : "r" (newvalue), - "m" (*atomic), - "0" (oldvalue)); - return (SDL_bool)(rv == oldvalue); -} - -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - void* rv; - __asm__ __volatile__("lock;" -# if defined(__x86_64__) - "cmpxchgq %q2, %1" -# else - "cmpxchgl %2, %1" -# endif - : "=a" (rv), - "=m" (*atomic) - : "r" (newvalue), - "m" (*atomic), - "0" (oldvalue)); - return (SDL_bool)(rv == oldvalue); -} -#elif defined(__GNUC__) && defined(__alpha__) -# define ATOMIC_MEMORY_BARRIER (__asm__ __volatile__ ("mb" : : : "memory")) -# define ATOMIC_INT_CMP_XCHG(atomic,value) \ - ({ \ - int rv,prev; \ - __asm__ __volatile__(" mb\n" \ - "1: ldl_l %0,%2\n" \ - " cmpeq %0,%3,%1\n" \ - " beq %1,2f\n" \ - " mov %4,%1\n" \ - " stl_c %1,%2\n" \ - " beq %1,1b\n" \ - " mb\n" \ - "2:" \ - : "=&r" (prev), \ - "=&r" (rv) \ - : "m" (*(atomic)), \ - "Ir" (oldvalue), \ - "Ir" (newvalue) \ - : "memory"); \ - (rv != 0); \ - }) - -# if (SIZEOF_VOIDP == 4) -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - int rv; - void* prev; - __asm__ __volatile__(" mb\n" - "1: ldl_l %0,%2\n" - " cmpeq %0,%3,%1\n" - " beq $1,2f\n" - " mov %4,%1\n" - " stl_c %1,%2\n" - " beq %1,1b\n" - " mb\n" - "2:" - : "=&r" (prev), - "=&r" (rv) - : "m" (*atomic), - "Ir" (oldvalue), - "Ir" (newvalue) - : "memory"); - return (SDL_bool)(rv != 0); -} -# elif (SIZEOF_VOIDP == 8) -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - int rv; - void* prev; - __asm__ __volatile__(" mb\n" - "1: ldq_l %0,%2\n" - " cmpeq %0,%3,%1\n" - " beq %1,2f\n" - " mov %4,%1\n" - " stq_c %1,%2\n" - " beq %1,1b\n" - " mb\n" - "2:" - : "=&r" (prev), - "=&r" (rv) - : "m" (*atomic), - "Ir" (oldvalue), - "Ir" (newvalue) - : "memory"); - return (SDL_bool)(rv != 0); -} -# else -# error "Your system has an unsupported pointer size" -# endif /* SIZEOF_VOIDP */ -#elif defined(__GNUC__) && defined(__sparc__) -# define ATOMIC_MEMORY_BARRIER \ - (__asm__ __volatile__("membar #LoadLoad | #LoadStore" \ - " | #StoreLoad | #StoreStore" : : : "memory")) -# define ATOMIC_INT_CMP_XCHG(atomic,oldvalue,newvalue) \ - ({ \ - int rv; \ - __asm__ __volatile__("cas [%4], %2, %0" \ - : "=r" (rv), "=m" (*(atomic)) \ - : "r" (oldvalue), "m" (*(atomic)), \ - "r" (atomic), "0" (newvalue)); \ - rv == oldvalue; \ - }) - -# if (SIZEOF_VOIDP == 4) -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - void* rv; - __asm__ __volatile__("cas [%4], %2, %0" - : "=r" (rv), - "=m" (*atomic) - : "r" (oldvalue), - "m" (*atomic), - "r" (atomic), - "0" (newvalue)); - return (SDL_bool)(rv == oldvalue); -} -# elif (SIZEOF_VOIDP == 8) -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - void* rv; - void** a = atomic; - __asm__ __volatile__("casx [%4], %2, %0" - : "=r" (rv), - "=m" (*a) - : "r" (oldvalue), - "m" (*a), - "r" (a), - "0" (newvalue)); - return (SDL_bool)(rv == oldvalue); -} -# else -# error "Your system has an unsupported pointer size" -# endif /* SIZEOF_VOIDP */ -#elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC)) -# define ATOMIC_MEMORY_BARRIER \ - (__asm__ __volatile__ ("sync" : : : "memory")) -static __inline__ void -SDL_atomic_int_add(volatile int* atomic, int value) -{ - int rv,tmp; - __asm__ __volatile__("1: lwarx %0, 0, %3\n" - " add %1, %0, %4\n" - " stwcx. %1, 0, %3\n" - " bne- 1b" - : "=&b" (rv), - "=&r" (tmp), - "=m" (*atomic) - : "b" (atomic), - "r" (value), - "m" (*atomic) - : "cr0", - "memory"); -} - -static __inline__ int -SDL_atomic_int_xchg_add(volatile int* atomic, int value) -{ - int rv,tmp; - __asm__ __volatile__("1: lwarx %0, 0, %3\n" - " add %1, %0, %4\n" - " stwcx. %1, 0, %3\n" - " bne- 1b" - : "=&b" (rv), - "=&r" (tmp), - "=m" (*atomic) - : "b" (atomic), - "r" (value), - "m" (*atomic) - : "cr0", - "memory"); - return rv; -} - -# if (SIZEOF_VOIDP == 4) -static __inline__ SDL_bool -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) -{ - int rv; - __asm__ __volatile__(" sync\n" - "1: lwarx %0, 0, %1\n" - " subf. %0, %2, %0\n" - " bne 2f\n" - " stwcx. %3, 0, %1\n" - " bne- 1b\n" - "2: isync" - : "=&r" (rv) - : "b" (atomic), - "r" (oldvalue), - "r" - : "cr0", - "memory"); - return (SDL_bool)(rv == 0); -} - -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - void* rv; - __asm__ __volatile__("sync\n" - "1: lwarx %0, 0, %1\n" - " subf. %0, %2, %0\n" - " bne 2f\n" - " stwcx. %3, 0, %1\n" - " bne- 1b\n" - "2: isync" - : "=&r" (rv) - : "b" (atomic), - "r" (oldvalue), - "r" (newvalue) - : "cr0", - "memory"); - return (SDL_bool)(rv == 0); -} -# elif (SIZEOF_VOIDP == 8) -static __inline__ SDL_bool -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) -{ - int rv; - __asm__ __volatile__(" sync\n" - "1: lwarx %0, 0, %1\n" - " extsw %0, %0\n" - " subf. %0, %2, %0\n" - " bne 2f\n" - " stwcx. %3, 0, %1\n" - " bne- 1b\n" - "2: isync" - : "=&r" (rv) - : "b" (atomic), - "r" (oldvalue), - "r" - : "cr0", - "memory"); - return (SDL_bool)(rv == 0); -} - -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - void* rv; - __asm__ __volatile__("sync\n" - "1: ldarx %0, 0, %1\n" - " subf. %0, %2, %0\n" - " bne 2f\n" - " stdcx. %3, 0, %1\n" - " bne- 1b\n" - "2: isync" - : "=&r" (rv) - : "b" (atomic), - "r" (oldvalue), - "r" (newvalue) - : "cr0", - "memory"); - return (SDL_bool)(rv == 0); -} -# else -# error "Your system has an unsupported pointer size" -# endif /* SIZEOF_VOIDP */ -#elif defined(__GNUC__) && (defined(__IA64__) || defined(__ia64__)) -# define ATOMIC_MEMORY_BARRIER (__sync_synchronize()) -# define SDL_atomic_int_xchg_add(atomic, value) \ - (__sync_fetch_and_add((atomic),(value))) -# define SDL_atomic_int_add(atomic, value) \ - ((void)__sync_fetch_and_add((atomic),(value))) -# define SDL_atomic_int_cmp_xchg(atomic,oldvalue,newvalue) \ - (__sync_bool_compare_and_swap((atomic),(oldvalue),(newvalue))) -# define SDL_atomic_ptr_cmp_xchg(atomic,oldvalue,newvalue) \ - (__sync_bool_compare_and_swap((long*)(atomic),(long)(oldvalue),(long)(newvalue))) -#elif defined(__GNUC__) && defined(__LINUX__) && (defined(__mips__) || defined(__MIPS__)) -static __inline__ int -SDL_atomic_int_xchg_add(volatile int* atomic, int value) -{ - int rv,tmp; - __asm__ __volatile__("1: \n" - ".set push \n" - ".set mips2 \n" - "ll %0,%3 \n" - "addu %1,%4,%0 \n" - "sc %1,%2 \n" - ".set pop \n" - "beqz %1,1b \n" - : "=&r" (rv), - "=&r" (tmp), - "=m" (*atomic) - : "m" (*atomic), - "r" (value) - : "memory"); - return rv; -} - -static __inline__ void -SDL_atomic_int_add(volatile int* atomic, int value) -{ - int rv; - __asm__ __volatile__("1: \n" - ".set push \n" - ".set mips2 \n" - "ll %0,%2 \n" - "addu %0,%3,%0 \n" - "sc %0,%1 \n" - ".set pop \n" - "beqz %0,1b \n" - : "=&r" (rv), - "=m" (*atomic) - : "m" (*atomic), - "r" (value) - : "memory"); -} - -static __inline__ SDL_bool -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) -{ - int rv; - __asm__ __volatile__(" .set push \n" - " .set noat \n" - " .set mips3 \n" - "1: ll %0, %2 \n" - " bne %0, %z3, 2f \n" - " .set mips0 \n" - " move $1, %z4 \n" - " .set mips3 \n" - " sc $1, %1 \n" - " beqz $1, 1b \n" - " sync \n" - "2: \n" - " .set pop \n" - : "=&r" (rv), - "=R" (*atomic) - : "R" (*atomic), - "Jr" (oldvalue), - "Jr" (newvalue) - : "memory"); - return (SDL_bool)rv; -} - -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - int rv; - __asm__ __volatile__(" .set push \n" - " .set noat \n" - " .set mips3 \n" -# if defined(__mips64) - "1: lld %0, %2 \n" -# else - "1: ll %0, %2 \n" -# endif - " bne %0, %z3, 2f \n" - " move $1, %z4 \n" -# if defined(__mips64) - " sc $1, %1 \n" -# else - " scd $1, %1 \n" -# endif - " beqz $1, 1b \n" - " sync \n" - "2: \n" - " .set pop \n" - : "=&r" (rv), - "=R" (*atomic) - : "R" (*atomic), - "Jr" (oldvalue), - "Jr" (newvalue) - : "memory"); - return (SDL_bool)rv; -} -#elif defined(__GNUC__) && defined(__m68k__) -static __inline__ int -SDL_atomic_int_xchg_add(volatile int* atomic, int value) -{ - int rv = *atomic; - int tmp; - __asm__ __volatile__("1: move%.l %0,%1 \n" - " add%.l %2,%1 \n" - " cas%.l %0,%1,%3 \n" - " jbne 1b \n" - : "=d" (rv), - "=&d" (tmp) - : "d" (value), - "m" (*atomic), - "0" (rv) - : "memory"); - return (SDL_bool)rv; -} - -static __inline__ void -SDL_atomic_int_add(volatile int* atomic, int value) -{ - __asm__ __volatile__("add%.l %0,%1" - : - : "id" (value), - "m" (*atomic) - : "memory"); -} - -static __inline__ SDL_bool -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) -{ - char rv; - int readvalue; - __asm__ __volatile__("cas%.l %2,%3,%1\n" - "seq %0" - : "=dm" (rv), - "=m" (*atomic), - "=d" (readvalue) - : "d" (newvalue), - "m" (*atomic), - "2" (oldvalue)); - return (SDL_bool)rv; -} - -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - char rv; - int readvalue; - __asm__ __volatile__("cas%.l %2,%3,%1\n" - "seq %0" - : "=dm" (rv), - "=m" (*atomic), - "=d" (readvalue) - : "d" (newvalue), - "m" (*atomic), - "2" (oldvalue)); - return (SDL_bool)rv; -} -#elif defined(__GNUC__) && defined(__s390__) -# define ATOMIC_INT_CMP_XCHG(atomic,oldvalue,newvalue) \ - ({ \ - int rv = oldvalue; \ - __asm__ __volatile__("cs %0, %2, %1" \ - : "+d" (rv), \ - "=Q" (*(atomic)) \ - : "d" (newvalue), \ - "m" (*(atomic)) \ - : "cc"); \ - rv == oldvalue; \ - }) -# if (SIZEOF_VOIDP == 4) -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - void* rv = oldvalue; - __asm__ __volatile__("cs %0, %2, %1" - : "+d" (rv), - "=Q" (*atomic) - : "d" (newvalue), - "m" (*atomic) - : "cc"); - return (SDL_bool)(rv == oldvalue); -} -# elif (SIZEOF_VOIDP == 8) -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - void* rv = oldvalue; - void** a = atomic; - __asm__ __volatile__("csg %0, %2, %1" - : "+d" (rv), - "=Q" (*a) - : "d" ((long)(newvalue)), - "m" (*a) - : "cc"); - return (SDL_bool)(rv == oldvalue); -} -# else -# error "Your system has an unsupported pointer size" -# endif /* SIZEOF_VOIDP */ -#elif defined(__WIN32__) -# include -static __inline__ int -SDL_atomic_int_xchg_add(volatile int* atomic, int value) -{ - return InterlockedExchangeAdd(atomic, value); -} - -static __inline__ void -SDL_atomic_int_add(volatile int* atomic, int value) -{ - InterlockedExchangeAdd(atomic, value); -} - -# if (WINVER > 0X0400) -static __inline__ SDL_bool -SDL_atmoic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) -{ - return (SDL_bool)(InterlockedCompareExchangePointer((PVOID*)atomic, - (PVOID)newvalue, - (PVOID)oldvalue) == oldvalue); -} - - -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - return (InterlockedCompareExchangePointer(atomic, newvalue, oldvalue) == oldvalue); -} -# else /* WINVER <= 0x0400 */ -# if (SIZEOF_VOIDP != 4) -# error "InterlockedCompareExchangePointer needed" -# endif - -static __inline__ SDL_bool -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) -{ - return (InterlockedCompareExchange(atomic, newvalue, oldvalue) == oldvalue); -} - -static __inline__ SDL_bool -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) -{ - return (InterlockedCompareExchange(atomic, newvalue, oldvalue) == oldvalue); -} -# endif -#else /* when all else fails */ -# define SDL_ATOMIC_OPS_NOT_SUPPORTED -# warning "Atomic Ops for this platform not supported!" -static __inline__ int -SDL_atomic_int_xchg_add(volatile int* atomic, int value) -{ - int rv = *atomic; - *(atomic) += value; - return rv; -} - -static __inline__ SDL_bool -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) -{ - return (*atomic == oldvalue) ? - ((*atomic = newvalue), SDL_TRUE) : SDL_FALSE; -} - -static __inline__ void -SDL_atomic_int_add(volatile int* atomic, int value) -{ - *atomic += value; -} -#endif /* arch & platforms */ - +/** + * \def SDL_AtomicWait64(ptr) + * + * \brief 64 bit version of SDL_AtomicWait32 + * + * \sa SDL_AtomicWait32 + */ +#define SDL_AtomicWait64(ptr) \ + { \ + while (!SDL_AtomicTestThenSet64(ptr) \ + { \ + SDL_Sleep(0); \ + }; \ + }; /* *INDENT-ON* */ -#ifdef ATOMIC_INT_CMP_XCHG -static __inline__ SDL_bool -SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue) -{ - return (SDL_bool) ATOMIC_INT_CMP_XCHG(atomic, oldvalue, newvalue); -} +/* Function prototypes */ -static __inline__ int -SDL_atomic_int_xchg_add(volatile int *atomic, int value) -{ - int rv; - do - rv = *atomic; - while (!ATOMIC_INT_CMP_XCHG(atomic, rv, rv + value)); - return rv; -} +/** + * \fn int SDL_AtomicExchange32(Uint32 * ptr, Uint32 value) + * + * \brief Atomically exchange two 32 bit values. + * + * \return the value point to by ptr. + * + * \param ptr points to the value to be fetched from *ptr. + * \param value is value to be stored at *ptr. + * + * The current value stored at *ptr is returned and it is replaced + * with value. This function can be used to implement SDL_TestThenSet. + * + */ +extern DECLSPEC Uint32 SDLCALL SDL_AtomicExchange32(Uint32 * ptr, Uint32 value); +/** + * \fn int SDL_AtomicCompareThenSet32(Uint32 * ptr, Uint32 oldvalue, Uint32 newvalue) + * + * \brief If *ptr == oldvalue then replace the contents of *ptr by new value. + * + * \return true if the newvalue was stored. + * + * \param *ptr is the value to be compared and replaced. + * \param oldvalue is value to be compared to *ptr. + * \param newvalue is value to be stored at *ptr. + * + */ +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCompareThenSet32(Uint32 * ptr, + Uint32 oldvalue, Uint32 newvalue); +/** + * \fn SDL_bool SDL_AtomicTestThenSet32(Uint32 * ptr); + * + * \brief Check to see if *ptr == 0 and set it to non-zero. + * + * \return SDL_True if the value pointed to by ptr was zero and + * SDL_False if it was not zero + * + * \param ptr points to the value to be tested and set. + * + */ +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTestThenSet32(Uint32 * ptr); +/** + * \fn void SDL_AtomicClear32(Uint32 * ptr); + * + * \brief set the value pointed to by ptr to be zero. + * + * \param ptr address of the value to be set to zero + * + */ +extern DECLSPEC void SDLCALL SDL_AtomicClear32(Uint32 * ptr); +/** + * \fn Uint32 SDL_AtomicFetchThenIncrement32(Uint32 * ptr); + * + * \brief fetch the current value of *ptr and then increment that + * value in place. + * + * \return the value before it was incremented. + * + * \param ptr address of the value to fetch and increment + * + */ +extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenIncrement32(Uint32 * ptr); +/** + * \fn Uint32 SDL_AtomicFetchThenDecrement32(Uint32 * ptr); + * + * \brief fetch *ptr and then decrement the value in place. + * + * \return the value before it was decremented. + * + * \param ptr address of the value to fetch and drement + * + */ +extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenDecrement32(Uint32 * ptr); +/** + * \fn Uint32 SDL_AtomicFetchThenAdd32(Uint32 * ptr, Uint32 value); + * + * \brief fetch the current value at ptr and then add value to *ptr. + * + * \return *ptr before the addition took place. + * + * \param ptr the address of data we are changing. + * \param value the value to add to *ptr. + * + */ +extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenAdd32(Uint32 * ptr, Uint32 value); +/** + * \fn Uint32 SDL_AtomicFetchThenSubtract32(Uint32 * ptr, Uint32 value); + * + * \brief Fetch *ptr and then subtract value from it. + * + * \return *ptr before the subtraction took place. + * + * \param ptr the address of the data being changed. + * \param value the value to subtract from *ptr. + * + */ +extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenSubtract32(Uint32 * ptr, Uint32 value); +/** + * \fn Uint32 SDL_AtomicIncrementThenFetch32(Uint32 * ptr); + * + * \brief Add one to the data pointed to by ptr and return that value. + * + * \return the incremented value. + * + * \param ptr address of the data to increment. + * + */ +extern DECLSPEC Uint32 SDLCALL SDL_AtomicIncrementThenFetch32(Uint32 * ptr); +/** + * \fn Uint32 SDL_AtomicDecrementThenFetch32(Uint32 * ptr); + * + * \brief Subtract one from data pointed to by ptr and return the new value. + * + * \return The decremented value. + * + * \param ptr The address of the data to decrement. + * + */ +extern DECLSPEC Uint32 SDLCALL SDL_AtomicDecrementThenFetch32(Uint32 * ptr); +/** + * \fn Uint32 SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 value); + * + * \brief Add value to the data pointed to by ptr and return result. + * + * \return The sum of *ptr and value. + * + * \param ptr The address of the data to be modified. + * \param value The value to be added. + * + */ +extern DECLSPEC Uint32 SDLCALL SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 value); +/** + * \fn Uint32 SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value); + * + * \brief Subtract value from the data pointed to by ptr and return the result. + * + * \return the difference between *ptr and value. + * + * \param ptr The address of the data to be modified. + * \param value The value to be subtracted. + * + */ +extern DECLSPEC Uint32 SDLCALL SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value); -static __inline__ void -SDL_atomic_int_add(volatile int *atomic, int value) -{ - int rv; - do - rv = *atomic; - while (!ATOMIC_INT_CMP_XCHG(atomic, rv, rv + value)); -} -#endif /* ATOMIC_CMP_XCHG */ +#ifdef SDL_HAS_64BIT_TYPE -#ifdef ATOMIC_MEMORY_BARRIER -# define SDL_atomic_int_get(atomic) \ - (ATOMIC_MEMORY_BARRIER,*(atomic)) -# define SDL_atomic_int_set(atomic,value) \ - (*(atomic)=value,ATOMIC_MEMORY_BARRIER) -#else -# define SDL_atomic_int_get(atomic) (*(atomic)) -# define SDL_atomic_int_set(atomic, newvalue) ((void)(*(atomic) = (newvalue))) -#endif /* MEMORY_BARRIER_NEEDED */ - -#define SDL_atomic_int_inc(atomic) (SDL_atomic_int_add((atomic),1)) -#define SDL_atomic_int_dec_test(atomic) (SDL_atomic_int_xchg_add((atomic),-1) == 1) +extern DECLSPEC Uint64 SDLCALL SDL_AtomicExchange64(Uint64 * ptr, Uint64 value); +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCompareThenSet64(Uint64 * ptr, + Uint64 oldvalue, Uint64 newvalue); +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTestThenSet64(Uint64 * ptr); +extern DECLSPEC void SDLCALL SDL_AtomicClear64(Uint64 * ptr); +extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenIncrement64(Uint64 * ptr); +extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenDecrement64(Uint64 * ptr); +extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenAdd64(Uint64 * ptr, Uint64 value); +extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenSubtract64(Uint64 * ptr, Uint64 value); +extern DECLSPEC Uint64 SDLCALL SDL_AtomicIncrementThenFetch64(Uint64 * ptr); +extern DECLSPEC Uint64 SDLCALL SDL_AtomicDecrementThenFetch64(Uint64 * ptr); +extern DECLSPEC Uint64 SDLCALL SDL_AtomicAddThenFetch64(Uint64 * ptr, Uint64 value); +extern DECLSPEC Uint64 SDLCALL SDL_AtomicSubtractThenFetch64(Uint64 * ptr, Uint64 value); +#endif /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/atomic/linux/SDL_atomic.c b/src/atomic/linux/SDL_atomic.c new file mode 100644 index 000000000..02c13dd3e --- /dev/null +++ b/src/atomic/linux/SDL_atomic.c @@ -0,0 +1,176 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef SDL_ATOMIC_LINUX + +#include "SDL.h" +#include "SDL_config.h" +#include "SDL_atomic.h" + +Uint32 +SDL_AtomicExchange32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +SDL_bool +SDL_AtomicCompareThenSet32(Uint32 * ptr, Uint32 oldvalue, Uint32 newvalue) +{ + return SDL_false; +} + +SDL_bool +SDL_AtomicTestThenSet32(Uint32 * ptr) +{ + return SDL_false; +} + +void +SDL_AtomicClear32(Uint32 * ptr) +{ +} + +Uint32 +SDL_AtomicFetchThenIncrement32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicFetchThenDecrement32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicFetchThenAdd32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +Uint32 +SDL_AtomicFetchThenSubtract32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +Uint32 +SDL_AtomicIncrementThenFetch32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicDecrementThenFetch32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +Uint32 +SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + + +#ifdef SDL_HAS_64BIT_TYPE + +Uint64 +SDL_AtomicExchange64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +SDL_bool +SDL_AtomicCompareThenSet64(Uint64 * ptr, +Uint64 oldvalue, Uint64 newvalue) +{ + return SDL_false; +} + +SDL_bool +SDL_AtomicTestThenSet64(Uint64 * ptr) +{ + return SDL_false; +} + +void +SDL_AtomicClear64(Uint64 * ptr) +{ +} + +Uint64 +SDL_AtomicFetchThenIncrement64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicFetchThenDecrement64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicFetchThenAdd64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +Uint64 +SDL_AtomicFetchThenSubtract64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +Uint64 +SDL_AtomicIncrementThenFetch64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicDecrementThenFetch64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicAddThenFetch64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +Uint64 +SDL_AtomicSubtractThenFetch64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +#endif +#endif diff --git a/src/atomic/macosx/SDL_atomic.c b/src/atomic/macosx/SDL_atomic.c new file mode 100644 index 000000000..02c13dd3e --- /dev/null +++ b/src/atomic/macosx/SDL_atomic.c @@ -0,0 +1,176 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef SDL_ATOMIC_LINUX + +#include "SDL.h" +#include "SDL_config.h" +#include "SDL_atomic.h" + +Uint32 +SDL_AtomicExchange32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +SDL_bool +SDL_AtomicCompareThenSet32(Uint32 * ptr, Uint32 oldvalue, Uint32 newvalue) +{ + return SDL_false; +} + +SDL_bool +SDL_AtomicTestThenSet32(Uint32 * ptr) +{ + return SDL_false; +} + +void +SDL_AtomicClear32(Uint32 * ptr) +{ +} + +Uint32 +SDL_AtomicFetchThenIncrement32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicFetchThenDecrement32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicFetchThenAdd32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +Uint32 +SDL_AtomicFetchThenSubtract32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +Uint32 +SDL_AtomicIncrementThenFetch32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicDecrementThenFetch32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +Uint32 +SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + + +#ifdef SDL_HAS_64BIT_TYPE + +Uint64 +SDL_AtomicExchange64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +SDL_bool +SDL_AtomicCompareThenSet64(Uint64 * ptr, +Uint64 oldvalue, Uint64 newvalue) +{ + return SDL_false; +} + +SDL_bool +SDL_AtomicTestThenSet64(Uint64 * ptr) +{ + return SDL_false; +} + +void +SDL_AtomicClear64(Uint64 * ptr) +{ +} + +Uint64 +SDL_AtomicFetchThenIncrement64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicFetchThenDecrement64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicFetchThenAdd64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +Uint64 +SDL_AtomicFetchThenSubtract64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +Uint64 +SDL_AtomicIncrementThenFetch64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicDecrementThenFetch64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicAddThenFetch64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +Uint64 +SDL_AtomicSubtractThenFetch64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +#endif +#endif diff --git a/src/atomic/win32/SDL_atomic.c b/src/atomic/win32/SDL_atomic.c new file mode 100644 index 000000000..02c13dd3e --- /dev/null +++ b/src/atomic/win32/SDL_atomic.c @@ -0,0 +1,176 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef SDL_ATOMIC_LINUX + +#include "SDL.h" +#include "SDL_config.h" +#include "SDL_atomic.h" + +Uint32 +SDL_AtomicExchange32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +SDL_bool +SDL_AtomicCompareThenSet32(Uint32 * ptr, Uint32 oldvalue, Uint32 newvalue) +{ + return SDL_false; +} + +SDL_bool +SDL_AtomicTestThenSet32(Uint32 * ptr) +{ + return SDL_false; +} + +void +SDL_AtomicClear32(Uint32 * ptr) +{ +} + +Uint32 +SDL_AtomicFetchThenIncrement32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicFetchThenDecrement32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicFetchThenAdd32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +Uint32 +SDL_AtomicFetchThenSubtract32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +Uint32 +SDL_AtomicIncrementThenFetch32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicDecrementThenFetch32(Uint32 * ptr) +{ + return 0; +} + +Uint32 +SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + +Uint32 +SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value) +{ + return 0; +} + + +#ifdef SDL_HAS_64BIT_TYPE + +Uint64 +SDL_AtomicExchange64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +SDL_bool +SDL_AtomicCompareThenSet64(Uint64 * ptr, +Uint64 oldvalue, Uint64 newvalue) +{ + return SDL_false; +} + +SDL_bool +SDL_AtomicTestThenSet64(Uint64 * ptr) +{ + return SDL_false; +} + +void +SDL_AtomicClear64(Uint64 * ptr) +{ +} + +Uint64 +SDL_AtomicFetchThenIncrement64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicFetchThenDecrement64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicFetchThenAdd64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +Uint64 +SDL_AtomicFetchThenSubtract64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +Uint64 +SDL_AtomicIncrementThenFetch64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicDecrementThenFetch64(Uint64 * ptr) +{ + return 0; +} + +Uint64 +SDL_AtomicAddThenFetch64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +Uint64 +SDL_AtomicSubtractThenFetch64(Uint64 * ptr, Uint64 value) +{ + return 0; +} + +#endif +#endif diff --git a/test/testatomic.c b/test/testatomic.c index 37e560490..ca47d68eb 100644 --- a/test/testatomic.c +++ b/test/testatomic.c @@ -3,62 +3,62 @@ int main(int argc, char **argv) { - int rv = 10; - volatile int atomic; +/* int rv = 10; */ +/* volatile int atomic; */ - SDL_atomic_int_set(&atomic, 10); - if (SDL_atomic_int_get(&atomic) != 10) - printf("Error: "); - printf("SDL_atomic_int_set(atomic, 10): atomic-> %d\n", - SDL_atomic_int_get(&atomic)); +/* SDL_atomic_int_set(&atomic, 10); */ +/* if (SDL_atomic_int_get(&atomic) != 10) */ +/* printf("Error: "); */ +/* printf("SDL_atomic_int_set(atomic, 10): atomic-> %d\n", */ +/* SDL_atomic_int_get(&atomic)); */ - SDL_atomic_int_add(&atomic, 10); - if (SDL_atomic_int_get(&atomic) != 20) - printf("Error: "); - printf("SDL_atomic_int_add(atomic, 10): atomic-> %d\n", - SDL_atomic_int_get(&atomic)); +/* SDL_atomic_int_add(&atomic, 10); */ +/* if (SDL_atomic_int_get(&atomic) != 20) */ +/* printf("Error: "); */ +/* printf("SDL_atomic_int_add(atomic, 10): atomic-> %d\n", */ +/* SDL_atomic_int_get(&atomic)); */ - rv = SDL_atomic_int_cmp_xchg(&atomic, 20, 30); - if (rv != SDL_TRUE || SDL_atomic_int_get(&atomic) != 30) - printf("Error: "); - printf("SDL_atomic_int_cmp_xchg(atomic, 20, 30): rv-> %d, atomic-> %d\n", - rv, SDL_atomic_int_get(&atomic)); +/* rv = SDL_atomic_int_cmp_xchg(&atomic, 20, 30); */ +/* if (rv != SDL_TRUE || SDL_atomic_int_get(&atomic) != 30) */ +/* printf("Error: "); */ +/* printf("SDL_atomic_int_cmp_xchg(atomic, 20, 30): rv-> %d, atomic-> %d\n", */ +/* rv, SDL_atomic_int_get(&atomic)); */ - rv = SDL_atomic_int_cmp_xchg(&atomic, 20, 30); - if (rv != SDL_FALSE || SDL_atomic_int_get(&atomic) != 30) - printf("Error: "); - printf("SDL_atomic_int_cmp_xchg(atomic, 20, 40): rv-> %d, atomic-> %d\n", - rv, SDL_atomic_int_get(&atomic)); +/* rv = SDL_atomic_int_cmp_xchg(&atomic, 20, 30); */ +/* if (rv != SDL_FALSE || SDL_atomic_int_get(&atomic) != 30) */ +/* printf("Error: "); */ +/* printf("SDL_atomic_int_cmp_xchg(atomic, 20, 40): rv-> %d, atomic-> %d\n", */ +/* rv, SDL_atomic_int_get(&atomic)); */ - rv = SDL_atomic_int_xchg_add(&atomic, 10); - if (rv != 30 || SDL_atomic_int_get(&atomic) != 40) - printf("Error: "); - printf("SDL_atomic_int_xchg_add(atomic, 10): rv-> %d, atomic-> %d\n", - rv, SDL_atomic_int_get(&atomic)); +/* rv = SDL_atomic_int_xchg_add(&atomic, 10); */ +/* if (rv != 30 || SDL_atomic_int_get(&atomic) != 40) */ +/* printf("Error: "); */ +/* printf("SDL_atomic_int_xchg_add(atomic, 10): rv-> %d, atomic-> %d\n", */ +/* rv, SDL_atomic_int_get(&atomic)); */ - SDL_atomic_int_inc(&atomic); - if (SDL_atomic_int_get(&atomic) != 41) - printf("Error: "); - printf("SDL_atomic_int_inc(atomic): atomic-> %d\n", - SDL_atomic_int_get(&atomic)); +/* SDL_atomic_int_inc(&atomic); */ +/* if (SDL_atomic_int_get(&atomic) != 41) */ +/* printf("Error: "); */ +/* printf("SDL_atomic_int_inc(atomic): atomic-> %d\n", */ +/* SDL_atomic_int_get(&atomic)); */ - rv = SDL_atomic_int_dec_test(&atomic); - if (rv != SDL_FALSE || SDL_atomic_int_get(&atomic) != 40) - printf("Error: "); - printf("SDL_atomic_int_dec_test(atomic): rv-> %d, atomic-> %d\n", - rv, SDL_atomic_int_get(&atomic)); +/* rv = SDL_atomic_int_dec_test(&atomic); */ +/* if (rv != SDL_FALSE || SDL_atomic_int_get(&atomic) != 40) */ +/* printf("Error: "); */ +/* printf("SDL_atomic_int_dec_test(atomic): rv-> %d, atomic-> %d\n", */ +/* rv, SDL_atomic_int_get(&atomic)); */ - SDL_atomic_int_set(&atomic, 1); - if (SDL_atomic_int_get(&atomic) != 1) - printf("Error: "); - printf("SDL_atomic_int_set(atomic, 1): atomic-> %d\n", - SDL_atomic_int_get(&atomic)); +/* SDL_atomic_int_set(&atomic, 1); */ +/* if (SDL_atomic_int_get(&atomic) != 1) */ +/* printf("Error: "); */ +/* printf("SDL_atomic_int_set(atomic, 1): atomic-> %d\n", */ +/* SDL_atomic_int_get(&atomic)); */ - rv = SDL_atomic_int_dec_test(&atomic); - if (rv != SDL_TRUE || SDL_atomic_int_get(&atomic) != 0) - printf("Error: "); - printf("SDL_atomic_int_dec_test(atomic): rv-> %d, atomic-> %d\n", - rv, SDL_atomic_int_get(&atomic)); +/* rv = SDL_atomic_int_dec_test(&atomic); */ +/* if (rv != SDL_TRUE || SDL_atomic_int_get(&atomic) != 0) */ +/* printf("Error: "); */ +/* printf("SDL_atomic_int_dec_test(atomic): rv-> %d, atomic-> %d\n", */ +/* rv, SDL_atomic_int_get(&atomic)); */ return 0; }