Changed directory structure to contain less symlinks so dependencies will get recalculated correctly by make
This commit is contained in:
469
project/jni/sdl-1.3/src/atomic/dummy/SDL_atomic.c
Normal file
469
project/jni/sdl-1.3/src/atomic/dummy/SDL_atomic.c
Normal file
@@ -0,0 +1,469 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2010 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
|
||||
|
||||
Contributed by Bob Pendleton, bob@pendleton.com
|
||||
*/
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_atomic.h"
|
||||
|
||||
#include "SDL_error.h"
|
||||
|
||||
/*
|
||||
This file provides 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 spin lock operations. If spin lock can not be
|
||||
implemented then these functions must fail.
|
||||
*/
|
||||
|
||||
/*
|
||||
DUMMY VERSION.
|
||||
|
||||
This version of the code assumes there is no support for atomic
|
||||
operations. Therefore, every function sets the SDL error
|
||||
message. Oddly enough, if you only have one thread then this
|
||||
version actuallys works.
|
||||
*/
|
||||
|
||||
/*
|
||||
Native spinlock routines. Because this is the dummy implementation
|
||||
these will always call SDL_SetError() and do nothing.
|
||||
*/
|
||||
|
||||
void
|
||||
SDL_AtomicLock(SDL_SpinLock *lock)
|
||||
{
|
||||
SDL_SetError("SDL_atomic.c: is not implemented on this platform");
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicUnlock(SDL_SpinLock *lock)
|
||||
{
|
||||
SDL_SetError("SDL_atomic.c: is not implemented on this platform");
|
||||
}
|
||||
|
||||
/*
|
||||
Note that platform specific versions can be built from this version
|
||||
by changing the #undefs to #defines and adding platform specific
|
||||
code.
|
||||
*/
|
||||
|
||||
#undef nativeTestThenSet32
|
||||
#undef nativeClear32
|
||||
#undef nativeFetchThenIncrement32
|
||||
#undef nativeFetchThenDecrement32
|
||||
#undef nativeFetchThenAdd32
|
||||
#undef nativeFetchThenSubtract32
|
||||
#undef nativeIncrementThenFetch32
|
||||
#undef nativeDecrementThenFetch32
|
||||
#undef nativeAddThenFetch32
|
||||
#undef nativeSubtractThenFetch32
|
||||
|
||||
#undef nativeTestThenSet64
|
||||
#undef nativeClear64
|
||||
#undef nativeFetchThenIncrement64
|
||||
#undef nativeFetchThenDecrement64
|
||||
#undef nativeFetchThenAdd64
|
||||
#undef nativeFetchThenSubtract64
|
||||
#undef nativeIncrementThenFetch64
|
||||
#undef nativeDecrementThenFetch64
|
||||
#undef nativeAddThenFetch64
|
||||
#undef nativeSubtractThenFetch64
|
||||
|
||||
/*
|
||||
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
|
||||
that avoids the "one big lock" problem. We use a vector of spin
|
||||
locks and pick which one to use based on the address of the operand
|
||||
of the function.
|
||||
|
||||
To generate the index of the lock we first shift by 3 bits to get
|
||||
rid on the zero bits that result from 32 and 64 bit allignment of
|
||||
data. We then mask off all but 5 bits and use those 5 bits as an
|
||||
index into the table.
|
||||
|
||||
Picking the lock this way insures that accesses to the same data at
|
||||
the same time will go to the same lock. OTOH, accesses to different
|
||||
data have only a 1/32 chance of hitting the same lock. That should
|
||||
pretty much eliminate the chances of several atomic operations on
|
||||
different data from waiting on the same "big lock". If it isn't
|
||||
then the table of locks can be expanded to a new size so long as
|
||||
the new size is a power of two.
|
||||
*/
|
||||
|
||||
static SDL_SpinLock locks[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static __inline__ void
|
||||
privateWaitLock(volatile void *ptr)
|
||||
{
|
||||
#if SIZEOF_VOIDP == 4
|
||||
Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f);
|
||||
#endif
|
||||
|
||||
SDL_AtomicLock(&locks[index]);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
privateUnlock(volatile void *ptr)
|
||||
{
|
||||
#if SIZEOF_VOIDP == 4
|
||||
Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f);
|
||||
#endif
|
||||
|
||||
SDL_AtomicUnlock(&locks[index]);
|
||||
}
|
||||
|
||||
/* 32 bit atomic operations */
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicTestThenSet32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeTestThenSet32
|
||||
#else
|
||||
SDL_bool result = SDL_FALSE;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
result = (*ptr == 0);
|
||||
if (result)
|
||||
{
|
||||
*ptr = 1;
|
||||
}
|
||||
privateUnlock(ptr);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicClear32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeClear32
|
||||
#else
|
||||
privateWaitLock(ptr);
|
||||
*ptr = 0;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenIncrement32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenDecrement32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr) -= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeFetchThenAdd32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeFetchThenSubtract32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)-= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeIncrementThenFetch32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeDecrementThenFetch32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeAddThenFetch32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeSubtractThenFetch32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 64 bit atomic operations */
|
||||
#ifdef SDL_HAS_64BIT_TYPE
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicTestThenSet64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeTestThenSet64
|
||||
#else
|
||||
SDL_bool result = SDL_FALSE;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
result = (*ptr == 0);
|
||||
if (result)
|
||||
{
|
||||
*ptr = 1;
|
||||
}
|
||||
privateUnlock(ptr);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicClear64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeClear64
|
||||
#else
|
||||
privateWaitLock(ptr);
|
||||
*ptr = 0;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenIncrement64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenDecrement64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr) -= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeFetchThenAdd64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeFetchThenSubtract64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)-= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeIncrementThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeDecrementThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeAddThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeSubtractThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
510
project/jni/sdl-1.3/src/atomic/linux/SDL_atomic.c
Normal file
510
project/jni/sdl-1.3/src/atomic/linux/SDL_atomic.c
Normal file
@@ -0,0 +1,510 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2010 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
|
||||
|
||||
Contributed by Bob Pendleton, bob@pendleton.com
|
||||
*/
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_atomic.h"
|
||||
|
||||
#include "SDL_error.h"
|
||||
|
||||
/*
|
||||
This file provides 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 spin lock operations. If spin lock can not be
|
||||
implemented then these functions must fail.
|
||||
*/
|
||||
|
||||
/*
|
||||
LINUX/GCC VERSION.
|
||||
|
||||
This version of the code assumes support of the atomic builtins as
|
||||
documented at gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html This
|
||||
code should work on any modern x86 or other processor supported by
|
||||
GCC.
|
||||
|
||||
Some processors will only support some of these operations so
|
||||
#ifdefs will have to be added as incompatibilities are discovered
|
||||
*/
|
||||
|
||||
/*
|
||||
Native spinlock routines.
|
||||
*/
|
||||
|
||||
void
|
||||
SDL_AtomicLock(SDL_SpinLock *lock)
|
||||
{
|
||||
while (0 != __sync_lock_test_and_set(lock, 1))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicUnlock(SDL_SpinLock *lock)
|
||||
{
|
||||
__sync_lock_test_and_set(lock, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
Note that platform specific versions can be built from this version
|
||||
by changing the #undefs to #defines and adding platform specific
|
||||
code.
|
||||
*/
|
||||
|
||||
#define nativeTestThenSet32
|
||||
#define nativeClear32
|
||||
#define nativeFetchThenIncrement32
|
||||
#define nativeFetchThenDecrement32
|
||||
#define nativeFetchThenAdd32
|
||||
#define nativeFetchThenSubtract32
|
||||
#define nativeIncrementThenFetch32
|
||||
#define nativeDecrementThenFetch32
|
||||
#define nativeAddThenFetch32
|
||||
#define nativeSubtractThenFetch32
|
||||
|
||||
#ifdef SDL_HAS_64BIT_TYPE
|
||||
#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
|
||||
#define nativeTestThenSet64
|
||||
#define nativeClear64
|
||||
#define nativeFetchThenIncrement64
|
||||
#define nativeFetchThenDecrement64
|
||||
#define nativeFetchThenAdd64
|
||||
#define nativeFetchThenSubtract64
|
||||
#define nativeIncrementThenFetch64
|
||||
#define nativeDecrementThenFetch64
|
||||
#define nativeAddThenFetch64
|
||||
#define nativeSubtractThenFetch64
|
||||
#else
|
||||
#undef nativeTestThenSet64
|
||||
#undef nativeClear64
|
||||
#undef nativeFetchThenIncrement64
|
||||
#undef nativeFetchThenDecrement64
|
||||
#undef nativeFetchThenAdd64
|
||||
#undef nativeFetchThenSubtract64
|
||||
#undef nativeIncrementThenFetch64
|
||||
#undef nativeDecrementThenFetch64
|
||||
#undef nativeAddThenFetch64
|
||||
#undef nativeSubtractThenFetch64
|
||||
#endif /* __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 */
|
||||
#endif /* SDL_HAS_64BIT_TYPE */
|
||||
|
||||
/*
|
||||
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
|
||||
that avoids the "one big lock" problem. We use a vector of spin
|
||||
locks and pick which one to use based on the address of the operand
|
||||
of the function.
|
||||
|
||||
To generate the index of the lock we first shift by 3 bits to get
|
||||
rid on the zero bits that result from 32 and 64 bit allignment of
|
||||
data. We then mask off all but 5 bits and use those 5 bits as an
|
||||
index into the table.
|
||||
|
||||
Picking the lock this way insures that accesses to the same data at
|
||||
the same time will go to the same lock. OTOH, accesses to different
|
||||
data have only a 1/32 chance of hitting the same lock. That should
|
||||
pretty much eliminate the chances of several atomic operations on
|
||||
different data from waiting on the same "big lock". If it isn't
|
||||
then the table of locks can be expanded to a new size so long as
|
||||
the new size is a power of two.
|
||||
*/
|
||||
|
||||
static SDL_SpinLock locks[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static __inline__ void
|
||||
privateWaitLock(volatile void *ptr)
|
||||
{
|
||||
#if SIZEOF_VOIDP == 4
|
||||
Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f);
|
||||
#endif
|
||||
|
||||
SDL_AtomicLock(&locks[index]);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
privateUnlock(volatile void *ptr)
|
||||
{
|
||||
#if SIZEOF_VOIDP == 4
|
||||
Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f);
|
||||
#endif
|
||||
|
||||
SDL_AtomicUnlock(&locks[index]);
|
||||
}
|
||||
|
||||
/* 32 bit atomic operations */
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicTestThenSet32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeTestThenSet32
|
||||
return 0 == __sync_lock_test_and_set(ptr, 1);
|
||||
#else
|
||||
SDL_bool result = SDL_FALSE;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
result = (*ptr == 0);
|
||||
if (result)
|
||||
{
|
||||
*ptr = 1;
|
||||
}
|
||||
privateUnlock(ptr);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicClear32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeClear32
|
||||
__sync_lock_test_and_set(ptr, 0);
|
||||
return;
|
||||
#else
|
||||
privateWaitLock(ptr);
|
||||
*ptr = 0;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenIncrement32
|
||||
return __sync_fetch_and_add(ptr, 1);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenDecrement32
|
||||
return __sync_fetch_and_sub(ptr, 1);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr) -= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeFetchThenAdd32
|
||||
return __sync_fetch_and_add(ptr, value);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeFetchThenSubtract32
|
||||
return __sync_fetch_and_sub(ptr, value);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)-= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeIncrementThenFetch32
|
||||
return __sync_add_and_fetch(ptr, 1);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeDecrementThenFetch32
|
||||
return __sync_sub_and_fetch(ptr, 1);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeAddThenFetch32
|
||||
return __sync_add_and_fetch(ptr, value);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeSubtractThenFetch32
|
||||
return __sync_sub_and_fetch(ptr, value);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 64 bit atomic operations */
|
||||
#ifdef SDL_HAS_64BIT_TYPE
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicTestThenSet64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeTestThenSet64
|
||||
return 0 == __sync_lock_test_and_set(ptr, 1);
|
||||
#else
|
||||
SDL_bool result = SDL_FALSE;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
result = (*ptr == 0);
|
||||
if (result)
|
||||
{
|
||||
*ptr = 1;
|
||||
}
|
||||
privateUnlock(ptr);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicClear64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeClear64
|
||||
__sync_lock_test_and_set(ptr, 0);
|
||||
return;
|
||||
#else
|
||||
privateWaitLock(ptr);
|
||||
*ptr = 0;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenIncrement64
|
||||
return __sync_fetch_and_add(ptr, 1);
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenDecrement64
|
||||
return __sync_fetch_and_sub(ptr, 1);
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr) -= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeFetchThenAdd64
|
||||
return __sync_fetch_and_add(ptr, value);
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeFetchThenSubtract64
|
||||
return __sync_fetch_and_sub(ptr, value);
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)-= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeIncrementThenFetch64
|
||||
return __sync_add_and_fetch(ptr, 1);
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeDecrementThenFetch64
|
||||
return __sync_sub_and_fetch(ptr, 1);
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeAddThenFetch64
|
||||
return __sync_add_and_fetch(ptr, value);
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeSubtractThenFetch64
|
||||
return __sync_sub_and_fetch(ptr, value);
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* SDL_HAS_64BIT_TYPE */
|
||||
469
project/jni/sdl-1.3/src/atomic/macosx/SDL_atomic.c
Normal file
469
project/jni/sdl-1.3/src/atomic/macosx/SDL_atomic.c
Normal file
@@ -0,0 +1,469 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2010 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
|
||||
|
||||
Contributed by Bob Pendleton, bob@pendleton.com
|
||||
*/
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_atomic.h"
|
||||
|
||||
#include "SDL_error.h"
|
||||
|
||||
/*
|
||||
This file provides 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 spin lock operations. If spin lock can not be
|
||||
implemented then these functions must fail.
|
||||
*/
|
||||
|
||||
/*
|
||||
DUMMY VERSION.
|
||||
|
||||
This version of the code assumes there is no support for atomic
|
||||
operations. Therefore, every function sets the SDL error
|
||||
message. Oddly enough, if you only have one thread then this
|
||||
version actuallys works.
|
||||
*/
|
||||
|
||||
/*
|
||||
Native spinlock routines. Because this is the dummy implementation
|
||||
these will always call SDL_SetError() and do nothing.
|
||||
*/
|
||||
|
||||
void
|
||||
SDL_AtomicLock(SDL_SpinLock *lock)
|
||||
{
|
||||
SDL_SetError("SDL_atomic.c: is not implemented on this platform");
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicUnlock(SDL_SpinLock *lock)
|
||||
{
|
||||
SDL_SetError("SDL_atomic.c: is not implemented on this platform");
|
||||
}
|
||||
|
||||
/*
|
||||
Note that platform specific versions can be built from this version
|
||||
by changing the #undefs to #defines and adding platform specific
|
||||
code.
|
||||
*/
|
||||
|
||||
#undef nativeTestThenSet32
|
||||
#undef nativeClear32
|
||||
#undef nativeFetchThenIncrement32
|
||||
#undef nativeFetchThenDecrement32
|
||||
#undef nativeFetchThenAdd32
|
||||
#undef nativeFetchThenSubtract32
|
||||
#undef nativeIncrementThenFetch32
|
||||
#undef nativeDecrementThenFetch32
|
||||
#undef nativeAddThenFetch32
|
||||
#undef nativeSubtractThenFetch32
|
||||
|
||||
#undef nativeTestThenSet64
|
||||
#undef nativeClear64
|
||||
#undef nativeFetchThenIncrement64
|
||||
#undef nativeFetchThenDecrement64
|
||||
#undef nativeFetchThenAdd64
|
||||
#undef nativeFetchThenSubtract64
|
||||
#undef nativeIncrementThenFetch64
|
||||
#undef nativeDecrementThenFetch64
|
||||
#undef nativeAddThenFetch64
|
||||
#undef nativeSubtractThenFetch64
|
||||
|
||||
/*
|
||||
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
|
||||
that avoids the "one big lock" problem. We use a vector of spin
|
||||
locks and pick which one to use based on the address of the operand
|
||||
of the function.
|
||||
|
||||
To generate the index of the lock we first shift by 3 bits to get
|
||||
rid on the zero bits that result from 32 and 64 bit allignment of
|
||||
data. We then mask off all but 5 bits and use those 5 bits as an
|
||||
index into the table.
|
||||
|
||||
Picking the lock this way insures that accesses to the same data at
|
||||
the same time will go to the same lock. OTOH, accesses to different
|
||||
data have only a 1/32 chance of hitting the same lock. That should
|
||||
pretty much eliminate the chances of several atomic operations on
|
||||
different data from waiting on the same "big lock". If it isn't
|
||||
then the table of locks can be expanded to a new size so long as
|
||||
the new size is a power of two.
|
||||
*/
|
||||
|
||||
static SDL_SpinLock locks[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static __inline__ void
|
||||
privateWaitLock(volatile void *ptr)
|
||||
{
|
||||
#if SIZEOF_VOIDP == 4
|
||||
Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f);
|
||||
#endif
|
||||
|
||||
SDL_AtomicLock(&locks[index]);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
privateUnlock(volatile void *ptr)
|
||||
{
|
||||
#if SIZEOF_VOIDP == 4
|
||||
Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f);
|
||||
#endif
|
||||
|
||||
SDL_AtomicUnlock(&locks[index]);
|
||||
}
|
||||
|
||||
/* 32 bit atomic operations */
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicTestThenSet32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeTestThenSet32
|
||||
#else
|
||||
SDL_bool result = SDL_FALSE;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
result = (*ptr == 0);
|
||||
if (result)
|
||||
{
|
||||
*ptr = 1;
|
||||
}
|
||||
privateUnlock(ptr);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicClear32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeClear32
|
||||
#else
|
||||
privateWaitLock(ptr);
|
||||
*ptr = 0;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenIncrement32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenDecrement32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr) -= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeFetchThenAdd32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeFetchThenSubtract32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)-= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeIncrementThenFetch32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeDecrementThenFetch32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeAddThenFetch32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeSubtractThenFetch32
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 64 bit atomic operations */
|
||||
#ifdef SDL_HAS_64BIT_TYPE
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicTestThenSet64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeTestThenSet64
|
||||
#else
|
||||
SDL_bool result = SDL_FALSE;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
result = (*ptr == 0);
|
||||
if (result)
|
||||
{
|
||||
*ptr = 1;
|
||||
}
|
||||
privateUnlock(ptr);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicClear64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeClear64
|
||||
#else
|
||||
privateWaitLock(ptr);
|
||||
*ptr = 0;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenIncrement64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenDecrement64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr) -= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeFetchThenAdd64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeFetchThenSubtract64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)-= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeIncrementThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeDecrementThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeAddThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeSubtractThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
505
project/jni/sdl-1.3/src/atomic/qnx/SDL_atomic.c
Normal file
505
project/jni/sdl-1.3/src/atomic/qnx/SDL_atomic.c
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2010 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
|
||||
|
||||
QNX native atomic operations
|
||||
Copyright (C) 2009 Mike Gorchak
|
||||
(mike@malva.ua, lestat@i.com.ua)
|
||||
*/
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_atomic.h"
|
||||
#include "SDL_error.h"
|
||||
|
||||
#include <atomic.h>
|
||||
|
||||
/* SMP Exchange for PPC platform */
|
||||
#ifdef __PPC__
|
||||
#include <ppc/smpxchg.h>
|
||||
#endif /* __PPC__ */
|
||||
|
||||
/* SMP Exchange for ARM platform */
|
||||
#ifdef __ARM__
|
||||
#include <arm/smpxchg.h>
|
||||
#endif /* __ARM__ */
|
||||
|
||||
/* SMP Exchange for MIPS platform */
|
||||
#if defined (__MIPSEB__) || defined(__MIPSEL__)
|
||||
#include <mips/smpxchg.h>
|
||||
#endif /* __MIPSEB__ || __MIPSEL__ */
|
||||
|
||||
/* SMP Exchange for SH platform */
|
||||
#ifdef __SH__
|
||||
#include <sh/smpxchg.h>
|
||||
#endif /* __SH__ */
|
||||
|
||||
/* SMP Exchange for x86 platform */
|
||||
#ifdef __X86__
|
||||
#include <x86/smpxchg.h>
|
||||
#endif /* __X86__ */
|
||||
|
||||
/*
|
||||
This file provides 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 spin lock operations. If spin lock can not be
|
||||
implemented then these functions must fail.
|
||||
*/
|
||||
|
||||
void
|
||||
SDL_AtomicLock(SDL_SpinLock *lock)
|
||||
{
|
||||
unsigned volatile* l = (unsigned volatile*)lock;
|
||||
Uint32 oldval = 0;
|
||||
Uint32 newval = 1;
|
||||
|
||||
oldval = _smp_xchg(l, newval);
|
||||
while(1 == oldval)
|
||||
{
|
||||
oldval = _smp_xchg(l, newval);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicUnlock(SDL_SpinLock *lock)
|
||||
{
|
||||
unsigned volatile* l = (unsigned volatile*)lock;
|
||||
Uint32 newval = 0;
|
||||
|
||||
_smp_xchg(l, newval);
|
||||
}
|
||||
|
||||
/*
|
||||
QNX 6.4.1 supports only 32 bit atomic access
|
||||
*/
|
||||
|
||||
#undef nativeTestThenSet32
|
||||
#define nativeClear32
|
||||
#define nativeFetchThenIncrement32
|
||||
#define nativeFetchThenDecrement32
|
||||
#define nativeFetchThenAdd32
|
||||
#define nativeFetchThenSubtract32
|
||||
#define nativeIncrementThenFetch32
|
||||
#define nativeDecrementThenFetch32
|
||||
#define nativeAddThenFetch32
|
||||
#define nativeSubtractThenFetch32
|
||||
|
||||
#undef nativeTestThenSet64
|
||||
#undef nativeClear64
|
||||
#undef nativeFetchThenIncrement64
|
||||
#undef nativeFetchThenDecrement64
|
||||
#undef nativeFetchThenAdd64
|
||||
#undef nativeFetchThenSubtract64
|
||||
#undef nativeIncrementThenFetch64
|
||||
#undef nativeDecrementThenFetch64
|
||||
#undef nativeAddThenFetch64
|
||||
#undef nativeSubtractThenFetch64
|
||||
|
||||
/*
|
||||
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
|
||||
that avoids the "one big lock" problem. We use a vector of spin
|
||||
locks and pick which one to use based on the address of the operand
|
||||
of the function.
|
||||
|
||||
To generate the index of the lock we first shift by 3 bits to get
|
||||
rid on the zero bits that result from 32 and 64 bit allignment of
|
||||
data. We then mask off all but 5 bits and use those 5 bits as an
|
||||
index into the table.
|
||||
|
||||
Picking the lock this way insures that accesses to the same data at
|
||||
the same time will go to the same lock. OTOH, accesses to different
|
||||
data have only a 1/32 chance of hitting the same lock. That should
|
||||
pretty much eliminate the chances of several atomic operations on
|
||||
different data from waiting on the same "big lock". If it isn't
|
||||
then the table of locks can be expanded to a new size so long as
|
||||
the new size is a power of two.
|
||||
*/
|
||||
|
||||
static SDL_SpinLock locks[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static __inline__ void
|
||||
privateWaitLock(volatile void *ptr)
|
||||
{
|
||||
#if SIZEOF_VOIDP == 4
|
||||
Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f);
|
||||
#endif /* SIZEOF_VOIDP */
|
||||
|
||||
SDL_AtomicLock(&locks[index]);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
privateUnlock(volatile void *ptr)
|
||||
{
|
||||
#if SIZEOF_VOIDP == 4
|
||||
Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f);
|
||||
#endif /* SIZEOF_VOIDP */
|
||||
|
||||
SDL_AtomicUnlock(&locks[index]);
|
||||
}
|
||||
|
||||
/* 32 bit atomic operations */
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicTestThenSet32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeTestThenSet32
|
||||
#else
|
||||
SDL_bool result = SDL_FALSE;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
result = (*ptr == 0);
|
||||
if (result)
|
||||
{
|
||||
*ptr = 1;
|
||||
}
|
||||
privateUnlock(ptr);
|
||||
|
||||
return result;
|
||||
#endif /* nativeTestThenSet32 */
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicClear32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeClear32
|
||||
atomic_clr(ptr, 0xFFFFFFFF);
|
||||
#else
|
||||
privateWaitLock(ptr);
|
||||
*ptr = 0;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return;
|
||||
#endif /* nativeClear32 */
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenIncrement32
|
||||
return atomic_add_value(ptr, 0x00000001);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeFetchThenIncrement32 */
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenDecrement32
|
||||
return atomic_sub_value(ptr, 0x00000001);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr) -= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeFetchThenDecrement32 */
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeFetchThenAdd32
|
||||
return atomic_add_value(ptr, value);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeFetchThenAdd32 */
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeFetchThenSubtract32
|
||||
return atomic_sub_value(ptr, value);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)-= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeFetchThenSubtract32 */
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeIncrementThenFetch32
|
||||
atomic_add(ptr, 0x00000001);
|
||||
return atomic_add_value(ptr, 0x00000000);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeIncrementThenFetch32 */
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeDecrementThenFetch32
|
||||
atomic_sub(ptr, 0x00000001);
|
||||
return atomic_sub_value(ptr, 0x00000000);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeDecrementThenFetch32 */
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeAddThenFetch32
|
||||
atomic_add(ptr, value);
|
||||
return atomic_add_value(ptr, 0x00000000);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeAddThenFetch32 */
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeSubtractThenFetch32
|
||||
atomic_sub(ptr, value);
|
||||
return atomic_sub_value(ptr, 0x00000000);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeSubtractThenFetch32 */
|
||||
}
|
||||
|
||||
/* 64 bit atomic operations */
|
||||
#ifdef SDL_HAS_64BIT_TYPE
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicTestThenSet64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeTestThenSet64
|
||||
#else
|
||||
SDL_bool result = SDL_FALSE;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
result = (*ptr == 0);
|
||||
if (result)
|
||||
{
|
||||
*ptr = 1;
|
||||
}
|
||||
privateUnlock(ptr);
|
||||
|
||||
return result;
|
||||
#endif /* nativeTestThenSet64 */
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicClear64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeClear64
|
||||
#else
|
||||
privateWaitLock(ptr);
|
||||
*ptr = 0;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return;
|
||||
#endif /* nativeClear64 */
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenIncrement64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeFetchThenIncrement64 */
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenDecrement64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr) -= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeFetchThenDecrement64 */
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeFetchThenAdd64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeFetchThenAdd64 */
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeFetchThenSubtract64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)-= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeFetchThenSubtract64 */
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeIncrementThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeIncrementThenFetch64 */
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeDecrementThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeDecrementThenFetch64 */
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeAddThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeAddThenFetch64 */
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeSubtractThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif /* nativeSubtractThenFetch64 */
|
||||
}
|
||||
|
||||
#endif /* SDL_HAS_64BIT_TYPE */
|
||||
512
project/jni/sdl-1.3/src/atomic/win32/SDL_atomic.c
Normal file
512
project/jni/sdl-1.3/src/atomic/win32/SDL_atomic.c
Normal file
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2010 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
|
||||
|
||||
Contributed by Bob Pendleton, bob@pendleton.com
|
||||
*/
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_atomic.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include "SDL_error.h"
|
||||
|
||||
/*
|
||||
This file provides 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 spin lock operations. If spin lock can not be
|
||||
implemented then these functions must fail.
|
||||
*/
|
||||
|
||||
/*
|
||||
WIN32 VERSION.
|
||||
|
||||
This makes use of native Windows atomic operations.
|
||||
*/
|
||||
|
||||
/*
|
||||
Native spinlock routines. Because this is the dummy implementation
|
||||
these will always call SDL_SetError() and do nothing.
|
||||
*/
|
||||
|
||||
void
|
||||
SDL_AtomicLock(SDL_SpinLock *lock)
|
||||
{
|
||||
long volatile * l = (long volatile *)lock;
|
||||
Uint32 old = 0;
|
||||
Uint32 new = 1;
|
||||
|
||||
old = InterlockedExchange(l, new);
|
||||
while(1 == old)
|
||||
{
|
||||
old = InterlockedExchange(l, new);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicUnlock(SDL_SpinLock *lock)
|
||||
{
|
||||
long volatile * l = (long volatile *)lock;
|
||||
Uint32 new = 0;
|
||||
|
||||
InterlockedExchange(l, new);
|
||||
}
|
||||
|
||||
/*
|
||||
Note that platform specific versions can be built from this version
|
||||
by changing the #undefs to #defines and adding platform specific
|
||||
code.
|
||||
*/
|
||||
|
||||
#define nativeTestThenSet32
|
||||
#define nativeClear32
|
||||
#define nativeFetchThenIncrement32
|
||||
#define nativeFetchThenDecrement32
|
||||
#define nativeFetchThenAdd32
|
||||
#define nativeFetchThenSubtract32
|
||||
#define nativeIncrementThenFetch32
|
||||
#define nativeDecrementThenFetch32
|
||||
#define nativeAddThenFetch32
|
||||
#define nativeSubtractThenFetch32
|
||||
|
||||
#undef nativeTestThenSet64
|
||||
#undef nativeClear64
|
||||
#undef nativeFetchThenIncrement64
|
||||
#undef nativeFetchThenDecrement64
|
||||
#undef nativeFetchThenAdd64
|
||||
#undef nativeFetchThenSubtract64
|
||||
#undef nativeIncrementThenFetch64
|
||||
#undef nativeDecrementThenFetch64
|
||||
#undef nativeAddThenFetch64
|
||||
#undef nativeSubtractThenFetch64
|
||||
|
||||
/*
|
||||
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
|
||||
that avoids the "one big lock" problem. We use a vector of spin
|
||||
locks and pick which one to use based on the address of the operand
|
||||
of the function.
|
||||
|
||||
To generate the index of the lock we first shift by 3 bits to get
|
||||
rid on the zero bits that result from 32 and 64 bit allignment of
|
||||
data. We then mask off all but 5 bits and use those 5 bits as an
|
||||
index into the table.
|
||||
|
||||
Picking the lock this way insures that accesses to the same data at
|
||||
the same time will go to the same lock. OTOH, accesses to different
|
||||
data have only a 1/32 chance of hitting the same lock. That should
|
||||
pretty much eliminate the chances of several atomic operations on
|
||||
different data from waiting on the same "big lock". If it isn't
|
||||
then the table of locks can be expanded to a new size so long as
|
||||
the new size is a power of two.
|
||||
*/
|
||||
|
||||
static SDL_SpinLock locks[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static __inline__ void
|
||||
privateWaitLock(volatile void *ptr)
|
||||
{
|
||||
#if SIZEOF_VOIDP == 4
|
||||
Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f);
|
||||
#endif
|
||||
|
||||
SDL_AtomicLock(&locks[index]);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
privateUnlock(volatile void *ptr)
|
||||
{
|
||||
#if SIZEOF_VOIDP == 4
|
||||
Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f);
|
||||
#endif
|
||||
|
||||
SDL_AtomicUnlock(&locks[index]);
|
||||
}
|
||||
|
||||
/* 32 bit atomic operations */
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicTestThenSet32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeTestThenSet32
|
||||
long volatile * p = (long volatile *)ptr;
|
||||
Uint32 new = 1;
|
||||
|
||||
return 0 == InterlockedExchange(p, new);
|
||||
#else
|
||||
SDL_bool result = SDL_FALSE;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
result = (*ptr == 0);
|
||||
if (result)
|
||||
{
|
||||
*ptr = 1;
|
||||
}
|
||||
privateUnlock(ptr);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicClear32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeClear32
|
||||
long volatile * p = (long volatile *)ptr;
|
||||
Uint32 new = 0;
|
||||
|
||||
InterlockedExchange(p, new);
|
||||
#else
|
||||
privateWaitLock(ptr);
|
||||
*ptr = 0;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenIncrement32
|
||||
long volatile * p = (long volatile *)ptr;
|
||||
|
||||
return InterlockedExchangeAdd(p, 1);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenDecrement32
|
||||
long volatile * p = (long volatile *)ptr;
|
||||
|
||||
return InterlockedExchangeAdd(p, -1);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr) -= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeFetchThenAdd32
|
||||
long volatile * p = (long volatile *)ptr;
|
||||
|
||||
return InterlockedExchangeAdd(p, value);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeFetchThenSubtract32
|
||||
long volatile * p = (long volatile *)ptr;
|
||||
|
||||
return InterlockedExchangeAdd(p, (0 - value));
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)-= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeIncrementThenFetch32
|
||||
long volatile * p = (LONG volatile *)ptr;
|
||||
|
||||
return InterlockedIncrement(p);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr)
|
||||
{
|
||||
#ifdef nativeDecrementThenFetch32
|
||||
long volatile * p = (LONG volatile *)ptr;
|
||||
|
||||
return InterlockedDecrement(p);
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeAddThenFetch32
|
||||
long volatile * p = (long volatile *)ptr;
|
||||
|
||||
return InterlockedExchangeAdd(p, value) + value;
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value)
|
||||
{
|
||||
#ifdef nativeSubtractThenFetch32
|
||||
long volatile * p = (long volatile *)ptr;
|
||||
|
||||
return InterlockedExchangeAdd(p, (0 - value)) - value;
|
||||
#else
|
||||
Uint32 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 64 bit atomic operations */
|
||||
#ifdef SDL_HAS_64BIT_TYPE
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicTestThenSet64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeTestThenSet64
|
||||
#else
|
||||
SDL_bool result = SDL_FALSE;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
result = (*ptr == 0);
|
||||
if (result)
|
||||
{
|
||||
*ptr = 1;
|
||||
}
|
||||
privateUnlock(ptr);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicClear64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeClear64
|
||||
#else
|
||||
privateWaitLock(ptr);
|
||||
*ptr = 0;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenIncrement64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeFetchThenDecrement64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr) -= 1;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeFetchThenAdd64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)+= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeFetchThenSubtract64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
tmp = *ptr;
|
||||
(*ptr)-= value;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeIncrementThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr)
|
||||
{
|
||||
#ifdef nativeDecrementThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= 1;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeAddThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)+= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value)
|
||||
{
|
||||
#ifdef nativeSubtractThenFetch64
|
||||
#else
|
||||
Uint64 tmp = 0;
|
||||
|
||||
privateWaitLock(ptr);
|
||||
(*ptr)-= value;
|
||||
tmp = *ptr;
|
||||
privateUnlock(ptr);
|
||||
|
||||
return tmp;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user