src/atomic/SDL_spinlock.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 15 Jan 2011 12:41:59 -0800
changeset 5003 3a95a2b93eb3
child 5004 0c72ae7b7cb2
permissions -rw-r--r--
Updated the atomic API for better use cases
     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 #define WIN32_LEAN_AND_MEAN
    29 #include <windows.h>
    30 
    31 #elif defined(__MACOSX__)
    32 #include <libkern/OSAtomic.h>
    33 
    34 #endif
    35 
    36 
    37 /* This function is where all the magic happens... */
    38 SDL_bool
    39 SDL_AtomicTryLock(SDL_SpinLock *lock)
    40 {
    41 #if defined(__WIN32__)
    42     return (InterlockedExchange(lock, 1) == 0);
    43 
    44 #elif defined(__MACOSX__)
    45     return OSAtomicCompareAndSwap32Barrier(0, 1, lock);
    46 
    47 #elif defined(__GNUC__)
    48 #if defined(__arm__)
    49 #ifdef __ARM_ARCH_5__
    50     int result;
    51     __asm__ __volatile__ (
    52         "swp %0, %1, [%2]\n"
    53         : "=&r,&r" (result) : "r,0" (1), "r,r" (lock) : "memory");
    54     return (result == 0);
    55 #else
    56     int result;
    57     __asm__ __volatile__ (
    58         "ldrex %0, [%2]\nteq   %0, #0\nstrexeq %0, %1, [%2]"
    59         : "=&r" (result) : "r" (1), "r" (lock) : "cc", "memory");
    60     return (result == 0);
    61 #endif
    62 #else
    63     return (__sync_lock_test_and_set(lock, 1) == 0);
    64 #endif
    65 
    66 #else
    67     /* Need CPU instructions for spinlock here! */
    68     __need_spinlock_implementation__
    69 #endif
    70 }
    71 
    72 void
    73 SDL_AtomicLock(SDL_SpinLock *lock)
    74 {
    75     /* FIXME: Should we have an eventual timeout? */
    76     while (!SDL_AtomicTryLock(lock)) {
    77         SDL_Delay(0);
    78     }
    79 }
    80 
    81 void
    82 SDL_AtomicUnlock(SDL_SpinLock *lock)
    83 {
    84 #if defined(__WIN32__)
    85     *lock = 0;
    86 
    87 #elif defined(__MACOSX__)
    88     *lock = 0;
    89 
    90 #elif defined(__GNUC__) && !defined(__arm__)
    91     __sync_lock_release(lock);
    92 
    93 #else
    94     /* Assuming memory barrier in lock and integral assignment operation */
    95     *lock = 0;
    96 #endif
    97 }
    98 
    99 /* vi: set ts=4 sw=4 expandtab: */