src/atomic/SDL_spinlock.c
changeset 8582 c3e9a2b93517
parent 8536 a2be4a225f91
child 8583 fb2933ca805f
     1.1 --- a/src/atomic/SDL_spinlock.c	Tue Mar 04 19:49:11 2014 -0500
     1.2 +++ b/src/atomic/SDL_spinlock.c	Sun Mar 09 11:06:11 2014 -0700
     1.3 @@ -1,126 +1,126 @@
     1.4 -/*
     1.5 -  Simple DirectMedia Layer
     1.6 -  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     1.7 -
     1.8 -  This software is provided 'as-is', without any express or implied
     1.9 -  warranty.  In no event will the authors be held liable for any damages
    1.10 -  arising from the use of this software.
    1.11 -
    1.12 -  Permission is granted to anyone to use this software for any purpose,
    1.13 -  including commercial applications, and to alter it and redistribute it
    1.14 -  freely, subject to the following restrictions:
    1.15 -
    1.16 -  1. The origin of this software must not be misrepresented; you must not
    1.17 -     claim that you wrote the original software. If you use this software
    1.18 -     in a product, an acknowledgment in the product documentation would be
    1.19 -     appreciated but is not required.
    1.20 -  2. Altered source versions must be plainly marked as such, and must not be
    1.21 -     misrepresented as being the original software.
    1.22 -  3. This notice may not be removed or altered from any source distribution.
    1.23 -*/
    1.24 -#include "SDL_config.h"
    1.25 -
    1.26 -#if defined(__WIN32__) || defined(__WINRT__)
    1.27 -#include "../core/windows/SDL_windows.h"
    1.28 -#endif
    1.29 -
    1.30 -#include "SDL_atomic.h"
    1.31 -#include "SDL_mutex.h"
    1.32 -#include "SDL_timer.h"
    1.33 -
    1.34 -
    1.35 -/* This function is where all the magic happens... */
    1.36 -SDL_bool
    1.37 -SDL_AtomicTryLock(SDL_SpinLock *lock)
    1.38 -{
    1.39 -#if SDL_ATOMIC_DISABLED
    1.40 -    /* Terrible terrible damage */
    1.41 -    static SDL_mutex *_spinlock_mutex;
    1.42 -
    1.43 -    if (!_spinlock_mutex) {
    1.44 -        /* Race condition on first lock... */
    1.45 -        _spinlock_mutex = SDL_CreateMutex();
    1.46 -    }
    1.47 -    SDL_LockMutex(_spinlock_mutex);
    1.48 -    if (*lock == 0) {
    1.49 -        *lock = 1;
    1.50 -        SDL_UnlockMutex(_spinlock_mutex);
    1.51 -        return SDL_TRUE;
    1.52 -    } else {
    1.53 -        SDL_UnlockMutex(_spinlock_mutex);
    1.54 -        return SDL_FALSE;
    1.55 -    }
    1.56 -
    1.57 -#elif defined(_MSC_VER)
    1.58 -    SDL_COMPILE_TIME_ASSERT(locksize, sizeof(*lock) == sizeof(long));
    1.59 -    return (InterlockedExchange((long*)lock, 1) == 0);
    1.60 -
    1.61 -#elif HAVE_GCC_ATOMICS || HAVE_GCC_SYNC_LOCK_TEST_AND_SET
    1.62 -    return (__sync_lock_test_and_set(lock, 1) == 0);
    1.63 -
    1.64 -#elif defined(__GNUC__) && defined(__arm__) && \
    1.65 -        (defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || \
    1.66 -         defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5TE__) || \
    1.67 -         defined(__ARM_ARCH_5TEJ__))
    1.68 -    int result;
    1.69 -    __asm__ __volatile__ (
    1.70 -        "swp %0, %1, [%2]\n"
    1.71 -        : "=&r,&r" (result) : "r,0" (1), "r,r" (lock) : "memory");
    1.72 -    return (result == 0);
    1.73 -
    1.74 -#elif defined(__GNUC__) && defined(__arm__)
    1.75 -    int result;
    1.76 -    __asm__ __volatile__ (
    1.77 -        "ldrex %0, [%2]\nteq   %0, #0\nstrexeq %0, %1, [%2]"
    1.78 -        : "=&r" (result) : "r" (1), "r" (lock) : "cc", "memory");
    1.79 -    return (result == 0);
    1.80 -
    1.81 -#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
    1.82 -    int result;
    1.83 -    __asm__ __volatile__(
    1.84 -        "lock ; xchgl %0, (%1)\n"
    1.85 -        : "=r" (result) : "r" (lock), "0" (1) : "cc", "memory");
    1.86 -    return (result == 0);
    1.87 -
    1.88 -#elif defined(__MACOSX__) || defined(__IPHONEOS__)
    1.89 -    /* Maybe used for PowerPC, but the Intel asm or gcc atomics are favored. */
    1.90 -    return OSAtomicCompareAndSwap32Barrier(0, 1, lock);
    1.91 -
    1.92 -#elif HAVE_PTHREAD_SPINLOCK
    1.93 -    /* pthread instructions */
    1.94 -    return (pthread_spin_trylock(lock) == 0);
    1.95 -
    1.96 -#else
    1.97 -#error Please implement for your platform.
    1.98 -    return SDL_FALSE;
    1.99 -#endif
   1.100 -}
   1.101 -
   1.102 -void
   1.103 -SDL_AtomicLock(SDL_SpinLock *lock)
   1.104 -{
   1.105 -    /* FIXME: Should we have an eventual timeout? */
   1.106 -    while (!SDL_AtomicTryLock(lock)) {
   1.107 -        SDL_Delay(0);
   1.108 -    }
   1.109 -}
   1.110 -
   1.111 -void
   1.112 -SDL_AtomicUnlock(SDL_SpinLock *lock)
   1.113 -{
   1.114 -#if defined(_MSC_VER)
   1.115 -    _ReadWriteBarrier();
   1.116 -    *lock = 0;
   1.117 -
   1.118 -#elif HAVE_GCC_ATOMICS || HAVE_GCC_SYNC_LOCK_TEST_AND_SET
   1.119 -    __sync_lock_release(lock);
   1.120 -
   1.121 -#elif HAVE_PTHREAD_SPINLOCK
   1.122 -    pthread_spin_unlock(lock);
   1.123 -
   1.124 -#else
   1.125 -    *lock = 0;
   1.126 -#endif
   1.127 -}
   1.128 -
   1.129 -/* vi: set ts=4 sw=4 expandtab: */
   1.130 +/*
   1.131 +  Simple DirectMedia Layer
   1.132 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
   1.133 +
   1.134 +  This software is provided 'as-is', without any express or implied
   1.135 +  warranty.  In no event will the authors be held liable for any damages
   1.136 +  arising from the use of this software.
   1.137 +
   1.138 +  Permission is granted to anyone to use this software for any purpose,
   1.139 +  including commercial applications, and to alter it and redistribute it
   1.140 +  freely, subject to the following restrictions:
   1.141 +
   1.142 +  1. The origin of this software must not be misrepresented; you must not
   1.143 +     claim that you wrote the original software. If you use this software
   1.144 +     in a product, an acknowledgment in the product documentation would be
   1.145 +     appreciated but is not required.
   1.146 +  2. Altered source versions must be plainly marked as such, and must not be
   1.147 +     misrepresented as being the original software.
   1.148 +  3. This notice may not be removed or altered from any source distribution.
   1.149 +*/
   1.150 +#include "SDL_config.h"
   1.151 +
   1.152 +#if defined(__WIN32__) || defined(__WINRT__)
   1.153 +#include "../core/windows/SDL_windows.h"
   1.154 +#endif
   1.155 +
   1.156 +#include "SDL_atomic.h"
   1.157 +#include "SDL_mutex.h"
   1.158 +#include "SDL_timer.h"
   1.159 +
   1.160 +
   1.161 +/* This function is where all the magic happens... */
   1.162 +SDL_bool
   1.163 +SDL_AtomicTryLock(SDL_SpinLock *lock)
   1.164 +{
   1.165 +#if SDL_ATOMIC_DISABLED
   1.166 +    /* Terrible terrible damage */
   1.167 +    static SDL_mutex *_spinlock_mutex;
   1.168 +
   1.169 +    if (!_spinlock_mutex) {
   1.170 +        /* Race condition on first lock... */
   1.171 +        _spinlock_mutex = SDL_CreateMutex();
   1.172 +    }
   1.173 +    SDL_LockMutex(_spinlock_mutex);
   1.174 +    if (*lock == 0) {
   1.175 +        *lock = 1;
   1.176 +        SDL_UnlockMutex(_spinlock_mutex);
   1.177 +        return SDL_TRUE;
   1.178 +    } else {
   1.179 +        SDL_UnlockMutex(_spinlock_mutex);
   1.180 +        return SDL_FALSE;
   1.181 +    }
   1.182 +
   1.183 +#elif defined(_MSC_VER)
   1.184 +    SDL_COMPILE_TIME_ASSERT(locksize, sizeof(*lock) == sizeof(long));
   1.185 +    return (InterlockedExchange((long*)lock, 1) == 0);
   1.186 +
   1.187 +#elif HAVE_GCC_ATOMICS || HAVE_GCC_SYNC_LOCK_TEST_AND_SET
   1.188 +    return (__sync_lock_test_and_set(lock, 1) == 0);
   1.189 +
   1.190 +#elif defined(__GNUC__) && defined(__arm__) && \
   1.191 +        (defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || \
   1.192 +         defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5TE__) || \
   1.193 +         defined(__ARM_ARCH_5TEJ__))
   1.194 +    int result;
   1.195 +    __asm__ __volatile__ (
   1.196 +        "swp %0, %1, [%2]\n"
   1.197 +        : "=&r,&r" (result) : "r,0" (1), "r,r" (lock) : "memory");
   1.198 +    return (result == 0);
   1.199 +
   1.200 +#elif defined(__GNUC__) && defined(__arm__)
   1.201 +    int result;
   1.202 +    __asm__ __volatile__ (
   1.203 +        "ldrex %0, [%2]\nteq   %0, #0\nstrexeq %0, %1, [%2]"
   1.204 +        : "=&r" (result) : "r" (1), "r" (lock) : "cc", "memory");
   1.205 +    return (result == 0);
   1.206 +
   1.207 +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
   1.208 +    int result;
   1.209 +    __asm__ __volatile__(
   1.210 +        "lock ; xchgl %0, (%1)\n"
   1.211 +        : "=r" (result) : "r" (lock), "0" (1) : "cc", "memory");
   1.212 +    return (result == 0);
   1.213 +
   1.214 +#elif defined(__MACOSX__) || defined(__IPHONEOS__)
   1.215 +    /* Maybe used for PowerPC, but the Intel asm or gcc atomics are favored. */
   1.216 +    return OSAtomicCompareAndSwap32Barrier(0, 1, lock);
   1.217 +
   1.218 +#elif HAVE_PTHREAD_SPINLOCK
   1.219 +    /* pthread instructions */
   1.220 +    return (pthread_spin_trylock(lock) == 0);
   1.221 +
   1.222 +#else
   1.223 +#error Please implement for your platform.
   1.224 +    return SDL_FALSE;
   1.225 +#endif
   1.226 +}
   1.227 +
   1.228 +void
   1.229 +SDL_AtomicLock(SDL_SpinLock *lock)
   1.230 +{
   1.231 +    /* FIXME: Should we have an eventual timeout? */
   1.232 +    while (!SDL_AtomicTryLock(lock)) {
   1.233 +        SDL_Delay(0);
   1.234 +    }
   1.235 +}
   1.236 +
   1.237 +void
   1.238 +SDL_AtomicUnlock(SDL_SpinLock *lock)
   1.239 +{
   1.240 +#if defined(_MSC_VER)
   1.241 +    _ReadWriteBarrier();
   1.242 +    *lock = 0;
   1.243 +
   1.244 +#elif HAVE_GCC_ATOMICS || HAVE_GCC_SYNC_LOCK_TEST_AND_SET
   1.245 +    __sync_lock_release(lock);
   1.246 +
   1.247 +#elif HAVE_PTHREAD_SPINLOCK
   1.248 +    pthread_spin_unlock(lock);
   1.249 +
   1.250 +#else
   1.251 +    *lock = 0;
   1.252 +#endif
   1.253 +}
   1.254 +
   1.255 +/* vi: set ts=4 sw=4 expandtab: */