I've made so many changes I don't dare continue until I check the current stuff in.

/test/testatomic.c performs absolutely basic tests to show that the function work as expected. Need a second test to do more detailed tests.

/include/SDL_atomic.h provides declarations for all included functions.

/src/atomic/linux/SDL_atomic.c provided all the functions. On a generic built the 64 bit functions work, but they are emulated. On a build for -march=pentium and above the 64 bit functions use native instructions
/src/atomic/dummy/SDL_atomic.c emulates all the operations using SDL_mutex.h.
/src/atomic/win32/SDL_atomic.c is a copy of dummy
/src/atomic/macosx/SDL_atomic.s is a copy of dummy

These versions of SDL_atomic.c provide a frame work for building the library with a mixture of native and emulated functions. This allows the whole library to be provided on all platforms. (I hope.)
I hope this fits with the SDL philosophy of either providing a common subset or emulating when the platform is missing a feature.

I have not added dummy, macosx, or win32 to the build. They are there as place holders for future work.

I have modified congifure.in to compile sources in /src/atomic/linux. (The SDL configure.in file is an amazing piece of work and I hope I didn't mess it up. :-)

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%403671
This commit is contained in:
Bob Pendleton 2009-06-29 19:54:43 +00:00
parent 9b4d5550f8
commit dad8f05067
6 changed files with 3785 additions and 169 deletions

View File

@ -29,7 +29,6 @@
#ifndef _SDL_atomic_h_
#define _SDL_atomic_h_
#include "SDL_stdinc.h"
#include "SDL_platform.h"
@ -42,72 +41,51 @@ extern "C" {
/* *INDENT-ON* */
#endif
/* *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.
*
* These operations may, or may not, actually be implemented using
* processor specific atomic operations. When possible they are
* implemented as true processor specific atomic operations. When that
* is not possible the are implemented using locks that *do* use the
* available atomic operations. In rare cases they may be implemented
* using SDL's mutex fuctions.
*/
#define SDL_AtomicBusyWait32(ptr) \
{ \
while (!SDL_AtomicTestThenSet32(ptr) \
{ \
}; \
};
/**
* \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); \
}; \
};
/**
* \def SDL_AtomicBusyWait64(ptr)
*
* \brief 64 bit version of busy wait
*
* \sa SDL_AtomicBusyWait32
*/
#define SDL_AtomicBusyWait64(ptr) \
{ \
while (!SDL_AtomicTestThenSet64(ptr) \
{ \
}; \
};
/**
* \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* */
/* Function prototypes */
/* 8 bit atomic operations */
extern DECLSPEC Uint8 SDLCALL SDL_AtomicExchange8(Uint8 * ptr, Uint8 value);
extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCompareThenSet8(Uint8 * ptr,
Uint8 oldvalue, Uint8 newvalue);
extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTestThenSet8(Uint8 * ptr);
extern DECLSPEC void SDLCALL SDL_AtomicClear8(Uint8 * ptr);
extern DECLSPEC Uint8 SDLCALL SDL_AtomicFetchThenIncrement8(Uint8 * ptr);
extern DECLSPEC Uint8 SDLCALL SDL_AtomicFetchThenDecrement8(Uint8 * ptr);
extern DECLSPEC Uint8 SDLCALL SDL_AtomicFetchThenAdd8(Uint8 * ptr, Uint8 value);
extern DECLSPEC Uint8 SDLCALL SDL_AtomicFetchThenSubtract8(Uint8 * ptr, Uint8 value);
extern DECLSPEC Uint8 SDLCALL SDL_AtomicIncrementThenFetch8(Uint8 * ptr);
extern DECLSPEC Uint8 SDLCALL SDL_AtomicDecrementThenFetch8(Uint8 * ptr);
extern DECLSPEC Uint8 SDLCALL SDL_AtomicAddThenFetch8(Uint8 * ptr, Uint8 value);
extern DECLSPEC Uint8 SDLCALL SDL_AtomicSubtractThenFetch8(Uint8 * ptr, Uint8 value);
/* 16 bit atomic operations */
extern DECLSPEC Uint16 SDLCALL SDL_AtomicExchange16(Uint16 * ptr, Uint16 value);
extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCompareThenSet16(Uint16 * ptr,
Uint16 oldvalue, Uint16 newvalue);
extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTestThenSet16(Uint16 * ptr);
extern DECLSPEC void SDLCALL SDL_AtomicClear16(Uint16 * ptr);
extern DECLSPEC Uint16 SDLCALL SDL_AtomicFetchThenIncrement16(Uint16 * ptr);
extern DECLSPEC Uint16 SDLCALL SDL_AtomicFetchThenDecrement16(Uint16 * ptr);
extern DECLSPEC Uint16 SDLCALL SDL_AtomicFetchThenAdd16(Uint16 * ptr, Uint16 value);
extern DECLSPEC Uint16 SDLCALL SDL_AtomicFetchThenSubtract16(Uint16 * ptr, Uint16 value);
extern DECLSPEC Uint16 SDLCALL SDL_AtomicIncrementThenFetch16(Uint16 * ptr);
extern DECLSPEC Uint16 SDLCALL SDL_AtomicDecrementThenFetch16(Uint16 * ptr);
extern DECLSPEC Uint16 SDLCALL SDL_AtomicAddThenFetch16(Uint16 * ptr, Uint16 value);
extern DECLSPEC Uint16 SDLCALL SDL_AtomicSubtractThenFetch16(Uint16 * ptr, Uint16 value);
/* 32 bit atomic operations */
/**
* \fn int SDL_AtomicExchange32(Uint32 * ptr, Uint32 value)
*
@ -252,6 +230,7 @@ extern DECLSPEC Uint32 SDLCALL SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 val
*/
extern DECLSPEC Uint32 SDLCALL SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value);
/* 64 bit atomic operations */
#ifdef SDL_HAS_64BIT_TYPE
extern DECLSPEC Uint64 SDLCALL SDL_AtomicExchange64(Uint64 * ptr, Uint64 value);
@ -267,7 +246,7 @@ 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
#endif /* SDL_HAS_64BIT_TYPE */
/* Ends C function definitions when using C++ */
#ifdef __cplusplus

File diff suppressed because it is too large Load Diff

View File

@ -20,154 +20,955 @@
slouken@libsdl.org
*/
#include "SDL.h"
#include "SDL_config.h"
#include "SDL_stdinc.h"
#include "SDL_atomic.h"
/*
This file provides 8, 16, 32, and 64 bit atomic operations. If the
operations are provided by the native hardware and operating system
they are used. If they are not then the operations are emulated
using the SDL mutex operations.
*/
/*
First, detect whether the operations are supported and create
#defines that indicate that they do exist. The goal is to have all
the system dependent code in the top part of the file so that the
bottom can be use unchanged across all platforms.
Second, #define all the operations in each size class that are
supported. Doing this allows supported operations to be used along
side of emulated operations.
*/
/*
Linux version.
Test for gnu C builtin support for atomic operations. The only way
I know of is to check to see if the
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_* macros are defined.
*/
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
#define HAVE_ALL_8_BIT_OPS
#define nativeExchange8(ptr, value) (__sync_lock_test_and_set(ptr, value))
#define nativeCompareThenSet8(ptr, oldvalue, newvalue) (oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
#define nativeTestThenSet8(ptr) (0 == __sync_lock_test_and_set(ptr, 1))
#define nativeClear8(ptr) (__sync_lock_release(ptr))
#define nativeFetchThenIncrement8(ptr) (__sync_fetch_and_add(ptr, 1))
#define nativeFetchThenDecrement8(ptr) (__sync_fetch_and_sub(ptr, 1))
#define nativeFetchThenAdd8(ptr, value) (__sync_fetch_and_add(ptr, value))
#define nativeFetchThenSubtract8(ptr, value) (__sync_fetch_and_sub(ptr, value))
#define nativeIncrementThenFetch8(ptr) (__sync_add_and_fetch(ptr, 1))
#define nativeDecrementThenFetch8(ptr) (__sync_sub_and_fetch(ptr, 1))
#define nativeAddThenFetch8(ptr, value) (__sync_add_and_fetch(ptr, value))
#define nativeSubtractThenFetch8(ptr, value) (__sync_sub_and_fetch(ptr, value))
#endif
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
#define HAVE_ALL_16_BIT_OPS
#define nativeExchange16(ptr, value) (__sync_lock_test_and_set(ptr, value))
#define nativeCompareThenSet16(ptr, oldvalue, newvalue) (oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
#define nativeTestThenSet16(ptr) (0 == __sync_lock_test_and_set(ptr, 1))
#define nativeClear16(ptr) (__sync_lock_release(ptr))
#define nativeFetchThenIncrement16(ptr) (__sync_fetch_and_add(ptr, 1))
#define nativeFetchThenDecrement16(ptr) (__sync_fetch_and_sub(ptr, 1))
#define nativeFetchThenAdd16(ptr, value) (__sync_fetch_and_add(ptr, value))
#define nativeFetchThenSubtract16(ptr, value) (__sync_fetch_and_sub(ptr, value))
#define nativeIncrementThenFetch16(ptr) (__sync_add_and_fetch(ptr, 1))
#define nativeDecrementThenFetch16(ptr) (__sync_sub_and_fetch(ptr, 1))
#define nativeAddThenFetch16(ptr, value) (__sync_add_and_fetch(ptr, value))
#define nativeSubtractThenFetch16(ptr, value) (__sync_sub_and_fetch(ptr, value))
#endif
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
#define HAVE_ALL_32_BIT_OPS
#define nativeExchange32(ptr, value) (__sync_lock_test_and_set(ptr, value))
#define nativeCompareThenSet32(ptr, oldvalue, newvalue) (oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
#define nativeTestThenSet32(ptr) (0 == __sync_lock_test_and_set(ptr, 1))
#define nativeClear32(ptr) (__sync_lock_release(ptr))
#define nativeFetchThenIncrement32(ptr) (__sync_fetch_and_add(ptr, 1))
#define nativeFetchThenDecrement32(ptr) (__sync_fetch_and_sub(ptr, 1))
#define nativeFetchThenAdd32(ptr, value) (__sync_fetch_and_add(ptr, value))
#define nativeFetchThenSubtract32(ptr, value) (__sync_fetch_and_sub(ptr, value))
#define nativeIncrementThenFetch32(ptr) (__sync_add_and_fetch(ptr, 1))
#define nativeDecrementThenFetch32(ptr) (__sync_sub_and_fetch(ptr, 1))
#define nativeAddThenFetch32(ptr, value) (__sync_add_and_fetch(ptr, value))
#define nativeSubtractThenFetch32(ptr, value) (__sync_sub_and_fetch(ptr, value))
#endif
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
#define HAVE_ALL_64_BIT_OPS
#define nativeExchange64(ptr, value) (__sync_lock_test_and_set(ptr, value))
#define nativeCompareThenSet64(ptr, oldvalue, newvalue) (oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
#define nativeTestThenSet64(ptr) (0 == __sync_lock_test_and_set(ptr, 1))
#define nativeClear64(ptr) (__sync_lock_release(ptr))
#define nativeFetchThenIncrement64(ptr) (__sync_fetch_and_add(ptr, 1))
#define nativeFetchThenDecrement64(ptr) (__sync_fetch_and_sub(ptr, 1))
#define nativeFetchThenAdd64(ptr, value) (__sync_fetch_and_add(ptr, value))
#define nativeFetchThenSubtract64(ptr, value) (__sync_fetch_and_sub(ptr, value))
#define nativeIncrementThenFetch64(ptr) (__sync_add_and_fetch(ptr, 1))
#define nativeDecrementThenFetch64(ptr) (__sync_sub_and_fetch(ptr, 1))
#define nativeAddThenFetch64(ptr, value) (__sync_add_and_fetch(ptr, value))
#define nativeSubtractThenFetch64(ptr, value) (__sync_sub_and_fetch(ptr, value))
#endif
/*
If any of the operations are not provided then we must emulate some of
them.
*/
#if !defined(HAVE_ALL_8_BIT_OPS) || !defined(HAVE_ALL_16_BIT_OPS) || !defined(HAVE_ALL_32_BIT_OPS) || !defined(HAVE_ALL_64_BIT_OPS)
static Uint32 lock = 0;
#define privateWaitLock() \
while (nativeTestThenSet32(&lock)) \
{ \
};
#define privateUnlock() (nativeClear32(&lock))
#endif
/* 8 bit atomic operations */
Uint8
SDL_AtomicExchange8(Uint8 * ptr, Uint8 value)
{
#ifdef nativeExchange8
return nativeExchange8(ptr, value);
#else
Uint8 tmp = 0;;
privateWaitLock();
tmp = *ptr;
*ptr = value;
privateUnlock();
return tmp;
#endif
}
SDL_bool
SDL_AtomicCompareThenSet8(Uint8 * ptr, Uint8 oldvalue, Uint8 newvalue)
{
#ifdef nativeCompareThenSet8
return (SDL_bool)nativeCompareThenSet8(ptr, oldvalue, newvalue);
#else
SDL_bool result = SDL_FALSE;
privateWaitLock();
result = (*ptr == oldvalue);
if (result)
{
*ptr = newvalue;
}
privateUnlock();
return result;
#endif
}
SDL_bool
SDL_AtomicTestThenSet8(Uint8 * ptr)
{
#ifdef nativeTestThenSet8
return (SDL_bool)nativeTestThenSet8(ptr);
#else
SDL_bool result = SDL_FALSE;
privateWaitLock();
result = (*ptr == 0);
if (result)
{
*ptr = 1;
}
privateUnlock();
return result;
#endif
}
void
SDL_AtomicClear8(Uint8 * ptr)
{
#ifdef nativeClear8
nativeClear8(ptr);
#else
privateWaitLock();
*ptr = 0;
privateUnlock();
return;
#endif
}
Uint8
SDL_AtomicFetchThenIncrement8(Uint8 * ptr)
{
#ifdef nativeFetchThenIncrement8
return nativeFetchThenIncrement8(ptr);
#else
Uint8 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)+= 1;
privateUnlock();
return tmp;
#endif
}
Uint8
SDL_AtomicFetchThenDecrement8(Uint8 * ptr)
{
#ifdef nativeFetchThenDecrement8
return nativeFetchThenDecrement8(ptr);
#else
Uint8 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr) -= 1;
privateUnlock();
return tmp;
#endif
}
Uint8
SDL_AtomicFetchThenAdd8(Uint8 * ptr, Uint8 value)
{
#ifdef nativeFetchThenAdd8
return nativeFetchThenAdd8(ptr, value);
#else
Uint8 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)+= value;
privateUnlock();
return tmp;
#endif
}
Uint8
SDL_AtomicFetchThenSubtract8(Uint8 * ptr, Uint8 value)
{
#ifdef nativeFetchThenSubtract8
return nativeFetchThenSubtract8(ptr, value);
#else
Uint8 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)-= value;
privateUnlock();
return tmp;
#endif
}
Uint8
SDL_AtomicIncrementThenFetch8(Uint8 * ptr)
{
#ifdef nativeIncrementThenFetch8
return nativeIncrementThenFetch8(ptr);
#else
Uint8 tmp = 0;;
privateWaitLock();
(*ptr)+= 1;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint8
SDL_AtomicDecrementThenFetch8(Uint8 * ptr)
{
#ifdef nativeDecrementThenFetch8
return nativeDecrementThenFetch8(ptr);
#else
Uint8 tmp = 0;;
privateWaitLock();
(*ptr)-= 1;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint8
SDL_AtomicAddThenFetch8(Uint8 * ptr, Uint8 value)
{
#ifdef nativeAddThenFetch8
return nativeAddThenFetch8(ptr, value);
#else
Uint8 tmp = 0;;
privateWaitLock();
(*ptr)+= value;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint8
SDL_AtomicSubtractThenFetch8(Uint8 * ptr, Uint8 value)
{
#ifdef nativeSubtractThenFetch8
return nativeSubtractThenFetch8(ptr, value);
#else
Uint8 tmp = 0;;
privateWaitLock();
(*ptr)-= value;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
/* 16 bit atomic operations */
Uint16
SDL_AtomicExchange16(Uint16 * ptr, Uint16 value)
{
#ifdef nativeExchange16
return nativeExchange16(ptr, value);
#else
Uint16 tmp = 0;;
privateWaitLock();
tmp = *ptr;
*ptr = value;
privateUnlock();
return tmp;
#endif
}
SDL_bool
SDL_AtomicCompareThenSet16(Uint16 * ptr, Uint16 oldvalue, Uint16 newvalue)
{
#ifdef nativeCompareThenSet16
return (SDL_bool)nativeCompareThenSet16(ptr, oldvalue, newvalue);
#else
SDL_bool result = SDL_FALSE;
privateWaitLock();
result = (*ptr == oldvalue);
if (result)
{
*ptr = newvalue;
}
privateUnlock();
return result;
#endif
}
SDL_bool
SDL_AtomicTestThenSet16(Uint16 * ptr)
{
#ifdef nativeTestThenSet16
return (SDL_bool)nativeTestThenSet16(ptr);
#else
SDL_bool result = SDL_FALSE;
privateWaitLock();
result = (*ptr == 0);
if (result)
{
*ptr = 1;
}
privateUnlock();
return result;
#endif
}
void
SDL_AtomicClear16(Uint16 * ptr)
{
#ifdef nativeClear16
nativeClear16(ptr);
#else
privateWaitLock();
*ptr = 0;
privateUnlock();
return;
#endif
}
Uint16
SDL_AtomicFetchThenIncrement16(Uint16 * ptr)
{
#ifdef nativeFetchThenIncrement16
return nativeFetchThenIncrement16(ptr);
#else
Uint16 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)+= 1;
privateUnlock();
return tmp;
#endif
}
Uint16
SDL_AtomicFetchThenDecrement16(Uint16 * ptr)
{
#ifdef nativeFetchThenDecrement16
return nativeFetchThenDecrement16(ptr);
#else
Uint16 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr) -= 1;
privateUnlock();
return tmp;
#endif
}
Uint16
SDL_AtomicFetchThenAdd16(Uint16 * ptr, Uint16 value)
{
#ifdef nativeFetchThenAdd16
return nativeFetchThenAdd16(ptr, value);
#else
Uint16 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)+= value;
privateUnlock();
return tmp;
#endif
}
Uint16
SDL_AtomicFetchThenSubtract16(Uint16 * ptr, Uint16 value)
{
#ifdef nativeFetchThenSubtract16
return nativeFetchThenSubtract16(ptr, value);
#else
Uint16 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)-= value;
privateUnlock();
return tmp;
#endif
}
Uint16
SDL_AtomicIncrementThenFetch16(Uint16 * ptr)
{
#ifdef nativeIncrementThenFetch16
return nativeIncrementThenFetch16(ptr);
#else
Uint16 tmp = 0;;
privateWaitLock();
(*ptr)+= 1;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint16
SDL_AtomicDecrementThenFetch16(Uint16 * ptr)
{
#ifdef nativeDecrementThenFetch16
return nativeDecrementThenFetch16(ptr);
#else
Uint16 tmp = 0;;
privateWaitLock();
(*ptr)-= 1;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint16
SDL_AtomicAddThenFetch16(Uint16 * ptr, Uint16 value)
{
#ifdef nativeAddThenFetch16
return nativeAddThenFetch16(ptr, value);
#else
Uint16 tmp = 0;;
privateWaitLock();
(*ptr)+= value;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint16
SDL_AtomicSubtractThenFetch16(Uint16 * ptr, Uint16 value)
{
#ifdef nativeSubtractThenFetch16
return nativeSubtractThenFetch16(ptr, value);
#else
Uint16 tmp = 0;;
privateWaitLock();
(*ptr)-= value;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
/* 32 bit atomic operations */
Uint32
SDL_AtomicExchange32(Uint32 * ptr, Uint32 value)
{
return __sync_lock_test_and_set(ptr, value);
#ifdef nativeExchange32
return nativeExchange32(ptr, value);
#else
Uint32 tmp = 0;;
privateWaitLock();
tmp = *ptr;
*ptr = value;
privateUnlock();
return tmp;
#endif
}
SDL_bool
SDL_AtomicCompareThenSet32(Uint32 * ptr, Uint32 oldvalue, Uint32 newvalue)
{
return (SDL_bool)__sync_bool_compare_and_swap(ptr, oldvalue, newvalue);
#ifdef nativeCompareThenSet32
return (SDL_bool)nativeCompareThenSet32(ptr, oldvalue, newvalue);
#else
SDL_bool result = SDL_FALSE;
privateWaitLock();
result = (*ptr == oldvalue);
if (result)
{
*ptr = newvalue;
}
privateUnlock();
return result;
#endif
}
SDL_bool
SDL_AtomicTestThenSet32(Uint32 * ptr)
{
return (SDL_bool)(0 == __sync_lock_test_and_set(ptr, 1));
#ifdef nativeTestThenSet32
return (SDL_bool)nativeTestThenSet32(ptr);
#else
SDL_bool result = SDL_FALSE;
privateWaitLock();
result = (*ptr == 0);
if (result)
{
*ptr = 1;
}
privateUnlock();
return result;
#endif
}
void
SDL_AtomicClear32(Uint32 * ptr)
{
__sync_lock_release(ptr);
#ifdef nativeClear32
nativeClear32(ptr);
#else
privateWaitLock();
*ptr = 0;
privateUnlock();
return;
#endif
}
Uint32
SDL_AtomicFetchThenIncrement32(Uint32 * ptr)
{
return __sync_fetch_and_add(ptr, 1);
#ifdef nativeFetchThenIncrement32
return nativeFetchThenIncrement32(ptr);
#else
Uint32 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)+= 1;
privateUnlock();
return tmp;
#endif
}
Uint32
SDL_AtomicFetchThenDecrement32(Uint32 * ptr)
{
return __sync_fetch_and_sub(ptr, 1);
#ifdef nativeFetchThenDecrement32
return nativeFetchThenDecrement32(ptr);
#else
Uint32 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr) -= 1;
privateUnlock();
return tmp;
#endif
}
Uint32
SDL_AtomicFetchThenAdd32(Uint32 * ptr, Uint32 value)
{
return __sync_fetch_and_add(ptr, value);
#ifdef nativeFetchThenAdd32
return nativeFetchThenAdd32(ptr, value);
#else
Uint32 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)+= value;
privateUnlock();
return tmp;
#endif
}
Uint32
SDL_AtomicFetchThenSubtract32(Uint32 * ptr, Uint32 value)
{
return __sync_fetch_and_sub(ptr, value);
#ifdef nativeFetchThenSubtract32
return nativeFetchThenSubtract32(ptr, value);
#else
Uint32 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)-= value;
privateUnlock();
return tmp;
#endif
}
Uint32
SDL_AtomicIncrementThenFetch32(Uint32 * ptr)
{
return __sync_add_and_fetch(ptr, 1);
#ifdef nativeIncrementThenFetch32
return nativeIncrementThenFetch32(ptr);
#else
Uint32 tmp = 0;;
privateWaitLock();
(*ptr)+= 1;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint32
SDL_AtomicDecrementThenFetch32(Uint32 * ptr)
{
return __sync_sub_and_fetch(ptr, 1);
#ifdef nativeDecrementThenFetch32
return nativeDecrementThenFetch32(ptr);
#else
Uint32 tmp = 0;;
privateWaitLock();
(*ptr)-= 1;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint32
SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 value)
{
return __sync_add_and_fetch(ptr, value);
#ifdef nativeAddThenFetch32
return nativeAddThenFetch32(ptr, value);
#else
Uint32 tmp = 0;;
privateWaitLock();
(*ptr)+= value;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint32
SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value)
{
return __sync_sub_and_fetch(ptr, value);
#ifdef nativeSubtractThenFetch32
return nativeSubtractThenFetch32(ptr, value);
#else
Uint32 tmp = 0;;
privateWaitLock();
(*ptr)-= value;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
/* #ifdef SDL_HAS_64BIT_TYPE */
#if 0
/* 64 bit atomic operations */
#ifdef SDL_HAS_64BIT_TYPE
Uint64
SDL_AtomicExchange64(Uint64 * ptr, Uint64 value)
{
return __sync_lock_test_and_set(ptr, value);
#ifdef nativeExchange64
return nativeExchange64(ptr, value);
#else
Uint64 tmp = 0;;
privateWaitLock();
tmp = *ptr;
*ptr = value;
privateUnlock();
return tmp;
#endif
}
SDL_bool
SDL_AtomicCompareThenSet64(Uint64 * ptr, Uint64 oldvalue, Uint64 newvalue)
{
return (SDL_bool)__sync_bool_compare_and_swap(ptr, oldvalue, newvalue);
#ifdef nativeCompareThenSet64
return (SDL_bool)nativeCompareThenSet64(ptr, oldvalue, newvalue);
#else
SDL_bool result = SDL_FALSE;
privateWaitLock();
result = (*ptr == oldvalue);
if (result)
{
*ptr = newvalue;
}
privateUnlock();
return result;
#endif
}
SDL_bool
SDL_AtomicTestThenSet64(Uint64 * ptr)
{
return (SDL_bool)(0 == __sync_lock_test_and_set(ptr, 1));
#ifdef nativeTestThenSet64
return (SDL_bool)nativeTestThenSet64(ptr);
#else
SDL_bool result = SDL_FALSE;
privateWaitLock();
result = (*ptr == 0);
if (result)
{
*ptr = 1;
}
privateUnlock();
return result;
#endif
}
void
SDL_AtomicClear64(Uint64 * ptr)
{
__sync_lock_release(ptr);
#ifdef nativeClear64
nativeClear64(ptr);
#else
privateWaitLock();
*ptr = 0;
privateUnlock();
return;
#endif
}
Uint64
SDL_AtomicFetchThenIncrement64(Uint64 * ptr)
{
return __sync_fetch_and_add(ptr, 1);
#ifdef nativeFetchThenIncrement64
return nativeFetchThenIncrement64(ptr);
#else
Uint64 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)+= 1;
privateUnlock();
return tmp;
#endif
}
Uint64
SDL_AtomicFetchThenDecrement64(Uint64 * ptr)
{
return __sync_fetch_and_sub(ptr, 1);
#ifdef nativeFetchThenDecrement64
return nativeFetchThenDecrement64(ptr);
#else
Uint64 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr) -= 1;
privateUnlock();
return tmp;
#endif
}
Uint64
SDL_AtomicFetchThenAdd64(Uint64 * ptr, Uint64 value)
{
return __sync_fetch_and_add(ptr, value);
#ifdef nativeFetchThenAdd64
return nativeFetchThenAdd64(ptr, value);
#else
Uint64 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)+= value;
privateUnlock();
return tmp;
#endif
}
Uint64
SDL_AtomicFetchThenSubtract64(Uint64 * ptr, Uint64 value)
{
return __sync_fetch_and_sub(ptr, value);
#ifdef nativeFetchThenSubtract64
return nativeFetchThenSubtract64(ptr, value);
#else
Uint64 tmp = 0;;
privateWaitLock();
tmp = *ptr;
(*ptr)-= value;
privateUnlock();
return tmp;
#endif
}
Uint64
SDL_AtomicIncrementThenFetch64(Uint64 * ptr)
{
return __sync_add_and_fetch(ptr, 1);
#ifdef nativeIncrementThenFetch64
return nativeIncrementThenFetch64(ptr);
#else
Uint64 tmp = 0;;
privateWaitLock();
(*ptr)+= 1;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint64
SDL_AtomicDecrementThenFetch64(Uint64 * ptr)
{
return __sync_sub_and_fetch(ptr, 1);
#ifdef nativeDecrementThenFetch64
return nativeDecrementThenFetch64(ptr);
#else
Uint64 tmp = 0;;
privateWaitLock();
(*ptr)-= 1;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint64
SDL_AtomicAddThenFetch64(Uint64 * ptr, Uint64 value)
{
return __sync_add_and_fetch(ptr, value);
#ifdef nativeAddThenFetch64
return nativeAddThenFetch64(ptr, value);
#else
Uint64 tmp = 0;;
privateWaitLock();
(*ptr)+= value;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
Uint64
SDL_AtomicSubtractThenFetch64(Uint64 * ptr, Uint64 value)
{
return __sync_sub_and_fetch(ptr, value);
#ifdef nativeSubtractThenFetch64
return nativeSubtractThenFetch64(ptr, value);
#else
Uint64 tmp = 0;;
privateWaitLock();
(*ptr)-= value;
tmp = *ptr;
privateUnlock();
return tmp;
#endif
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,50 +1,232 @@
#include "SDL.h"
/*
Absolutely basic test just to see if we get the expected value after
calling each function.
Absolutely basic tests just to see if we get the expected value
after calling each function.
*/
char *
tf(SDL_bool tf)
{
static char *t = "true";
static char *f = "false";
if (tf)
{
return t;
}
return f;
}
int
main(int argc, char **argv)
{
Uint8 val8 = 0;
Uint8 ret8 = 0;
Uint16 val16 = 0;
Uint16 ret16 = 0;
Uint32 val32 = 0;
Uint32 ret32 = 0;
Uint64 val64 = 0;
Uint64 ret64 = 0;
SDL_bool tfval = SDL_FALSE;
SDL_bool tfret = SDL_FALSE;
printf("8 bit -----------------------------------------\n\n");
ret8 = SDL_AtomicExchange8(&val8, 10);
printf("Exchange8 ret=%d val=%d\n", ret8, val8);
ret8 = SDL_AtomicExchange8(&val8, 0);
printf("Exchange8 ret=%d val=%d\n", ret8, val8);
val8 = 10;
tfret = SDL_AtomicCompareThenSet8(&val8, 10, 20);
printf("CompareThenSet8 tfret=%s val=%d\n", tf(tfret), val8);
val8 = 10;
tfret = SDL_AtomicCompareThenSet8(&val8, 0, 20);
printf("CompareThenSet8 tfret=%s val=%d\n", tf(tfret), val8);
val8 = 0;
tfret = SDL_AtomicTestThenSet8(&val8);
printf("TestThenSet8 tfret=%s val=%d\n", tf(tfret), val8);
tfret = SDL_AtomicTestThenSet8(&val8);
printf("TestThenSet8 tfret=%s val=%d\n", tf(tfret), val8);
SDL_AtomicClear8(&val8);
printf("Clear8 val=%d\n", val8);
ret8 = SDL_AtomicFetchThenIncrement8(&val8);
printf("FetchThenIncrement8 ret=%d val=%d\n", ret8, val8);
ret8 = SDL_AtomicFetchThenDecrement8(&val8);
printf("FetchThenDecrement8 ret=%d val=%d\n", ret8, val8);
ret8 = SDL_AtomicFetchThenAdd8(&val8, 10);
printf("FetchThenAdd8 ret=%d val=%d\n", ret8, val8);
ret8 = SDL_AtomicFetchThenSubtract8(&val8, 10);
printf("FetchThenSubtract8 ret=%d val=%d\n", ret8, val8);
ret8 = SDL_AtomicIncrementThenFetch8(&val8);
printf("IncrementThenFetch8 ret=%d val=%d\n", ret8, val8);
ret8 = SDL_AtomicDecrementThenFetch8(&val8);
printf("DecrementThenFetch8 ret=%d val=%d\n", ret8, val8);
ret8 = SDL_AtomicAddThenFetch8(&val8, 10);
printf("AddThenFetch8 ret=%d val=%d\n", ret8, val8);
ret8 = SDL_AtomicSubtractThenFetch8(&val8, 10);
printf("SubtractThenFetch8 ret=%d val=%d\n", ret8, val8);
printf("16 bit -----------------------------------------\n\n");
ret16 = SDL_AtomicExchange16(&val16, 10);
printf("Exchange16 ret=%d val=%d\n", ret16, val16);
ret16 = SDL_AtomicExchange16(&val16, 0);
printf("Exchange16 ret=%d val=%d\n", ret16, val16);
val16 = 10;
tfret = SDL_AtomicCompareThenSet16(&val16, 10, 20);
printf("CompareThenSet16 tfret=%s val=%d\n", tf(tfret), val16);
val16 = 10;
tfret = SDL_AtomicCompareThenSet16(&val16, 0, 20);
printf("CompareThenSet16 tfret=%s val=%d\n", tf(tfret), val16);
val16 = 0;
tfret = SDL_AtomicTestThenSet16(&val16);
printf("TestThenSet16 tfret=%s val=%d\n", tf(tfret), val16);
tfret = SDL_AtomicTestThenSet16(&val16);
printf("TestThenSet16 tfret=%s val=%d\n", tf(tfret), val16);
SDL_AtomicClear16(&val16);
printf("Clear16 val=%d\n", val16);
ret16 = SDL_AtomicFetchThenIncrement16(&val16);
printf("FetchThenIncrement16 ret=%d val=%d\n", ret16, val16);
ret16 = SDL_AtomicFetchThenDecrement16(&val16);
printf("FetchThenDecrement16 ret=%d val=%d\n", ret16, val16);
ret16 = SDL_AtomicFetchThenAdd16(&val16, 10);
printf("FetchThenAdd16 ret=%d val=%d\n", ret16, val16);
ret16 = SDL_AtomicFetchThenSubtract16(&val16, 10);
printf("FetchThenSubtract16 ret=%d val=%d\n", ret16, val16);
ret16 = SDL_AtomicIncrementThenFetch16(&val16);
printf("IncrementThenFetch16 ret=%d val=%d\n", ret16, val16);
ret16 = SDL_AtomicDecrementThenFetch16(&val16);
printf("DecrementThenFetch16 ret=%d val=%d\n", ret16, val16);
ret16 = SDL_AtomicAddThenFetch16(&val16, 10);
printf("AddThenFetch16 ret=%d val=%d\n", ret16, val16);
ret16 = SDL_AtomicSubtractThenFetch16(&val16, 10);
printf("SubtractThenFetch16 ret=%d val=%d\n", ret16, val16);
printf("32 bit -----------------------------------------\n\n");
ret32 = SDL_AtomicExchange32(&val32, 10);
tfval = SDL_AtomicCompareThenSet32(&val32, 10, 20);
tfval = SDL_AtomicTestThenSet32(&val32);
SDL_AtomicClear32(&val32);
ret32 = SDL_AtomicFetchThenIncrement32(&val32);
ret32 = SDL_AtomicFetchThenDecrement32(&val32);
ret32 = SDL_AtomicFetchThenAdd32(&val32, 10);
ret32 = SDL_AtomicFetchThenSubtract32(&val32, 10);
ret32 = SDL_AtomicIncrementThenFetch32(&val32);
ret32 = SDL_AtomicDecrementThenFetch32(&val32);
ret32 = SDL_AtomicAddThenFetch32(&val32, 10);
ret32 = SDL_AtomicSubtractThenFetch32(&val32, 10);
printf("Exchange32 ret=%d val=%d\n", ret32, val32);
ret32 = SDL_AtomicExchange32(&val32, 0);
printf("Exchange32 ret=%d val=%d\n", ret32, val32);
/* #ifdef SDL_HAS_64BIT_TYPE */
#if 0
val32 = 10;
tfret = SDL_AtomicCompareThenSet32(&val32, 10, 20);
printf("CompareThenSet32 tfret=%s val=%d\n", tf(tfret), val32);
val32 = 10;
tfret = SDL_AtomicCompareThenSet32(&val32, 0, 20);
printf("CompareThenSet32 tfret=%s val=%d\n", tf(tfret), val32);
val32 = 0;
tfret = SDL_AtomicTestThenSet32(&val32);
printf("TestThenSet32 tfret=%s val=%d\n", tf(tfret), val32);
tfret = SDL_AtomicTestThenSet32(&val32);
printf("TestThenSet32 tfret=%s val=%d\n", tf(tfret), val32);
SDL_AtomicClear32(&val32);
printf("Clear32 val=%d\n", val32);
ret32 = SDL_AtomicFetchThenIncrement32(&val32);
printf("FetchThenIncrement32 ret=%d val=%d\n", ret32, val32);
ret32 = SDL_AtomicFetchThenDecrement32(&val32);
printf("FetchThenDecrement32 ret=%d val=%d\n", ret32, val32);
ret32 = SDL_AtomicFetchThenAdd32(&val32, 10);
printf("FetchThenAdd32 ret=%d val=%d\n", ret32, val32);
ret32 = SDL_AtomicFetchThenSubtract32(&val32, 10);
printf("FetchThenSubtract32 ret=%d val=%d\n", ret32, val32);
ret32 = SDL_AtomicIncrementThenFetch32(&val32);
printf("IncrementThenFetch32 ret=%d val=%d\n", ret32, val32);
ret32 = SDL_AtomicDecrementThenFetch32(&val32);
printf("DecrementThenFetch32 ret=%d val=%d\n", ret32, val32);
ret32 = SDL_AtomicAddThenFetch32(&val32, 10);
printf("AddThenFetch32 ret=%d val=%d\n", ret32, val32);
ret32 = SDL_AtomicSubtractThenFetch32(&val32, 10);
printf("SubtractThenFetch32 ret=%d val=%d\n", ret32, val32);
#ifdef SDL_HAS_64BIT_TYPE
printf("64 bit -----------------------------------------\n\n");
ret64 = SDL_AtomicExchange64(&val64, 10);
tfval = SDL_AtomicCompareThenSet64(&val64, 10, 20);
tfval = SDL_AtomicTestThenSet64(&val64);
printf("Exchange64 ret=%lld val=%lld\n", ret64, val64);
ret64 = SDL_AtomicExchange64(&val64, 0);
printf("Exchange64 ret=%lld val=%lld\n", ret64, val64);
val64 = 10;
tfret = SDL_AtomicCompareThenSet64(&val64, 10, 20);
printf("CompareThenSet64 tfret=%s val=%lld\n", tf(tfret), val64);
val64 = 10;
tfret = SDL_AtomicCompareThenSet64(&val64, 0, 20);
printf("CompareThenSet64 tfret=%s val=%lld\n", tf(tfret), val64);
val64 = 0;
tfret = SDL_AtomicTestThenSet64(&val64);
printf("TestThenSet64 tfret=%s val=%lld\n", tf(tfret), val64);
tfret = SDL_AtomicTestThenSet64(&val64);
printf("TestThenSet64 tfret=%s val=%lld\n", tf(tfret), val64);
SDL_AtomicClear64(&val64);
printf("Clear64 val=%lld\n", val64);
ret64 = SDL_AtomicFetchThenIncrement64(&val64);
printf("FetchThenIncrement64 ret=%lld val=%lld\n", ret64, val64);
ret64 = SDL_AtomicFetchThenDecrement64(&val64);
printf("FetchThenDecrement64 ret=%lld val=%lld\n", ret64, val64);
ret64 = SDL_AtomicFetchThenAdd64(&val64, 10);
printf("FetchThenAdd64 ret=%lld val=%lld\n", ret64, val64);
ret64 = SDL_AtomicFetchThenSubtract64(&val64, 10);
printf("FetchThenSubtract64 ret=%lld val=%lld\n", ret64, val64);
ret64 = SDL_AtomicIncrementThenFetch64(&val64);
printf("IncrementThenFetch64 ret=%lld val=%lld\n", ret64, val64);
ret64 = SDL_AtomicDecrementThenFetch64(&val64);
printf("DecrementThenFetch64 ret=%lld val=%lld\n", ret64, val64);
ret64 = SDL_AtomicAddThenFetch64(&val64, 10);
printf("AddThenFetch64 ret=%lld val=%lld\n", ret64, val64);
ret64 = SDL_AtomicSubtractThenFetch64(&val64, 10);
printf("SubtractThenFetch64 ret=%lld val=%lld\n", ret64, val64);
#endif
return 0;