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