src/atomic/SDL_spinlock.c
changeset 5003 3a95a2b93eb3
child 5004 0c72ae7b7cb2
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/atomic/SDL_spinlock.c	Sat Jan 15 12:41:59 2011 -0800
     1.3 @@ -0,0 +1,99 @@
     1.4 +/*
     1.5 +  SDL - Simple DirectMedia Layer
     1.6 +  Copyright (C) 1997-2010 Sam Lantinga
     1.7 +
     1.8 +  This library is free software; you can redistribute it and/or
     1.9 +  modify it under the terms of the GNU Lesser General Public
    1.10 +  License as published by the Free Software Foundation; either
    1.11 +  version 2.1 of the License, or (at your option) any later version.
    1.12 +
    1.13 +  This library is distributed in the hope that it will be useful,
    1.14 +  but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +  Lesser General Public License for more details.
    1.17 +
    1.18 +  You should have received a copy of the GNU Lesser General Public
    1.19 +  License along with this library; if not, write to the Free Software
    1.20 +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    1.21 +
    1.22 +  Sam Lantinga
    1.23 +  slouken@libsdl.org
    1.24 +*/
    1.25 +#include "SDL_stdinc.h"
    1.26 +
    1.27 +#include "SDL_atomic.h"
    1.28 +#include "SDL_timer.h"
    1.29 +
    1.30 +#if defined(__WIN32__)
    1.31 +#define WIN32_LEAN_AND_MEAN
    1.32 +#include <windows.h>
    1.33 +
    1.34 +#elif defined(__MACOSX__)
    1.35 +#include <libkern/OSAtomic.h>
    1.36 +
    1.37 +#endif
    1.38 +
    1.39 +
    1.40 +/* This function is where all the magic happens... */
    1.41 +SDL_bool
    1.42 +SDL_AtomicTryLock(SDL_SpinLock *lock)
    1.43 +{
    1.44 +#if defined(__WIN32__)
    1.45 +    return (InterlockedExchange(lock, 1) == 0);
    1.46 +
    1.47 +#elif defined(__MACOSX__)
    1.48 +    return OSAtomicCompareAndSwap32Barrier(0, 1, lock);
    1.49 +
    1.50 +#elif defined(__GNUC__)
    1.51 +#if defined(__arm__)
    1.52 +#ifdef __ARM_ARCH_5__
    1.53 +    int result;
    1.54 +    __asm__ __volatile__ (
    1.55 +        "swp %0, %1, [%2]\n"
    1.56 +        : "=&r,&r" (result) : "r,0" (1), "r,r" (lock) : "memory");
    1.57 +    return (result == 0);
    1.58 +#else
    1.59 +    int result;
    1.60 +    __asm__ __volatile__ (
    1.61 +        "ldrex %0, [%2]\nteq   %0, #0\nstrexeq %0, %1, [%2]"
    1.62 +        : "=&r" (result) : "r" (1), "r" (lock) : "cc", "memory");
    1.63 +    return (result == 0);
    1.64 +#endif
    1.65 +#else
    1.66 +    return (__sync_lock_test_and_set(lock, 1) == 0);
    1.67 +#endif
    1.68 +
    1.69 +#else
    1.70 +    /* Need CPU instructions for spinlock here! */
    1.71 +    __need_spinlock_implementation__
    1.72 +#endif
    1.73 +}
    1.74 +
    1.75 +void
    1.76 +SDL_AtomicLock(SDL_SpinLock *lock)
    1.77 +{
    1.78 +    /* FIXME: Should we have an eventual timeout? */
    1.79 +    while (!SDL_AtomicTryLock(lock)) {
    1.80 +        SDL_Delay(0);
    1.81 +    }
    1.82 +}
    1.83 +
    1.84 +void
    1.85 +SDL_AtomicUnlock(SDL_SpinLock *lock)
    1.86 +{
    1.87 +#if defined(__WIN32__)
    1.88 +    *lock = 0;
    1.89 +
    1.90 +#elif defined(__MACOSX__)
    1.91 +    *lock = 0;
    1.92 +
    1.93 +#elif defined(__GNUC__) && !defined(__arm__)
    1.94 +    __sync_lock_release(lock);
    1.95 +
    1.96 +#else
    1.97 +    /* Assuming memory barrier in lock and integral assignment operation */
    1.98 +    *lock = 0;
    1.99 +#endif
   1.100 +}
   1.101 +
   1.102 +/* vi: set ts=4 sw=4 expandtab: */