src/atomic/SDL_spinlock.c
author Sam Lantinga
Mon, 09 Jan 2017 11:58:01 -0800
changeset 10802 6afc9b833867
parent 10737 3406a0f8b041
child 11318 06fd8421e8f6
permissions -rw-r--r--
We only need the first few keymaps corresponding to the following constants:
K_NORMTAB, K_SHIFTTAB, K_ALTTAB, K_ALTSHIFTTAB

In the normal case we'll load all the keymaps from the kernel, but this reduces the size of the SDL library for the fallback case when we can't get to the tty.
slouken@8582
     1
/*
slouken@8582
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@8582
     4
slouken@8582
     5
  This software is provided 'as-is', without any express or implied
slouken@8582
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@8582
     7
  arising from the use of this software.
slouken@8582
     8
slouken@8582
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@8582
    10
  including commercial applications, and to alter it and redistribute it
slouken@8582
    11
  freely, subject to the following restrictions:
slouken@8582
    12
slouken@8582
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@8582
    14
     claim that you wrote the original software. If you use this software
slouken@8582
    15
     in a product, an acknowledgment in the product documentation would be
slouken@8582
    16
     appreciated but is not required.
slouken@8582
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@8582
    18
     misrepresented as being the original software.
slouken@8582
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@8582
    20
*/
icculus@8093
    21
#include "../SDL_internal.h"
slouken@8582
    22
slouken@8582
    23
#if defined(__WIN32__) || defined(__WINRT__)
slouken@8582
    24
#include "../core/windows/SDL_windows.h"
slouken@8582
    25
#endif
slouken@8582
    26
slouken@8582
    27
#include "SDL_atomic.h"
slouken@8582
    28
#include "SDL_mutex.h"
slouken@8582
    29
#include "SDL_timer.h"
slouken@8582
    30
binarycrusader@8979
    31
#if !defined(HAVE_GCC_ATOMICS) && defined(__SOLARIS__)
binarycrusader@8979
    32
#include <atomic.h>
binarycrusader@8979
    33
#endif
slouken@8582
    34
slouken@8582
    35
/* This function is where all the magic happens... */
slouken@8582
    36
SDL_bool
slouken@8582
    37
SDL_AtomicTryLock(SDL_SpinLock *lock)
slouken@8582
    38
{
slouken@8582
    39
#if SDL_ATOMIC_DISABLED
slouken@8582
    40
    /* Terrible terrible damage */
slouken@8582
    41
    static SDL_mutex *_spinlock_mutex;
slouken@8582
    42
slouken@8582
    43
    if (!_spinlock_mutex) {
slouken@8582
    44
        /* Race condition on first lock... */
slouken@8582
    45
        _spinlock_mutex = SDL_CreateMutex();
slouken@8582
    46
    }
slouken@8582
    47
    SDL_LockMutex(_spinlock_mutex);
slouken@8582
    48
    if (*lock == 0) {
slouken@8582
    49
        *lock = 1;
slouken@8582
    50
        SDL_UnlockMutex(_spinlock_mutex);
slouken@8582
    51
        return SDL_TRUE;
slouken@8582
    52
    } else {
slouken@8582
    53
        SDL_UnlockMutex(_spinlock_mutex);
slouken@8582
    54
        return SDL_FALSE;
slouken@8582
    55
    }
slouken@8582
    56
slouken@8582
    57
#elif defined(_MSC_VER)
slouken@8582
    58
    SDL_COMPILE_TIME_ASSERT(locksize, sizeof(*lock) == sizeof(long));
slouken@8582
    59
    return (InterlockedExchange((long*)lock, 1) == 0);
slouken@8582
    60
slouken@8582
    61
#elif HAVE_GCC_ATOMICS || HAVE_GCC_SYNC_LOCK_TEST_AND_SET
slouken@8582
    62
    return (__sync_lock_test_and_set(lock, 1) == 0);
slouken@8582
    63
slouken@8582
    64
#elif defined(__GNUC__) && defined(__arm__) && \
slouken@8582
    65
        (defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || \
slouken@8582
    66
         defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5TE__) || \
slouken@8582
    67
         defined(__ARM_ARCH_5TEJ__))
slouken@8582
    68
    int result;
slouken@8582
    69
    __asm__ __volatile__ (
slouken@8582
    70
        "swp %0, %1, [%2]\n"
slouken@8582
    71
        : "=&r,&r" (result) : "r,0" (1), "r,r" (lock) : "memory");
slouken@8582
    72
    return (result == 0);
slouken@8582
    73
slouken@8582
    74
#elif defined(__GNUC__) && defined(__arm__)
slouken@8582
    75
    int result;
slouken@8582
    76
    __asm__ __volatile__ (
slouken@8582
    77
        "ldrex %0, [%2]\nteq   %0, #0\nstrexeq %0, %1, [%2]"
slouken@8582
    78
        : "=&r" (result) : "r" (1), "r" (lock) : "cc", "memory");
slouken@8582
    79
    return (result == 0);
slouken@8582
    80
slouken@8582
    81
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
slouken@8582
    82
    int result;
slouken@8582
    83
    __asm__ __volatile__(
slouken@8582
    84
        "lock ; xchgl %0, (%1)\n"
slouken@8582
    85
        : "=r" (result) : "r" (lock), "0" (1) : "cc", "memory");
slouken@8582
    86
    return (result == 0);
slouken@8582
    87
slouken@8582
    88
#elif defined(__MACOSX__) || defined(__IPHONEOS__)
slouken@8582
    89
    /* Maybe used for PowerPC, but the Intel asm or gcc atomics are favored. */
slouken@8582
    90
    return OSAtomicCompareAndSwap32Barrier(0, 1, lock);
slouken@8582
    91
binarycrusader@8979
    92
#elif defined(__SOLARIS__) && defined(_LP64)
binarycrusader@8979
    93
    /* Used for Solaris with non-gcc compilers. */
binarycrusader@8979
    94
    return (SDL_bool) ((int) atomic_cas_64((volatile uint64_t*)lock, 0, 1) == 0);
binarycrusader@8979
    95
binarycrusader@8979
    96
#elif defined(__SOLARIS__) && !defined(_LP64)
binarycrusader@8979
    97
    /* Used for Solaris with non-gcc compilers. */
binarycrusader@8979
    98
    return (SDL_bool) ((int) atomic_cas_32((volatile uint32_t*)lock, 0, 1) == 0);
binarycrusader@8979
    99
slouken@8582
   100
#else
slouken@8582
   101
#error Please implement for your platform.
slouken@8582
   102
    return SDL_FALSE;
slouken@8582
   103
#endif
slouken@8582
   104
}
slouken@8582
   105
slouken@8582
   106
void
slouken@8582
   107
SDL_AtomicLock(SDL_SpinLock *lock)
slouken@8582
   108
{
slouken@8582
   109
    /* FIXME: Should we have an eventual timeout? */
slouken@8582
   110
    while (!SDL_AtomicTryLock(lock)) {
slouken@8582
   111
        SDL_Delay(0);
slouken@8582
   112
    }
slouken@8582
   113
}
slouken@8582
   114
slouken@8582
   115
void
slouken@8582
   116
SDL_AtomicUnlock(SDL_SpinLock *lock)
slouken@8582
   117
{
slouken@8582
   118
#if defined(_MSC_VER)
slouken@8582
   119
    _ReadWriteBarrier();
slouken@8582
   120
    *lock = 0;
slouken@8582
   121
slouken@8582
   122
#elif HAVE_GCC_ATOMICS || HAVE_GCC_SYNC_LOCK_TEST_AND_SET
slouken@8582
   123
    __sync_lock_release(lock);
slouken@8582
   124
binarycrusader@8979
   125
#elif defined(__SOLARIS__)
binarycrusader@8979
   126
    /* Used for Solaris when not using gcc. */
binarycrusader@8979
   127
    *lock = 0;
binarycrusader@8979
   128
    membar_producer();
binarycrusader@8979
   129
slouken@8582
   130
#else
slouken@8582
   131
    *lock = 0;
slouken@8582
   132
#endif
slouken@8582
   133
}
slouken@8582
   134
slouken@8582
   135
/* vi: set ts=4 sw=4 expandtab: */