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