include/SDL_atomic.h
author Sam Lantinga <slouken@libsdl.org>
Wed, 10 Jun 2009 13:34:20 +0000
changeset 3186 51750b7a966f
parent 3181 030899df1af5
child 3187 e041d2c603fe
permissions -rw-r--r--
indent
bob@3180
     1
/*
bob@3180
     2
    SDL - Simple DirectMedia Layer
bob@3180
     3
    Copyright (C) 1997-2006 Sam Lantinga
bob@3180
     4
bob@3180
     5
    This library is free software; you can redistribute it and/or
bob@3180
     6
    modify it under the terms of the GNU Lesser General Public
bob@3180
     7
    License as published by the Free Software Foundation; either
bob@3180
     8
    version 2.1 of the License, or (at your option) any later version.
bob@3180
     9
bob@3180
    10
    This library is distributed in the hope that it will be useful,
bob@3180
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
bob@3180
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
bob@3180
    13
    Lesser General Public License for more details.
bob@3180
    14
bob@3180
    15
    You should have received a copy of the GNU Lesser General Public
bob@3180
    16
    License along with this library; if not, write to the Free Software
bob@3180
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
bob@3180
    18
bob@3180
    19
    Sam Lantinga
bob@3180
    20
    slouken@libsdl.org
bob@3180
    21
 */
bob@3180
    22
bob@3180
    23
/**
bob@3180
    24
 * \file SDL_atomic.h
bob@3180
    25
 *
bob@3180
    26
 * Atomic int and pointer magic
bob@3180
    27
 */
bob@3180
    28
bob@3180
    29
#ifndef _SDL_atomic_h_
bob@3180
    30
#define _SDL_atomic_h_
bob@3180
    31
bob@3180
    32
bob@3180
    33
#include "SDL_stdinc.h"
bob@3180
    34
#include "SDL_platform.h"
bob@3180
    35
bob@3180
    36
#include "begin_code.h"
bob@3180
    37
bob@3180
    38
/* Set up for C function definitions, even when using C++ */
bob@3180
    39
#ifdef __cplusplus
bob@3180
    40
/* *INDENT-OFF* */
bob@3180
    41
extern "C" {
bob@3180
    42
/* *INDENT-ON* */
bob@3180
    43
#endif
bob@3180
    44
bob@3180
    45
#if defined(__GNUC__) && (defined(i386) || defined(__i386__)  || defined(__x86_64__))
bob@3180
    46
static __inline__ void
slouken@3186
    47
SDL_atomic_int_add(volatile int *atomic, int value)
bob@3180
    48
{
slouken@3186
    49
    __asm__ __volatile__("lock;" "addl %1, %0":"=m"(*atomic)
slouken@3186
    50
                         :"ir"(value), "m"(*atomic));
bob@3180
    51
}
bob@3180
    52
bob@3180
    53
static __inline__ int
slouken@3186
    54
SDL_atomic_int_xchg_add(volatile int *atomic, int value)
slouken@3186
    55
{
slouken@3186
    56
    int rv;
slouken@3186
    57
    __asm__ __volatile__("lock;" "xaddl %0, %1":"=r"(rv), "=m"(*atomic)
slouken@3186
    58
                         :"0"(value), "m"(*atomic));
slouken@3186
    59
    return rv;
bob@3180
    60
}
bob@3180
    61
bob@3180
    62
static __inline__ SDL_bool
slouken@3186
    63
SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
bob@3180
    64
{
slouken@3186
    65
    int rv;
slouken@3186
    66
    __asm__ __volatile__("lock;" "cmpxchgl %2, %1":"=a"(rv), "=m"(*atomic)
slouken@3186
    67
                         :"r"(newvalue), "m"(*atomic), "0"(oldvalue));
slouken@3186
    68
    return (SDL_bool) (rv == oldvalue);
bob@3180
    69
}
bob@3180
    70
bob@3180
    71
static __inline__ SDL_bool
slouken@3186
    72
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
    73
                        void *newvalue)
bob@3180
    74
{
slouken@3186
    75
    void *rv;
slouken@3186
    76
    __asm__ __volatile__("lock;"
slouken@3186
    77
# if defined(__x86_64__)
slouken@3186
    78
                         "cmpxchgq %q2, %1"
bob@3180
    79
# else
slouken@3186
    80
                         "cmpxchgl %2, %1"
slouken@3186
    81
# endif
slouken@3186
    82
                         :"=a"(rv), "=m"(*atomic)
slouken@3186
    83
                         :"r"(newvalue), "m"(*atomic), "0"(oldvalue));
slouken@3186
    84
    return (SDL_bool) (rv == oldvalue);
bob@3180
    85
}
bob@3180
    86
#elif defined(__GNUC__) && defined(__alpha__)
bob@3180
    87
# define ATOMIC_MEMORY_BARRIER (__asm__ __volatile__ ("mb" : : : "memory"))
bob@3180
    88
# define ATOMIC_INT_CMP_XCHG(atomic,value)              \
bob@3180
    89
  ({                                                    \
bob@3180
    90
    int rv,prev;                                        \
bob@3180
    91
    __asm__ __volatile__("   mb\n"                      \
bob@3180
    92
                         "1: ldl_l   %0,%2\n"           \
bob@3180
    93
                         "   cmpeq   %0,%3,%1\n"        \
bob@3180
    94
                         "   beq     %1,2f\n"           \
bob@3180
    95
                         "   mov     %4,%1\n"           \
bob@3180
    96
                         "   stl_c   %1,%2\n"           \
bob@3180
    97
                         "   beq     %1,1b\n"           \
bob@3180
    98
                         "   mb\n"                      \
bob@3180
    99
                         "2:"                           \
bob@3180
   100
                         : "=&r" (prev),                \
bob@3180
   101
                           "=&r" (rv)                   \
bob@3180
   102
                         : "m" (*(atomic)),             \
bob@3180
   103
                           "Ir" (oldvalue),             \
bob@3180
   104
                           "Ir" (newvalue)              \
bob@3180
   105
                         : "memory");                   \
bob@3180
   106
    (rv != 0);                                          \
bob@3180
   107
  })
bob@3180
   108
bob@3180
   109
# if (SIZEOF_VOIDP == 4)
bob@3180
   110
static __inline__ SDL_bool
slouken@3186
   111
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   112
                        void *newvalue)
bob@3180
   113
{
slouken@3186
   114
    int rv;
slouken@3186
   115
    void *prev;
slouken@3186
   116
    __asm__ __volatile__("   mb\n"
slouken@3186
   117
                         "1: ldl_l %0,%2\n"
slouken@3186
   118
                         "   cmpeq %0,%3,%1\n"
slouken@3186
   119
                         "   beq   $1,2f\n"
slouken@3186
   120
                         "   mov   %4,%1\n"
slouken@3186
   121
                         "   stl_c %1,%2\n"
slouken@3186
   122
                         "   beq   %1,1b\n"
slouken@3186
   123
                         "   mb\n" "2:":"=&r"(prev), "=&r"(rv)
slouken@3186
   124
                         :"m"(*atomic), "Ir"(oldvalue), "Ir"(newvalue)
slouken@3186
   125
                         :"memory");
slouken@3186
   126
    return (SDL_bool) (rv != 0);
bob@3180
   127
}
bob@3180
   128
# elif (SIZEOF_VOIDP == 8)
bob@3180
   129
static __inline__ SDL_bool
slouken@3186
   130
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   131
                        void *newvalue)
bob@3180
   132
{
slouken@3186
   133
    int rv;
slouken@3186
   134
    void *prev;
slouken@3186
   135
    __asm__ __volatile__("   mb\n"
slouken@3186
   136
                         "1: ldq_l %0,%2\n"
slouken@3186
   137
                         "   cmpeq %0,%3,%1\n"
slouken@3186
   138
                         "   beq   %1,2f\n"
slouken@3186
   139
                         "   mov   %4,%1\n"
slouken@3186
   140
                         "   stq_c %1,%2\n"
slouken@3186
   141
                         "   beq   %1,1b\n"
slouken@3186
   142
                         "   mb\n" "2:":"=&r"(prev), "=&r"(rv)
slouken@3186
   143
                         :"m"(*atomic), "Ir"(oldvalue), "Ir"(newvalue)
slouken@3186
   144
                         :"memory");
slouken@3186
   145
    return (SDL_bool) (rv != 0);
bob@3180
   146
}
bob@3180
   147
# else
slouken@3186
   148
#  error "Your system has an unsupported pointer size"
slouken@3186
   149
# endif /* SIZEOF_VOIDP */
bob@3180
   150
#elif defined(__GNUC__) && defined(__sparc__)
bob@3180
   151
# define ATOMIC_MEMORY_BARRIER                                          \
bob@3180
   152
  (__asm__ __volatile__("membar #LoadLoad | #LoadStore"                 \
bob@3180
   153
                        " | #StoreLoad | #StoreStore" : : : "memory"))
bob@3180
   154
# define ATOMIC_INT_CMP_XCHG(atomic,oldvalue,newvalue)                  \
bob@3180
   155
  ({                                                                    \
bob@3180
   156
    int rv;                                                             \
bob@3180
   157
    __asm__ __volatile__("cas [%4], %2, %0"                             \
bob@3180
   158
                         : "=r" (rv), "=m" (*(atomic))                  \
bob@3180
   159
                         : "r" (oldvalue), "m" (*(atomic)),             \
bob@3180
   160
                         "r" (atomic), "0" (newvalue));                 \
bob@3180
   161
    rv == oldvalue;                                                     \
bob@3180
   162
  })
bob@3180
   163
bob@3180
   164
# if (SIZEOF_VOIDP == 4)
bob@3180
   165
static __inline__ SDL_bool
slouken@3186
   166
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   167
                        void *newvalue)
bob@3180
   168
{
slouken@3186
   169
    void *rv;
slouken@3186
   170
    __asm__ __volatile__("cas [%4], %2, %0":"=r"(rv), "=m"(*atomic)
slouken@3186
   171
                         :"r"(oldvalue),
slouken@3186
   172
                         "m"(*atomic), "r"(atomic), "0"(newvalue));
slouken@3186
   173
    return (SDL_bool) (rv == oldvalue);
bob@3180
   174
}
bob@3180
   175
# elif (SIZEOF_VOIDP == 8)
bob@3180
   176
static __inline__ SDL_bool
slouken@3186
   177
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   178
                        void *newvalue)
bob@3180
   179
{
slouken@3186
   180
    void *rv;
slouken@3186
   181
    void **a = atomic;
slouken@3186
   182
    __asm__ __volatile__("casx [%4], %2, %0":"=r"(rv), "=m"(*a)
slouken@3186
   183
                         :"r"(oldvalue), "m"(*a), "r"(a), "0"(newvalue));
slouken@3186
   184
    return (SDL_bool) (rv == oldvalue);
bob@3180
   185
}
bob@3180
   186
# else
bob@3180
   187
#  error "Your system has an unsupported pointer size"
bob@3180
   188
# endif /* SIZEOF_VOIDP */
bob@3180
   189
#elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC))
bob@3180
   190
# define ATOMIC_MEMORY_BARRIER \
bob@3180
   191
  (__asm__ __volatile__ ("sync" : : : "memory"))
bob@3180
   192
static __inline__ void
slouken@3186
   193
SDL_atomic_int_add(volatile int *atomic, int value)
slouken@3186
   194
{
slouken@3186
   195
    int rv, tmp;
slouken@3186
   196
    __asm__ __volatile__("1: lwarx   %0,  0, %3\n"
slouken@3186
   197
                         "   add     %1, %0, %4\n"
slouken@3186
   198
                         "   stwcx.  %1,  0, %3\n"
slouken@3186
   199
                         "   bne-    1b":"=&b"(rv), "=&r"(tmp), "=m"(*atomic)
slouken@3186
   200
                         :"b"(atomic), "r"(value), "m"(*atomic)
slouken@3186
   201
                         :"cr0", "memory");
bob@3180
   202
}
bob@3180
   203
bob@3180
   204
static __inline__ int
slouken@3186
   205
SDL_atomic_int_xchg_add(volatile int *atomic, int value)
slouken@3186
   206
{
slouken@3186
   207
    int rv, tmp;
slouken@3186
   208
    __asm__ __volatile__("1: lwarx  %0, 0, %3\n"
slouken@3186
   209
                         "   add    %1, %0, %4\n"
slouken@3186
   210
                         "   stwcx. %1, 0, %3\n"
slouken@3186
   211
                         "   bne-   1b":"=&b"(rv), "=&r"(tmp), "=m"(*atomic)
slouken@3186
   212
                         :"b"(atomic), "r"(value), "m"(*atomic)
slouken@3186
   213
                         :"cr0", "memory");
slouken@3186
   214
    return rv;
bob@3180
   215
}
bob@3180
   216
bob@3180
   217
# if (SIZEOF_VOIDP == 4)
bob@3180
   218
static __inline__ SDL_bool
slouken@3186
   219
SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
slouken@3186
   220
{
slouken@3186
   221
    int rv;
slouken@3186
   222
    __asm__ __volatile__("   sync\n"
slouken@3186
   223
                         "1: lwarx   %0, 0, %1\n"
slouken@3186
   224
                         "   subf.   %0, %2, %0\n"
slouken@3186
   225
                         "   bne     2f\n"
slouken@3186
   226
                         "   stwcx.  %3, 0, %1\n"
slouken@3186
   227
                         "   bne-    1b\n" "2: isync":"=&r"(rv)
slouken@3186
   228
                         :"b"(atomic), "r"(oldvalue), "r":"cr0", "memory");
slouken@3186
   229
    return (SDL_bool) (rv == 0);
bob@3180
   230
}
bob@3180
   231
bob@3180
   232
static __inline__ SDL_bool
slouken@3186
   233
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   234
                        void *newvalue)
bob@3180
   235
{
slouken@3186
   236
    void *rv;
slouken@3186
   237
    __asm__ __volatile__("sync\n"
slouken@3186
   238
                         "1: lwarx  %0,  0, %1\n"
slouken@3186
   239
                         "   subf.  %0, %2, %0\n"
slouken@3186
   240
                         "   bne    2f\n"
slouken@3186
   241
                         "   stwcx. %3,  0, %1\n"
slouken@3186
   242
                         "   bne-   1b\n" "2: isync":"=&r"(rv)
slouken@3186
   243
                         :"b"(atomic), "r"(oldvalue), "r"(newvalue)
slouken@3186
   244
                         :"cr0", "memory");
slouken@3186
   245
    return (SDL_bool) (rv == 0);
bob@3180
   246
}
bob@3180
   247
# elif (SIZEOF_VOIDP == 8)
bob@3180
   248
static __inline__ SDL_bool
slouken@3186
   249
SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
slouken@3186
   250
{
slouken@3186
   251
    int rv;
slouken@3186
   252
    __asm__ __volatile__("   sync\n"
slouken@3186
   253
                         "1: lwarx   %0,  0, %1\n"
slouken@3186
   254
                         "   extsw   %0, %0\n"
slouken@3186
   255
                         "   subf.   %0, %2, %0\n"
slouken@3186
   256
                         "   bne     2f\n"
slouken@3186
   257
                         "   stwcx.  %3,  0, %1\n"
slouken@3186
   258
                         "   bne-    1b\n" "2: isync":"=&r"(rv)
slouken@3186
   259
                         :"b"(atomic), "r"(oldvalue), "r":"cr0", "memory");
slouken@3186
   260
    return (SDL_bool) (rv == 0);
bob@3180
   261
}
bob@3180
   262
bob@3180
   263
static __inline__ SDL_bool
slouken@3186
   264
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   265
                        void *newvalue)
bob@3180
   266
{
slouken@3186
   267
    void *rv;
slouken@3186
   268
    __asm__ __volatile__("sync\n"
slouken@3186
   269
                         "1: ldarx  %0,  0, %1\n"
slouken@3186
   270
                         "   subf.  %0, %2, %0\n"
slouken@3186
   271
                         "   bne    2f\n"
slouken@3186
   272
                         "   stdcx. %3,  0, %1\n"
slouken@3186
   273
                         "   bne-   1b\n" "2: isync":"=&r"(rv)
slouken@3186
   274
                         :"b"(atomic), "r"(oldvalue), "r"(newvalue)
slouken@3186
   275
                         :"cr0", "memory");
slouken@3186
   276
    return (SDL_bool) (rv == 0);
bob@3180
   277
}
bob@3180
   278
# else
bob@3180
   279
#  error "Your system has an unsupported pointer size"
bob@3180
   280
# endif /* SIZEOF_VOIDP */
bob@3180
   281
#elif defined(__GNUC__) && (defined(__IA64__) || defined(__ia64__))
bob@3180
   282
# define ATOMIC_MEMORY_BARRIER (__sync_synchronize())
bob@3180
   283
# define SDL_atomic_int_xchg_add(atomic, value)     \
bob@3180
   284
  (__sync_fetch_and_add((atomic),(value)))
bob@3180
   285
# define SDL_atomic_int_add(atomic, value)                  \
bob@3180
   286
  ((void)__sync_fetch_and_add((atomic),(value)))
bob@3180
   287
# define SDL_atomic_int_cmp_xchg(atomic,oldvalue,newvalue)  \
bob@3180
   288
  (__sync_bool_compare_and_swap((atomic),(oldvalue),(newvalue)))
bob@3180
   289
# define SDL_atomic_ptr_cmp_xchg(atomic,oldvalue,newvalue)              \
bob@3180
   290
  (__sync_bool_compare_and_swap((long*)(atomic),(long)(oldvalue),(long)(newvalue)))
bob@3180
   291
#elif defined(__GNUC__) && defined(__LINUX__) && (defined(__mips__) || defined(__MIPS__))
bob@3180
   292
static __inline__ int
slouken@3186
   293
SDL_atomic_int_xchg_add(volatile int *atomic, int value)
slouken@3186
   294
{
slouken@3186
   295
    int rv, tmp;
slouken@3186
   296
    __asm__ __volatile__("1:              \n"
slouken@3186
   297
                         ".set  push      \n"
slouken@3186
   298
                         ".set  mips2     \n"
slouken@3186
   299
                         "ll    %0,%3     \n"
slouken@3186
   300
                         "addu  %1,%4,%0  \n"
slouken@3186
   301
                         "sc    %1,%2     \n"
slouken@3186
   302
                         ".set  pop       \n"
slouken@3186
   303
                         "beqz  %1,1b     \n":"=&r"(rv),
slouken@3186
   304
                         "=&r"(tmp), "=m"(*atomic)
slouken@3186
   305
                         :"m"(*atomic), "r"(value)
slouken@3186
   306
                         :"memory");
slouken@3186
   307
    return rv;
bob@3180
   308
}
bob@3180
   309
bob@3180
   310
static __inline__ void
slouken@3186
   311
SDL_atomic_int_add(volatile int *atomic, int value)
slouken@3186
   312
{
slouken@3186
   313
    int rv;
slouken@3186
   314
    __asm__ __volatile__("1:               \n"
slouken@3186
   315
                         ".set  push       \n"
slouken@3186
   316
                         ".set  mips2      \n"
slouken@3186
   317
                         "ll    %0,%2      \n"
slouken@3186
   318
                         "addu  %0,%3,%0   \n"
slouken@3186
   319
                         "sc    %0,%1      \n"
slouken@3186
   320
                         ".set  pop        \n"
slouken@3186
   321
                         "beqz  %0,1b      \n":"=&r"(rv), "=m"(*atomic)
slouken@3186
   322
                         :"m"(*atomic), "r"(value)
slouken@3186
   323
                         :"memory");
bob@3180
   324
}
bob@3180
   325
bob@3180
   326
static __inline__ SDL_bool
slouken@3186
   327
SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
bob@3180
   328
{
slouken@3186
   329
    int rv;
slouken@3186
   330
    __asm__ __volatile__("     .set push        \n"
slouken@3186
   331
                         "     .set noat        \n"
slouken@3186
   332
                         "     .set mips3       \n"
slouken@3186
   333
                         "1:   ll   %0, %2      \n"
slouken@3186
   334
                         "     bne  %0, %z3, 2f \n"
slouken@3186
   335
                         "     .set mips0       \n"
slouken@3186
   336
                         "     move $1, %z4     \n"
slouken@3186
   337
                         "     .set mips3       \n"
slouken@3186
   338
                         "     sc   $1, %1      \n"
slouken@3186
   339
                         "     beqz $1, 1b      \n"
slouken@3186
   340
                         "     sync             \n"
slouken@3186
   341
                         "2:                    \n"
slouken@3186
   342
                         "     .set pop         \n":"=&r"(rv), "=R"(*atomic)
slouken@3186
   343
                         :"R"(*atomic), "Jr"(oldvalue), "Jr"(newvalue)
slouken@3186
   344
                         :"memory");
slouken@3186
   345
    return (SDL_bool) rv;
bob@3180
   346
}
bob@3180
   347
bob@3180
   348
static __inline__ SDL_bool
slouken@3186
   349
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   350
                        void *newvalue)
slouken@3186
   351
{
slouken@3186
   352
    int rv;
slouken@3186
   353
    __asm__ __volatile__("     .set push        \n"
slouken@3186
   354
                         "     .set noat        \n" "     .set mips3       \n"
bob@3180
   355
# if defined(__mips64)
slouken@3186
   356
                         "1:   lld  %0, %2      \n"
bob@3180
   357
# else
slouken@3186
   358
                         "1:   ll   %0, %2      \n"
slouken@3186
   359
# endif
slouken@3186
   360
                         "     bne  %0, %z3, 2f \n" "     move $1, %z4     \n"
bob@3180
   361
# if defined(__mips64)
slouken@3186
   362
                         "     sc   $1, %1      \n"
bob@3180
   363
# else
slouken@3186
   364
                         "     scd  $1, %1      \n"
slouken@3186
   365
# endif
slouken@3186
   366
                         "     beqz $1, 1b      \n"
slouken@3186
   367
                         "     sync             \n"
slouken@3186
   368
                         "2:                    \n"
slouken@3186
   369
                         "     .set pop         \n":"=&r"(rv), "=R"(*atomic)
slouken@3186
   370
                         :"R"(*atomic), "Jr"(oldvalue), "Jr"(newvalue)
slouken@3186
   371
                         :"memory");
slouken@3186
   372
    return (SDL_bool) rv;
bob@3180
   373
}
bob@3180
   374
#elif defined(__GNUC__) && defined(__m68k__)
bob@3180
   375
static __inline__ int
slouken@3186
   376
SDL_atomic_int_xchg_add(volatile int *atomic, int value)
slouken@3186
   377
{
slouken@3186
   378
    int rv = *atomic;
slouken@3186
   379
    int tmp;
slouken@3186
   380
    __asm__ __volatile__("1: move%.l %0,%1    \n"
slouken@3186
   381
                         "   add%.l  %2,%1    \n"
slouken@3186
   382
                         "   cas%.l  %0,%1,%3 \n"
slouken@3186
   383
                         "   jbne    1b       \n":"=d"(rv), "=&d"(tmp)
slouken@3186
   384
                         :"d"(value), "m"(*atomic), "0"(rv)
slouken@3186
   385
                         :"memory");
slouken@3186
   386
    return (SDL_bool) rv;
bob@3180
   387
}
bob@3180
   388
bob@3180
   389
static __inline__ void
slouken@3186
   390
SDL_atomic_int_add(volatile int *atomic, int value)
slouken@3186
   391
{
slouken@3186
   392
    __asm__ __volatile__("add%.l %0,%1"::"id"(value), "m"(*atomic)
slouken@3186
   393
                         :"memory");
bob@3180
   394
}
bob@3180
   395
bob@3180
   396
static __inline__ SDL_bool
slouken@3186
   397
SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
slouken@3186
   398
{
slouken@3186
   399
    char rv;
slouken@3186
   400
    int readvalue;
slouken@3186
   401
    __asm__ __volatile__("cas%.l %2,%3,%1\n"
slouken@3186
   402
                         "seq    %0":"=dm"(rv), "=m"(*atomic), "=d"(readvalue)
slouken@3186
   403
                         :"d"(newvalue), "m"(*atomic), "2"(oldvalue));
slouken@3186
   404
    return (SDL_bool) rv;
bob@3180
   405
}
bob@3180
   406
bob@3180
   407
static __inline__ SDL_bool
slouken@3186
   408
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   409
                        void *newvalue)
bob@3180
   410
{
slouken@3186
   411
    char rv;
slouken@3186
   412
    int readvalue;
slouken@3186
   413
    __asm__ __volatile__("cas%.l %2,%3,%1\n"
slouken@3186
   414
                         "seq    %0":"=dm"(rv), "=m"(*atomic), "=d"(readvalue)
slouken@3186
   415
                         :"d"(newvalue), "m"(*atomic), "2"(oldvalue));
slouken@3186
   416
    return (SDL_bool) rv;
bob@3180
   417
}
bob@3180
   418
#elif defined(__GNUC__) && defined(__s390__)
bob@3180
   419
# define ATOMIC_INT_CMP_XCHG(atomic,oldvalue,newvalue)  \
bob@3180
   420
  ({                                                    \
bob@3180
   421
    int rv = oldvalue;                                  \
bob@3180
   422
    __asm__ __volatile__("cs %0, %2, %1"                \
bob@3180
   423
                         : "+d" (rv),                   \
bob@3180
   424
                           "=Q" (*(atomic))             \
bob@3180
   425
                         : "d" (newvalue),              \
bob@3180
   426
                           "m" (*(atomic))              \
bob@3180
   427
                         : "cc");                       \
bob@3180
   428
    rv == oldvalue;                                     \
bob@3180
   429
  })
bob@3180
   430
# if (SIZEOF_VOIDP == 4)
bob@3180
   431
static __inline__ SDL_bool
slouken@3186
   432
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   433
                        void *newvalue)
bob@3180
   434
{
slouken@3186
   435
    void *rv = oldvalue;
slouken@3186
   436
    __asm__ __volatile__("cs %0, %2, %1":"+d"(rv), "=Q"(*atomic)
slouken@3186
   437
                         :"d"(newvalue), "m"(*atomic)
slouken@3186
   438
                         :"cc");
slouken@3186
   439
    return (SDL_bool) (rv == oldvalue);
bob@3180
   440
}
bob@3180
   441
# elif (SIZEOF_VOIDP == 8)
bob@3180
   442
static __inline__ SDL_bool
slouken@3186
   443
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   444
                        void *newvalue)
bob@3180
   445
{
slouken@3186
   446
    void *rv = oldvalue;
slouken@3186
   447
    void **a = atomic;
slouken@3186
   448
    __asm__ __volatile__("csg %0, %2, %1":"+d"(rv), "=Q"(*a)
slouken@3186
   449
                         :"d"((long) (newvalue)), "m"(*a)
slouken@3186
   450
                         :"cc");
slouken@3186
   451
    return (SDL_bool) (rv == oldvalue);
bob@3180
   452
}
bob@3180
   453
# else
bob@3180
   454
#  error "Your system has an unsupported pointer size"
bob@3180
   455
# endif /* SIZEOF_VOIDP */
bob@3180
   456
#elif defined(__WIN32__)
bob@3180
   457
# include <windows.h>
bob@3180
   458
static __inline__ int
slouken@3186
   459
SDL_atomic_int_xchg_add(volatile int *atomic, int value)
bob@3180
   460
{
slouken@3186
   461
    return InterlockedExchangeAdd(atomic, value);
bob@3180
   462
}
bob@3180
   463
bob@3180
   464
static __inline__ void
slouken@3186
   465
SDL_atomic_int_add(volatile int *atomic, int value)
bob@3180
   466
{
slouken@3186
   467
    InterlockedExchangeAdd(atomic, value);
bob@3180
   468
}
bob@3180
   469
bob@3180
   470
# if (WINVER > 0X0400)
bob@3180
   471
static __inline__ SDL_bool
slouken@3186
   472
SDL_atmoic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
bob@3180
   473
{
slouken@3186
   474
    return (SDL_bool) (InterlockedCompareExchangePointer((PVOID *) atomic,
slouken@3186
   475
                                                         (PVOID) newvalue,
slouken@3186
   476
                                                         (PVOID) oldvalue) ==
slouken@3186
   477
                       oldvalue);
bob@3180
   478
}
bob@3180
   479
bob@3180
   480
bob@3180
   481
static __inline__ SDL_bool
slouken@3186
   482
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   483
                        void *newvalue)
bob@3180
   484
{
slouken@3186
   485
    return (InterlockedCompareExchangePointer(atomic, newvalue, oldvalue) ==
slouken@3186
   486
            oldvalue);
bob@3180
   487
}
bob@3180
   488
# else /* WINVER <= 0x0400 */
bob@3180
   489
#  if (SIZEOF_VOIDP != 4)
bob@3180
   490
#   error "InterlockedCompareExchangePointer needed"
bob@3180
   491
#  endif
bob@3180
   492
bob@3180
   493
static __inline__ SDL_bool
slouken@3186
   494
SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
bob@3180
   495
{
slouken@3186
   496
    return (InterlockedCompareExchange(atomic, newvalue, oldvalue) ==
slouken@3186
   497
            oldvalue);
bob@3180
   498
}
bob@3180
   499
bob@3180
   500
static __inline__ SDL_bool
slouken@3186
   501
SDL_atomic_ptr_cmp_xchg(volatile void **atomic, void *oldvalue,
slouken@3186
   502
                        void *newvalue)
bob@3180
   503
{
slouken@3186
   504
    return (InterlockedCompareExchange(atomic, newvalue, oldvalue) ==
slouken@3186
   505
            oldvalue);
bob@3180
   506
}
bob@3180
   507
# endif
bob@3180
   508
#else /* when all else fails */
bob@3180
   509
# define SDL_ATOMIC_OPS_NOT_SUPPORTED
bob@3180
   510
# warning "Atomic Ops for this platform not supported!"
bob@3180
   511
static __inline__ int
slouken@3186
   512
SDL_atomic_int_xchg_add(volatile int *atomic, int value)
slouken@3186
   513
{
slouken@3186
   514
    int rv = *atomic;
slouken@3186
   515
    *(atomic) += value;
slouken@3186
   516
    return rv;
bob@3180
   517
}
bob@3180
   518
bob@3180
   519
static __inline__ SDL_bool
slouken@3186
   520
SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
bob@3180
   521
{
slouken@3186
   522
    return (*atomic == oldvalue) ?
slouken@3186
   523
        ((*atomic = newvalue), SDL_TRUE) : SDL_FALSE;
bob@3180
   524
}
bob@3180
   525
bob@3180
   526
static __inline__ void
slouken@3186
   527
SDL_atomic_int_add(volatile int *atomic, int value)
bob@3180
   528
{
slouken@3186
   529
    *atomic += value;
bob@3180
   530
}
bob@3180
   531
#endif /* arch & platforms */
slouken@3186
   532
bob@3180
   533
#ifdef ATOMIC_INT_CMP_XCHG
bob@3180
   534
static __inline__ SDL_bool
slouken@3186
   535
SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
bob@3180
   536
{
slouken@3186
   537
    return (SDL_bool) ATOMIC_INT_CMP_XCHG(atomic, oldvalue, newvalue);
bob@3180
   538
}
bob@3180
   539
bob@3180
   540
static __inline__ int
slouken@3186
   541
SDL_atomic_int_xchg_add(volatile int *atomic, int value)
slouken@3186
   542
{
slouken@3186
   543
    int rv;
slouken@3186
   544
    do
slouken@3186
   545
        rv = *atomic;
slouken@3186
   546
    while (!ATOMIC_INT_CMP_XCHG(atomic, rv, rv + value));
slouken@3186
   547
    return rv;
bob@3180
   548
}
bob@3180
   549
bob@3180
   550
static __inline__ void
slouken@3186
   551
SDL_atomic_int_add(volatile int *atomic, int value)
bob@3180
   552
{
slouken@3186
   553
    int rv;
slouken@3186
   554
    do
slouken@3186
   555
        rv = *atomic;
slouken@3186
   556
    while (!ATOMIC_INT_CMP_XCHG(atomic, rv, rv + value));
bob@3180
   557
}
bob@3180
   558
#endif /* ATOMIC_CMP_XCHG */
bob@3180
   559
bob@3180
   560
#ifdef ATOMIC_MEMORY_BARRIER
bob@3180
   561
# define SDL_atomic_int_get(atomic) \
bob@3180
   562
  (ATOMIC_MEMORY_BARRIER,*(atomic))
bob@3180
   563
# define SDL_atomic_int_set(atomic,value) \
bob@3180
   564
  (*(atomic)=value,ATOMIC_MEMORY_BARRIER)
bob@3180
   565
#else
bob@3180
   566
# define SDL_atomic_int_get(atomic) (*(atomic))
bob@3180
   567
# define SDL_atomic_int_set(atomic, newvalue) ((void)(*(atomic) = (newvalue)))
bob@3180
   568
#endif /* MEMORY_BARRIER_NEEDED */
bob@3180
   569
bob@3180
   570
#define SDL_atomic_int_inc(atomic) (SDL_atomic_int_add((atomic),1))
bob@3180
   571
#define SDL_atomic_int_dec_test(atomic) (SDL_atomic_int_xchg_add((atomic),-1) == 1)
bob@3180
   572
bob@3180
   573
/* Ends C function definitions when using C++ */
bob@3180
   574
#ifdef __cplusplus
bob@3180
   575
/* *INDENT-OFF* */
bob@3180
   576
}
bob@3180
   577
/* *INDENT-ON* */
bob@3180
   578
#endif
bob@3180
   579
bob@3180
   580
#include "close_code.h"
bob@3180
   581
bob@3180
   582
#endif /* _SDL_atomic_h_ */
bob@3180
   583
bob@3180
   584
/* vi: set ts=4 sw=4 expandtab: */