src/atomic/SDL_spinlock.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 17 Jan 2011 14:05:43 -0800
changeset 5015 1bf9e38431ec
parent 5004 0c72ae7b7cb2
child 5028 fffb33ae85e8
permissions -rw-r--r--
Use compiler intrinsics on Windows
     1 /*
     2   SDL - Simple DirectMedia Layer
     3   Copyright (C) 1997-2010 Sam Lantinga
     4 
     5   This library is free software; you can redistribute it and/or
     6   modify it under the terms of the GNU Lesser General Public
     7   License as published by the Free Software Foundation; either
     8   version 2.1 of the License, or (at your option) any later version.
     9 
    10   This library is distributed in the hope that it will be useful,
    11   but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13   Lesser General Public License for more details.
    14 
    15   You should have received a copy of the GNU Lesser General Public
    16   License along with this library; if not, write to the Free Software
    17   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19   Sam Lantinga
    20   slouken@libsdl.org
    21 */
    22 #include "SDL_stdinc.h"
    23 
    24 #include "SDL_atomic.h"
    25 #include "SDL_timer.h"
    26 
    27 #if defined(__WIN32__)
    28 #include <intrin.h>
    29 
    30 #elif defined(__MACOSX__)
    31 #include <libkern/OSAtomic.h>
    32 
    33 #endif
    34 
    35 
    36 /* This function is where all the magic happens... */
    37 SDL_bool
    38 SDL_AtomicTryLock(SDL_SpinLock *lock)
    39 {
    40 #if defined(__WIN32__)
    41     SDL_COMPILE_TIME_ASSERT(locksize, sizeof(*lock) == sizeof(long));
    42     return (_InterlockedExchange((long*)lock, 1) == 0);
    43 
    44 #elif defined(__MACOSX__)
    45     return OSAtomicCompareAndSwap32Barrier(0, 1, lock);
    46 
    47 #elif defined(HAVE_GCC_ATOMICS)
    48     return (__sync_lock_test_and_set(lock, 1) == 0);
    49 
    50 #elif defined(__GNUC__) && defined(__arm__) && defined(__ARM_ARCH_5__)
    51     int result;
    52     __asm__ __volatile__ (
    53         "swp %0, %1, [%2]\n"
    54         : "=&r,&r" (result) : "r,0" (1), "r,r" (lock) : "memory");
    55     return (result == 0);
    56 
    57 #elif defined(__GNUC__) && defined(__arm__)
    58     int result;
    59     __asm__ __volatile__ (
    60         "ldrex %0, [%2]\nteq   %0, #0\nstrexeq %0, %1, [%2]"
    61         : "=&r" (result) : "r" (1), "r" (lock) : "cc", "memory");
    62     return (result == 0);
    63 
    64 #else
    65     /* Need CPU instructions for spinlock here! */
    66     __need_spinlock_implementation__
    67 #endif
    68 }
    69 
    70 void
    71 SDL_AtomicLock(SDL_SpinLock *lock)
    72 {
    73     /* FIXME: Should we have an eventual timeout? */
    74     while (!SDL_AtomicTryLock(lock)) {
    75         SDL_Delay(0);
    76     }
    77 }
    78 
    79 void
    80 SDL_AtomicUnlock(SDL_SpinLock *lock)
    81 {
    82     /* Assuming atomic assignment operation and full memory barrier in lock */
    83     *lock = 0;
    84 }
    85 
    86 /* vi: set ts=4 sw=4 expandtab: */