include/SDL_atomic.h
author Sam Lantinga <slouken@libsdl.org>
Wed, 10 Jun 2009 13:38:19 +0000
changeset 3187 e041d2c603fe
parent 3186 51750b7a966f
child 3199 3e1bf2b8bd81
permissions -rw-r--r--
indent is really bad at handling assembly
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
slouken@3187
    45
/* indent is really bad at handling assembly */
slouken@3187
    46
/* *INDENT-OFF* */
slouken@3187
    47
bob@3180
    48
#if defined(__GNUC__) && (defined(i386) || defined(__i386__)  || defined(__x86_64__))
bob@3180
    49
static __inline__ void
slouken@3187
    50
SDL_atomic_int_add(volatile int* atomic, int value)
bob@3180
    51
{
slouken@3187
    52
  __asm__ __volatile__("lock;"
slouken@3187
    53
                       "addl %1, %0"
slouken@3187
    54
                       : "=m" (*atomic)
slouken@3187
    55
                       : "ir" (value),
slouken@3187
    56
                         "m" (*atomic));
bob@3180
    57
}
bob@3180
    58
bob@3180
    59
static __inline__ int
slouken@3187
    60
SDL_atomic_int_xchg_add(volatile int* atomic, int value)
slouken@3187
    61
{                                              
slouken@3187
    62
  int rv;                                    
slouken@3187
    63
  __asm__ __volatile__("lock;"               
slouken@3187
    64
                       "xaddl %0, %1"        
slouken@3187
    65
                       : "=r" (rv),          
slouken@3187
    66
                         "=m" (*atomic)    
slouken@3187
    67
                       : "0" (value),        
slouken@3187
    68
                         "m" (*atomic));   
slouken@3187
    69
  return rv;                                        
bob@3180
    70
}
bob@3180
    71
bob@3180
    72
static __inline__ SDL_bool
slouken@3187
    73
SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
bob@3180
    74
{
slouken@3187
    75
  int rv;                                                      
slouken@3187
    76
  __asm__ __volatile__("lock;"                               
slouken@3187
    77
                       "cmpxchgl %2, %1"                     
slouken@3187
    78
                       : "=a" (rv),                          
slouken@3187
    79
                         "=m" (*atomic)             
slouken@3187
    80
                       : "r" (newvalue),                     
slouken@3187
    81
                         "m" (*atomic),                    
slouken@3187
    82
                         "0" (oldvalue));
slouken@3187
    83
  return (SDL_bool)(rv == oldvalue);                                          
bob@3180
    84
}
bob@3180
    85
bob@3180
    86
static __inline__ SDL_bool
slouken@3187
    87
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
    88
{
slouken@3187
    89
  void* rv;
slouken@3187
    90
  __asm__ __volatile__("lock;"
slouken@3187
    91
# if defined(__x86_64__)                       
slouken@3187
    92
                       "cmpxchgq %q2, %1"
bob@3180
    93
# else
slouken@3187
    94
                       "cmpxchgl %2, %1"
slouken@3187
    95
# endif                       
slouken@3187
    96
                       : "=a" (rv),
slouken@3187
    97
                         "=m" (*atomic)
slouken@3187
    98
                       : "r" (newvalue),
slouken@3187
    99
                         "m" (*atomic),
slouken@3187
   100
                         "0" (oldvalue));
slouken@3187
   101
  return (SDL_bool)(rv == oldvalue);
bob@3180
   102
}
bob@3180
   103
#elif defined(__GNUC__) && defined(__alpha__)
bob@3180
   104
# define ATOMIC_MEMORY_BARRIER (__asm__ __volatile__ ("mb" : : : "memory"))
bob@3180
   105
# define ATOMIC_INT_CMP_XCHG(atomic,value)              \
bob@3180
   106
  ({                                                    \
bob@3180
   107
    int rv,prev;                                        \
bob@3180
   108
    __asm__ __volatile__("   mb\n"                      \
bob@3180
   109
                         "1: ldl_l   %0,%2\n"           \
bob@3180
   110
                         "   cmpeq   %0,%3,%1\n"        \
bob@3180
   111
                         "   beq     %1,2f\n"           \
bob@3180
   112
                         "   mov     %4,%1\n"           \
bob@3180
   113
                         "   stl_c   %1,%2\n"           \
bob@3180
   114
                         "   beq     %1,1b\n"           \
bob@3180
   115
                         "   mb\n"                      \
bob@3180
   116
                         "2:"                           \
bob@3180
   117
                         : "=&r" (prev),                \
bob@3180
   118
                           "=&r" (rv)                   \
bob@3180
   119
                         : "m" (*(atomic)),             \
bob@3180
   120
                           "Ir" (oldvalue),             \
bob@3180
   121
                           "Ir" (newvalue)              \
bob@3180
   122
                         : "memory");                   \
bob@3180
   123
    (rv != 0);                                          \
bob@3180
   124
  })
bob@3180
   125
bob@3180
   126
# if (SIZEOF_VOIDP == 4)
bob@3180
   127
static __inline__ SDL_bool
slouken@3187
   128
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   129
{
slouken@3187
   130
  int rv;
slouken@3187
   131
  void* prev;
slouken@3187
   132
  __asm__ __volatile__("   mb\n"
slouken@3187
   133
                       "1: ldl_l %0,%2\n"
slouken@3187
   134
                       "   cmpeq %0,%3,%1\n"
slouken@3187
   135
                       "   beq   $1,2f\n"
slouken@3187
   136
                       "   mov   %4,%1\n"
slouken@3187
   137
                       "   stl_c %1,%2\n"
slouken@3187
   138
                       "   beq   %1,1b\n"
slouken@3187
   139
                       "   mb\n"
slouken@3187
   140
                       "2:"
slouken@3187
   141
                       : "=&r" (prev),
slouken@3187
   142
                         "=&r" (rv)
slouken@3187
   143
                       : "m" (*atomic),
slouken@3187
   144
                         "Ir" (oldvalue),
slouken@3187
   145
                         "Ir" (newvalue)
slouken@3187
   146
                       : "memory");
slouken@3187
   147
  return (SDL_bool)(rv != 0);
bob@3180
   148
}
bob@3180
   149
# elif (SIZEOF_VOIDP == 8)
bob@3180
   150
static __inline__ SDL_bool
slouken@3187
   151
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   152
{
slouken@3187
   153
  int rv;
slouken@3187
   154
  void* prev;
slouken@3187
   155
  __asm__ __volatile__("   mb\n"
slouken@3187
   156
                       "1: ldq_l %0,%2\n"
slouken@3187
   157
                       "   cmpeq %0,%3,%1\n"
slouken@3187
   158
                       "   beq   %1,2f\n"
slouken@3187
   159
                       "   mov   %4,%1\n"
slouken@3187
   160
                       "   stq_c %1,%2\n"
slouken@3187
   161
                       "   beq   %1,1b\n"
slouken@3187
   162
                       "   mb\n"
slouken@3187
   163
                       "2:"
slouken@3187
   164
                       : "=&r" (prev),
slouken@3187
   165
                         "=&r" (rv)
slouken@3187
   166
                       : "m" (*atomic),
slouken@3187
   167
                         "Ir" (oldvalue),
slouken@3187
   168
                         "Ir" (newvalue)
slouken@3187
   169
                       : "memory");
slouken@3187
   170
  return (SDL_bool)(rv != 0);
bob@3180
   171
}
bob@3180
   172
# else
slouken@3187
   173
#  error "Your system has an unsupported pointer size"  
slouken@3187
   174
# endif  /* SIZEOF_VOIDP */
bob@3180
   175
#elif defined(__GNUC__) && defined(__sparc__)
bob@3180
   176
# define ATOMIC_MEMORY_BARRIER                                          \
bob@3180
   177
  (__asm__ __volatile__("membar #LoadLoad | #LoadStore"                 \
bob@3180
   178
                        " | #StoreLoad | #StoreStore" : : : "memory"))
bob@3180
   179
# define ATOMIC_INT_CMP_XCHG(atomic,oldvalue,newvalue)                  \
bob@3180
   180
  ({                                                                    \
bob@3180
   181
    int rv;                                                             \
bob@3180
   182
    __asm__ __volatile__("cas [%4], %2, %0"                             \
bob@3180
   183
                         : "=r" (rv), "=m" (*(atomic))                  \
bob@3180
   184
                         : "r" (oldvalue), "m" (*(atomic)),             \
bob@3180
   185
                         "r" (atomic), "0" (newvalue));                 \
bob@3180
   186
    rv == oldvalue;                                                     \
bob@3180
   187
  })
bob@3180
   188
bob@3180
   189
# if (SIZEOF_VOIDP == 4)
bob@3180
   190
static __inline__ SDL_bool
slouken@3187
   191
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   192
{
slouken@3187
   193
  void* rv;
slouken@3187
   194
  __asm__ __volatile__("cas [%4], %2, %0"
slouken@3187
   195
                       : "=r" (rv),
slouken@3187
   196
                         "=m" (*atomic)
slouken@3187
   197
                       : "r" (oldvalue),
slouken@3187
   198
                         "m" (*atomic),
slouken@3187
   199
                         "r" (atomic),
slouken@3187
   200
                         "0" (newvalue));
slouken@3187
   201
  return (SDL_bool)(rv == oldvalue);
bob@3180
   202
}
bob@3180
   203
# elif (SIZEOF_VOIDP == 8)
bob@3180
   204
static __inline__ SDL_bool
slouken@3187
   205
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   206
{
slouken@3187
   207
  void* rv;
slouken@3187
   208
  void** a = atomic;
slouken@3187
   209
  __asm__ __volatile__("casx [%4], %2, %0"
slouken@3187
   210
                       : "=r" (rv),
slouken@3187
   211
                         "=m" (*a)
slouken@3187
   212
                       : "r" (oldvalue),
slouken@3187
   213
                         "m" (*a),
slouken@3187
   214
                         "r" (a),
slouken@3187
   215
                         "0" (newvalue));
slouken@3187
   216
  return (SDL_bool)(rv == oldvalue);
bob@3180
   217
}
bob@3180
   218
# else
bob@3180
   219
#  error "Your system has an unsupported pointer size"
bob@3180
   220
# endif /* SIZEOF_VOIDP */
bob@3180
   221
#elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC))
bob@3180
   222
# define ATOMIC_MEMORY_BARRIER \
bob@3180
   223
  (__asm__ __volatile__ ("sync" : : : "memory"))
bob@3180
   224
static __inline__ void
slouken@3187
   225
SDL_atomic_int_add(volatile int* atomic, int value)
slouken@3187
   226
{                                           
slouken@3187
   227
  int rv,tmp;                                   
slouken@3187
   228
  __asm__ __volatile__("1: lwarx   %0,  0, %3\n" 
slouken@3187
   229
                       "   add     %1, %0, %4\n"
slouken@3187
   230
                       "   stwcx.  %1,  0, %3\n" 
slouken@3187
   231
                       "   bne-    1b"          
slouken@3187
   232
                       : "=&b" (rv),            
slouken@3187
   233
                         "=&r" (tmp),           
slouken@3187
   234
                         "=m" (*atomic)       
slouken@3187
   235
                       : "b" (atomic),          
slouken@3187
   236
                         "r" (value),           
slouken@3187
   237
                         "m" (*atomic)        
slouken@3187
   238
                       : "cr0",                 
slouken@3187
   239
                         "memory");             
bob@3180
   240
}
bob@3180
   241
bob@3180
   242
static __inline__ int
slouken@3187
   243
SDL_atomic_int_xchg_add(volatile int* atomic, int value)
slouken@3187
   244
{                                          
slouken@3187
   245
  int rv,tmp;                               
slouken@3187
   246
  __asm__ __volatile__("1: lwarx  %0, 0, %3\n"        
slouken@3187
   247
                       "   add    %1, %0, %4\n"       
slouken@3187
   248
                       "   stwcx. %1, 0, %3\n"        
slouken@3187
   249
                       "   bne-   1b"                 
slouken@3187
   250
                       : "=&b" (rv),                  
slouken@3187
   251
                         "=&r" (tmp),                 
slouken@3187
   252
                         "=m" (*atomic)
slouken@3187
   253
                       : "b" (atomic),                
slouken@3187
   254
                         "r" (value),                 
slouken@3187
   255
                         "m" (*atomic)
slouken@3187
   256
                       : "cr0",                       
slouken@3187
   257
                       "memory");                   
slouken@3187
   258
  return rv;                                                 
bob@3180
   259
}
bob@3180
   260
bob@3180
   261
# if (SIZEOF_VOIDP == 4)
bob@3180
   262
static __inline__ SDL_bool
slouken@3187
   263
SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
slouken@3187
   264
{                                                        
slouken@3187
   265
  int rv;                                                 
slouken@3187
   266
  __asm__ __volatile__("   sync\n"                         
slouken@3187
   267
                       "1: lwarx   %0, 0, %1\n"           
slouken@3187
   268
                       "   subf.   %0, %2, %0\n"          
slouken@3187
   269
                       "   bne     2f\n"                  
slouken@3187
   270
                       "   stwcx.  %3, 0, %1\n"           
slouken@3187
   271
                       "   bne-    1b\n"                  
slouken@3187
   272
                       "2: isync"                         
slouken@3187
   273
                       : "=&r" (rv)                       
slouken@3187
   274
                       : "b" (atomic),                    
slouken@3187
   275
                         "r" (oldvalue),                  
slouken@3187
   276
                         "r"                              
slouken@3187
   277
                       : "cr0",                           
slouken@3187
   278
                         "memory");                         
slouken@3187
   279
  return (SDL_bool)(rv == 0);                                              
bob@3180
   280
}
bob@3180
   281
bob@3180
   282
static __inline__ SDL_bool
slouken@3187
   283
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   284
{
slouken@3187
   285
  void* rv;
slouken@3187
   286
  __asm__ __volatile__("sync\n"
slouken@3187
   287
                       "1: lwarx  %0,  0, %1\n"
slouken@3187
   288
                       "   subf.  %0, %2, %0\n"
slouken@3187
   289
                       "   bne    2f\n"
slouken@3187
   290
                       "   stwcx. %3,  0, %1\n"
slouken@3187
   291
                       "   bne-   1b\n"
slouken@3187
   292
                       "2: isync"
slouken@3187
   293
                       : "=&r" (rv)
slouken@3187
   294
                       : "b" (atomic),
slouken@3187
   295
                         "r" (oldvalue),
slouken@3187
   296
                         "r" (newvalue)
slouken@3187
   297
                       : "cr0",
slouken@3187
   298
                       "memory");
slouken@3187
   299
  return (SDL_bool)(rv == 0);
bob@3180
   300
}
bob@3180
   301
# elif (SIZEOF_VOIDP == 8)
bob@3180
   302
static __inline__ SDL_bool
slouken@3187
   303
SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
slouken@3187
   304
{                                                        
slouken@3187
   305
  int rv;                                                 
slouken@3187
   306
  __asm__ __volatile__("   sync\n"                         
slouken@3187
   307
                       "1: lwarx   %0,  0, %1\n"
slouken@3187
   308
                       "   extsw   %0, %0\n"
slouken@3187
   309
                       "   subf.   %0, %2, %0\n"          
slouken@3187
   310
                       "   bne     2f\n"                  
slouken@3187
   311
                       "   stwcx.  %3,  0, %1\n"           
slouken@3187
   312
                       "   bne-    1b\n"                  
slouken@3187
   313
                       "2: isync"                         
slouken@3187
   314
                       : "=&r" (rv)                       
slouken@3187
   315
                       : "b" (atomic),                    
slouken@3187
   316
                         "r" (oldvalue),                  
slouken@3187
   317
                         "r"                              
slouken@3187
   318
                       : "cr0",                           
slouken@3187
   319
                         "memory");                         
slouken@3187
   320
  return (SDL_bool)(rv == 0);                                              
bob@3180
   321
}
bob@3180
   322
bob@3180
   323
static __inline__ SDL_bool
slouken@3187
   324
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   325
{
slouken@3187
   326
  void* rv;
slouken@3187
   327
  __asm__ __volatile__("sync\n"
slouken@3187
   328
                       "1: ldarx  %0,  0, %1\n"
slouken@3187
   329
                       "   subf.  %0, %2, %0\n"
slouken@3187
   330
                       "   bne    2f\n"
slouken@3187
   331
                       "   stdcx. %3,  0, %1\n"
slouken@3187
   332
                       "   bne-   1b\n"
slouken@3187
   333
                       "2: isync"
slouken@3187
   334
                       : "=&r" (rv)
slouken@3187
   335
                       : "b" (atomic),
slouken@3187
   336
                         "r" (oldvalue),
slouken@3187
   337
                         "r" (newvalue)
slouken@3187
   338
                       : "cr0",
slouken@3187
   339
                       "memory");
slouken@3187
   340
  return (SDL_bool)(rv == 0);
bob@3180
   341
}
bob@3180
   342
# else
bob@3180
   343
#  error "Your system has an unsupported pointer size"
bob@3180
   344
# endif /* SIZEOF_VOIDP */
bob@3180
   345
#elif defined(__GNUC__) && (defined(__IA64__) || defined(__ia64__))
bob@3180
   346
# define ATOMIC_MEMORY_BARRIER (__sync_synchronize())
bob@3180
   347
# define SDL_atomic_int_xchg_add(atomic, value)     \
bob@3180
   348
  (__sync_fetch_and_add((atomic),(value)))
bob@3180
   349
# define SDL_atomic_int_add(atomic, value)                  \
bob@3180
   350
  ((void)__sync_fetch_and_add((atomic),(value)))
bob@3180
   351
# define SDL_atomic_int_cmp_xchg(atomic,oldvalue,newvalue)  \
bob@3180
   352
  (__sync_bool_compare_and_swap((atomic),(oldvalue),(newvalue)))
bob@3180
   353
# define SDL_atomic_ptr_cmp_xchg(atomic,oldvalue,newvalue)              \
bob@3180
   354
  (__sync_bool_compare_and_swap((long*)(atomic),(long)(oldvalue),(long)(newvalue)))
bob@3180
   355
#elif defined(__GNUC__) && defined(__LINUX__) && (defined(__mips__) || defined(__MIPS__))
bob@3180
   356
static __inline__ int
slouken@3187
   357
SDL_atomic_int_xchg_add(volatile int* atomic, int value)
slouken@3187
   358
{                                            
slouken@3187
   359
  int rv,tmp;                                 
slouken@3187
   360
  __asm__ __volatile__("1:              \n"                 
slouken@3187
   361
                       ".set  push      \n"         
slouken@3187
   362
                       ".set  mips2     \n"        
slouken@3187
   363
                       "ll    %0,%3     \n"        
slouken@3187
   364
                       "addu  %1,%4,%0  \n"     
slouken@3187
   365
                       "sc    %1,%2     \n"        
slouken@3187
   366
                       ".set  pop       \n"          
slouken@3187
   367
                       "beqz  %1,1b     \n"        
slouken@3187
   368
                       : "=&r" (rv),          
slouken@3187
   369
                         "=&r" (tmp),         
slouken@3187
   370
                         "=m" (*atomic)     
slouken@3187
   371
                       : "m" (*atomic),     
slouken@3187
   372
                         "r" (value)          
slouken@3187
   373
                       : "memory");           
slouken@3187
   374
  return rv;                                         
bob@3180
   375
}
bob@3180
   376
bob@3180
   377
static __inline__ void
slouken@3187
   378
SDL_atomic_int_add(volatile int* atomic, int value)
slouken@3187
   379
{                                           
slouken@3187
   380
  int rv;                                    
slouken@3187
   381
  __asm__ __volatile__("1:               \n"                
slouken@3187
   382
                       ".set  push       \n"        
slouken@3187
   383
                       ".set  mips2      \n"       
slouken@3187
   384
                       "ll    %0,%2      \n"       
slouken@3187
   385
                       "addu  %0,%3,%0   \n"    
slouken@3187
   386
                       "sc    %0,%1      \n"       
slouken@3187
   387
                       ".set  pop        \n"         
slouken@3187
   388
                       "beqz  %0,1b      \n"       
slouken@3187
   389
                       : "=&r" (rv),         
slouken@3187
   390
                         "=m" (*atomic)    
slouken@3187
   391
                       : "m" (*atomic),    
slouken@3187
   392
                         "r" (value)         
slouken@3187
   393
                       : "memory");          
bob@3180
   394
}
bob@3180
   395
bob@3180
   396
static __inline__ SDL_bool
slouken@3187
   397
SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
bob@3180
   398
{
slouken@3187
   399
  int rv;
slouken@3187
   400
  __asm__ __volatile__("     .set push        \n"
slouken@3187
   401
                       "     .set noat        \n"
slouken@3187
   402
                       "     .set mips3       \n"
slouken@3187
   403
                       "1:   ll   %0, %2      \n"
slouken@3187
   404
                       "     bne  %0, %z3, 2f \n"
slouken@3187
   405
                       "     .set mips0       \n"
slouken@3187
   406
                       "     move $1, %z4     \n"
slouken@3187
   407
                       "     .set mips3       \n"
slouken@3187
   408
                       "     sc   $1, %1      \n"
slouken@3187
   409
                       "     beqz $1, 1b      \n"
slouken@3187
   410
                       "     sync             \n"
slouken@3187
   411
                       "2:                    \n"
slouken@3187
   412
                       "     .set pop         \n"
slouken@3187
   413
                       : "=&r" (rv),
slouken@3187
   414
                         "=R" (*atomic)
slouken@3187
   415
                       : "R" (*atomic),
slouken@3187
   416
                         "Jr" (oldvalue),
slouken@3187
   417
                         "Jr" (newvalue)
slouken@3187
   418
                       : "memory");
slouken@3187
   419
  return (SDL_bool)rv;                  
bob@3180
   420
}
bob@3180
   421
bob@3180
   422
static __inline__ SDL_bool
slouken@3187
   423
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
slouken@3187
   424
{                                                     
slouken@3187
   425
  int rv;
slouken@3187
   426
  __asm__ __volatile__("     .set push        \n"
slouken@3187
   427
                       "     .set noat        \n"
slouken@3187
   428
                       "     .set mips3       \n"
bob@3180
   429
# if defined(__mips64)
slouken@3187
   430
                       "1:   lld  %0, %2      \n"
bob@3180
   431
# else
slouken@3187
   432
                       "1:   ll   %0, %2      \n"
slouken@3187
   433
# endif                       
slouken@3187
   434
                       "     bne  %0, %z3, 2f \n"
slouken@3187
   435
                       "     move $1, %z4     \n"
bob@3180
   436
# if defined(__mips64)
slouken@3187
   437
                       "     sc   $1, %1      \n"
bob@3180
   438
# else
slouken@3187
   439
                       "     scd  $1, %1      \n"
slouken@3187
   440
# endif                       
slouken@3187
   441
                       "     beqz $1, 1b      \n"
slouken@3187
   442
                       "     sync             \n"
slouken@3187
   443
                       "2:                    \n"
slouken@3187
   444
                       "     .set pop         \n"
slouken@3187
   445
                       : "=&r" (rv),
slouken@3187
   446
                         "=R" (*atomic)
slouken@3187
   447
                       : "R" (*atomic),
slouken@3187
   448
                         "Jr" (oldvalue),
slouken@3187
   449
                         "Jr" (newvalue)
slouken@3187
   450
                       : "memory");
slouken@3187
   451
  return (SDL_bool)rv;                                                  
bob@3180
   452
}
bob@3180
   453
#elif defined(__GNUC__) && defined(__m68k__)
bob@3180
   454
static __inline__ int
slouken@3187
   455
SDL_atomic_int_xchg_add(volatile int* atomic, int value)
slouken@3187
   456
{                                          
slouken@3187
   457
  int rv = *atomic;
slouken@3187
   458
  int tmp;
slouken@3187
   459
  __asm__ __volatile__("1: move%.l %0,%1    \n"
slouken@3187
   460
                       "   add%.l  %2,%1    \n"
slouken@3187
   461
                       "   cas%.l  %0,%1,%3 \n"
slouken@3187
   462
                       "   jbne    1b       \n"
slouken@3187
   463
                       : "=d" (rv),
slouken@3187
   464
                         "=&d" (tmp)
slouken@3187
   465
                       : "d" (value),
slouken@3187
   466
                         "m" (*atomic),
slouken@3187
   467
                         "0" (rv)
slouken@3187
   468
                       : "memory");
slouken@3187
   469
  return (SDL_bool)rv;
bob@3180
   470
}
bob@3180
   471
bob@3180
   472
static __inline__ void
slouken@3187
   473
SDL_atomic_int_add(volatile int* atomic, int value)
slouken@3187
   474
{                                           
slouken@3187
   475
  __asm__ __volatile__("add%.l %0,%1"        
slouken@3187
   476
                       :                     
slouken@3187
   477
                       : "id" (value),       
slouken@3187
   478
                         "m" (*atomic)
slouken@3187
   479
                       : "memory");          
bob@3180
   480
}
bob@3180
   481
bob@3180
   482
static __inline__ SDL_bool
slouken@3187
   483
SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
slouken@3187
   484
{                                           
slouken@3187
   485
  char rv;                                   
slouken@3187
   486
  int readvalue;                             
slouken@3187
   487
  __asm__ __volatile__("cas%.l %2,%3,%1\n"   
slouken@3187
   488
                       "seq    %0"           
slouken@3187
   489
                       : "=dm" (rv),         
slouken@3187
   490
                         "=m" (*atomic),   
slouken@3187
   491
                         "=d" (readvalue)    
slouken@3187
   492
                       : "d" (newvalue),     
slouken@3187
   493
                         "m" (*atomic),    
slouken@3187
   494
                         "2" (oldvalue));    
slouken@3187
   495
    return (SDL_bool)rv;                                        
bob@3180
   496
}
bob@3180
   497
bob@3180
   498
static __inline__ SDL_bool
slouken@3187
   499
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   500
{
slouken@3187
   501
  char rv;                                   
slouken@3187
   502
  int readvalue;                             
slouken@3187
   503
  __asm__ __volatile__("cas%.l %2,%3,%1\n"   
slouken@3187
   504
                       "seq    %0"           
slouken@3187
   505
                       : "=dm" (rv),         
slouken@3187
   506
                         "=m" (*atomic),   
slouken@3187
   507
                         "=d" (readvalue)    
slouken@3187
   508
                       : "d" (newvalue),     
slouken@3187
   509
                         "m" (*atomic),    
slouken@3187
   510
                         "2" (oldvalue));    
slouken@3187
   511
    return (SDL_bool)rv;                                        
bob@3180
   512
}
bob@3180
   513
#elif defined(__GNUC__) && defined(__s390__)
bob@3180
   514
# define ATOMIC_INT_CMP_XCHG(atomic,oldvalue,newvalue)  \
bob@3180
   515
  ({                                                    \
bob@3180
   516
    int rv = oldvalue;                                  \
bob@3180
   517
    __asm__ __volatile__("cs %0, %2, %1"                \
bob@3180
   518
                         : "+d" (rv),                   \
bob@3180
   519
                           "=Q" (*(atomic))             \
bob@3180
   520
                         : "d" (newvalue),              \
bob@3180
   521
                           "m" (*(atomic))              \
bob@3180
   522
                         : "cc");                       \
bob@3180
   523
    rv == oldvalue;                                     \
bob@3180
   524
  })
bob@3180
   525
# if (SIZEOF_VOIDP == 4)
bob@3180
   526
static __inline__ SDL_bool
slouken@3187
   527
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   528
{
slouken@3187
   529
  void* rv = oldvalue;
slouken@3187
   530
  __asm__ __volatile__("cs %0, %2, %1"
slouken@3187
   531
                       : "+d" (rv),
slouken@3187
   532
                         "=Q" (*atomic)
slouken@3187
   533
                       : "d" (newvalue),
slouken@3187
   534
                         "m" (*atomic)
slouken@3187
   535
                       : "cc");
slouken@3187
   536
  return (SDL_bool)(rv == oldvalue);
bob@3180
   537
}
bob@3180
   538
# elif (SIZEOF_VOIDP == 8)
bob@3180
   539
static __inline__ SDL_bool
slouken@3187
   540
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   541
{
slouken@3187
   542
  void* rv = oldvalue;
slouken@3187
   543
  void** a = atomic;
slouken@3187
   544
  __asm__ __volatile__("csg %0, %2, %1"
slouken@3187
   545
                       : "+d" (rv),
slouken@3187
   546
                         "=Q" (*a)
slouken@3187
   547
                       : "d" ((long)(newvalue)),
slouken@3187
   548
                         "m" (*a)
slouken@3187
   549
                       : "cc");
slouken@3187
   550
  return (SDL_bool)(rv == oldvalue);
bob@3180
   551
}
bob@3180
   552
# else
bob@3180
   553
#  error "Your system has an unsupported pointer size"
bob@3180
   554
# endif /* SIZEOF_VOIDP */
bob@3180
   555
#elif defined(__WIN32__)
bob@3180
   556
# include <windows.h>
bob@3180
   557
static __inline__ int
slouken@3187
   558
SDL_atomic_int_xchg_add(volatile int* atomic, int value)
bob@3180
   559
{
slouken@3187
   560
  return InterlockedExchangeAdd(atomic, value);
bob@3180
   561
}
bob@3180
   562
bob@3180
   563
static __inline__ void
slouken@3187
   564
SDL_atomic_int_add(volatile int* atomic, int value)
bob@3180
   565
{
slouken@3187
   566
  InterlockedExchangeAdd(atomic, value);
bob@3180
   567
}
bob@3180
   568
bob@3180
   569
# if (WINVER > 0X0400)
bob@3180
   570
static __inline__ SDL_bool
slouken@3187
   571
SDL_atmoic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
bob@3180
   572
{
slouken@3187
   573
   return (SDL_bool)(InterlockedCompareExchangePointer((PVOID*)atomic,
slouken@3187
   574
                                                       (PVOID)newvalue,
slouken@3187
   575
                                                       (PVOID)oldvalue) == oldvalue);
bob@3180
   576
}
bob@3180
   577
bob@3180
   578
bob@3180
   579
static __inline__ SDL_bool
slouken@3187
   580
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   581
{
slouken@3187
   582
  return (InterlockedCompareExchangePointer(atomic, newvalue, oldvalue) == oldvalue);
bob@3180
   583
}
bob@3180
   584
# else /* WINVER <= 0x0400 */
bob@3180
   585
#  if (SIZEOF_VOIDP != 4)
bob@3180
   586
#   error "InterlockedCompareExchangePointer needed"
bob@3180
   587
#  endif
bob@3180
   588
bob@3180
   589
static __inline__ SDL_bool
slouken@3187
   590
SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
bob@3180
   591
{
slouken@3187
   592
  return (InterlockedCompareExchange(atomic, newvalue, oldvalue) == oldvalue);
bob@3180
   593
}
bob@3180
   594
bob@3180
   595
static __inline__ SDL_bool
slouken@3187
   596
SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
bob@3180
   597
{
slouken@3187
   598
  return (InterlockedCompareExchange(atomic, newvalue, oldvalue) == oldvalue);
bob@3180
   599
}
bob@3180
   600
# endif
bob@3180
   601
#else /* when all else fails */
bob@3180
   602
# define SDL_ATOMIC_OPS_NOT_SUPPORTED
bob@3180
   603
# warning "Atomic Ops for this platform not supported!"
bob@3180
   604
static __inline__ int
slouken@3187
   605
SDL_atomic_int_xchg_add(volatile int* atomic, int value)
slouken@3187
   606
{                                           
slouken@3187
   607
  int rv = *atomic;                          
slouken@3187
   608
  *(atomic) += value;                        
slouken@3187
   609
  return rv;                                        
bob@3180
   610
}
bob@3180
   611
bob@3180
   612
static __inline__ SDL_bool
slouken@3187
   613
SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
bob@3180
   614
{
slouken@3187
   615
  return (*atomic == oldvalue) ?  
slouken@3187
   616
    ((*atomic = newvalue), SDL_TRUE) : SDL_FALSE;
bob@3180
   617
}
bob@3180
   618
bob@3180
   619
static __inline__ void
slouken@3187
   620
SDL_atomic_int_add(volatile int* atomic, int value)
bob@3180
   621
{
slouken@3187
   622
  *atomic += value;
bob@3180
   623
}
bob@3180
   624
#endif /* arch & platforms */
slouken@3187
   625
  
slouken@3187
   626
/* *INDENT-ON* */
slouken@3186
   627
bob@3180
   628
#ifdef ATOMIC_INT_CMP_XCHG
bob@3180
   629
static __inline__ SDL_bool
slouken@3186
   630
SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
bob@3180
   631
{
slouken@3186
   632
    return (SDL_bool) ATOMIC_INT_CMP_XCHG(atomic, oldvalue, newvalue);
bob@3180
   633
}
bob@3180
   634
bob@3180
   635
static __inline__ int
slouken@3186
   636
SDL_atomic_int_xchg_add(volatile int *atomic, int value)
slouken@3186
   637
{
slouken@3186
   638
    int rv;
slouken@3186
   639
    do
slouken@3186
   640
        rv = *atomic;
slouken@3186
   641
    while (!ATOMIC_INT_CMP_XCHG(atomic, rv, rv + value));
slouken@3186
   642
    return rv;
bob@3180
   643
}
bob@3180
   644
bob@3180
   645
static __inline__ void
slouken@3186
   646
SDL_atomic_int_add(volatile int *atomic, int value)
bob@3180
   647
{
slouken@3186
   648
    int rv;
slouken@3186
   649
    do
slouken@3186
   650
        rv = *atomic;
slouken@3186
   651
    while (!ATOMIC_INT_CMP_XCHG(atomic, rv, rv + value));
bob@3180
   652
}
bob@3180
   653
#endif /* ATOMIC_CMP_XCHG */
bob@3180
   654
bob@3180
   655
#ifdef ATOMIC_MEMORY_BARRIER
bob@3180
   656
# define SDL_atomic_int_get(atomic) \
bob@3180
   657
  (ATOMIC_MEMORY_BARRIER,*(atomic))
bob@3180
   658
# define SDL_atomic_int_set(atomic,value) \
bob@3180
   659
  (*(atomic)=value,ATOMIC_MEMORY_BARRIER)
bob@3180
   660
#else
bob@3180
   661
# define SDL_atomic_int_get(atomic) (*(atomic))
bob@3180
   662
# define SDL_atomic_int_set(atomic, newvalue) ((void)(*(atomic) = (newvalue)))
bob@3180
   663
#endif /* MEMORY_BARRIER_NEEDED */
bob@3180
   664
bob@3180
   665
#define SDL_atomic_int_inc(atomic) (SDL_atomic_int_add((atomic),1))
bob@3180
   666
#define SDL_atomic_int_dec_test(atomic) (SDL_atomic_int_xchg_add((atomic),-1) == 1)
bob@3180
   667
bob@3180
   668
/* Ends C function definitions when using C++ */
bob@3180
   669
#ifdef __cplusplus
bob@3180
   670
/* *INDENT-OFF* */
bob@3180
   671
}
bob@3180
   672
/* *INDENT-ON* */
bob@3180
   673
#endif
bob@3180
   674
bob@3180
   675
#include "close_code.h"
bob@3180
   676
bob@3180
   677
#endif /* _SDL_atomic_h_ */
bob@3180
   678
bob@3180
   679
/* vi: set ts=4 sw=4 expandtab: */