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