src/atomic/SDL_atomic.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Sat, 27 Jul 2013 14:06:06 +0200
changeset 7532 2c54272792e2
parent 7394 38dc4961ab15
child 7860 2b0bcdea3a79
permissions -rw-r--r--
Removed C++ macro setup in internal header for Android port which is only C now.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
     1
/*
5535
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
     2
  Simple DirectMedia Layer
6885
700f1b25f77f Happy New Year!
Sam Lantinga <slouken@libsdl.org>
parents: 6217
diff changeset
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
     4
5535
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
     5
  This software is provided 'as-is', without any express or implied
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
     6
  warranty.  In no event will the authors be held liable for any damages
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
     7
  arising from the use of this software.
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
     8
5535
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
     9
  Permission is granted to anyone to use this software for any purpose,
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
    10
  including commercial applications, and to alter it and redistribute it
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
    11
  freely, subject to the following restrictions:
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    12
5535
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
    13
  1. The origin of this software must not be misrepresented; you must not
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
    14
     claim that you wrote the original software. If you use this software
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
    15
     in a product, an acknowledgment in the product documentation would be
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
    16
     appreciated but is not required.
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
    17
  2. Altered source versions must be plainly marked as such, and must not be
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
    18
     misrepresented as being the original software.
96594ac5fd1a SDL 1.3 is now under the zlib license.
Sam Lantinga <slouken@libsdl.org>
parents: 5262
diff changeset
    19
  3. This notice may not be removed or altered from any source distribution.
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    20
*/
6217
6952b11b7f46 Make sure that we use consistent configuration options on platforms like Windows so that command line builds and IDE builds have ABI compatibility.
Sam Lantinga <slouken@libsdl.org>
parents: 6138
diff changeset
    21
#include "SDL_config.h"
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    22
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    23
#include "SDL_atomic.h"
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    24
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    25
/* Note that we undefine the atomic operations here, in case they are
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    26
   defined as compiler intrinsics while building SDL but the library user
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    27
   doesn't have that compiler.  That way we always have a working set of
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    28
   atomic operations built into the library.
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    29
*/
6978
e851407e9294 Put the real SDL_AtomicCAS() and SDL_AtomicCASPtr() symbols into the library.
Sam Lantinga <slouken@libsdl.org>
parents: 6885
diff changeset
    30
#undef SDL_AtomicCAS
e851407e9294 Put the real SDL_AtomicCAS() and SDL_AtomicCASPtr() symbols into the library.
Sam Lantinga <slouken@libsdl.org>
parents: 6885
diff changeset
    31
#undef SDL_AtomicCASPtr
7191
75360622e65f File style cleanup for the SDL 2.0 release
Sam Lantinga <slouken@libsdl.org>
parents: 6978
diff changeset
    32
75360622e65f File style cleanup for the SDL 2.0 release
Sam Lantinga <slouken@libsdl.org>
parents: 6978
diff changeset
    33
/*
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    34
  If any of the operations are not provided then we must emulate some
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    35
  of them. That means we need a nice implementation of spin locks
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    36
  that avoids the "one big lock" problem. We use a vector of spin
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    37
  locks and pick which one to use based on the address of the operand
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    38
  of the function.
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    39
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    40
  To generate the index of the lock we first shift by 3 bits to get
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    41
  rid on the zero bits that result from 32 and 64 bit allignment of
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    42
  data. We then mask off all but 5 bits and use those 5 bits as an
7191
75360622e65f File style cleanup for the SDL 2.0 release
Sam Lantinga <slouken@libsdl.org>
parents: 6978
diff changeset
    43
  index into the table.
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    44
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    45
  Picking the lock this way insures that accesses to the same data at
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    46
  the same time will go to the same lock. OTOH, accesses to different
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    47
  data have only a 1/32 chance of hitting the same lock. That should
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    48
  pretty much eliminate the chances of several atomic operations on
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    49
  different data from waiting on the same "big lock". If it isn't
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    50
  then the table of locks can be expanded to a new size so long as
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    51
  the new size is a power of two.
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    52
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    53
  Contributed by Bob Pendleton, bob@pendleton.com
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    54
*/
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    55
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    56
static SDL_SpinLock locks[32];
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    57
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    58
static __inline__ void
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    59
enterLock(void *a)
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    60
{
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    61
    uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f);
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    62
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    63
    SDL_AtomicLock(&locks[index]);
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    64
}
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    65
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    66
static __inline__ void
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    67
leaveLock(void *a)
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    68
{
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    69
    uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f);
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    70
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    71
    SDL_AtomicUnlock(&locks[index]);
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    72
}
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    73
6978
e851407e9294 Put the real SDL_AtomicCAS() and SDL_AtomicCASPtr() symbols into the library.
Sam Lantinga <slouken@libsdl.org>
parents: 6885
diff changeset
    74
DECLSPEC SDL_bool SDLCALL
e851407e9294 Put the real SDL_AtomicCAS() and SDL_AtomicCASPtr() symbols into the library.
Sam Lantinga <slouken@libsdl.org>
parents: 6885
diff changeset
    75
SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval)
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    76
{
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    77
    SDL_bool retval = SDL_FALSE;
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    78
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    79
    enterLock(a);
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    80
    if (a->value == oldval) {
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    81
        a->value = newval;
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    82
        retval = SDL_TRUE;
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    83
    }
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    84
    leaveLock(a);
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    85
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    86
    return retval;
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    87
}
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    88
6978
e851407e9294 Put the real SDL_AtomicCAS() and SDL_AtomicCASPtr() symbols into the library.
Sam Lantinga <slouken@libsdl.org>
parents: 6885
diff changeset
    89
DECLSPEC SDL_bool SDLCALL
e851407e9294 Put the real SDL_AtomicCAS() and SDL_AtomicCASPtr() symbols into the library.
Sam Lantinga <slouken@libsdl.org>
parents: 6885
diff changeset
    90
SDL_AtomicCASPtr(void **a, void *oldval, void *newval)
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    91
{
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    92
    SDL_bool retval = SDL_FALSE;
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    93
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    94
    enterLock(a);
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    95
    if (*a == oldval) {
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    96
        *a = newval;
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
    97
        retval = SDL_TRUE;
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    98
    }
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
    99
    leaveLock(a);
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
   100
5004
0c72ae7b7cb2 Added native atomic operations for Windows, Mac OS X, and gcc compiler intrinsics.
Sam Lantinga <slouken@libsdl.org>
parents: 5003
diff changeset
   101
    return retval;
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
   102
}
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
   103
7394
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   104
#if defined(__GNUC__) && defined(__arm__) && \
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   105
   (defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__))
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   106
__asm__(
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   107
"   .align 2\n"
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   108
"   .globl _SDL_MemoryBarrierRelease\n"
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   109
"   .globl _SDL_MemoryBarrierAcquire\n"
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   110
"_SDL_MemoryBarrierRelease:\n"
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   111
"_SDL_MemoryBarrierAcquire:\n"
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   112
"   mov r0, #0\n"
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   113
"   mcr p15, 0, r0, c7, c10, 5\n"
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   114
"   bx lr\n"
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   115
);
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   116
#endif /* __GNUC__ && __arm__ && ARMV6 */
38dc4961ab15 Added PowerPC and ARM versions of the memory barrier functions.
Sam Lantinga <slouken@libsdl.org>
parents: 7191
diff changeset
   117
5003
3a95a2b93eb3 Updated the atomic API for better use cases
Sam Lantinga <slouken@libsdl.org>
parents:
diff changeset
   118
/* vi: set ts=4 sw=4 expandtab: */