include/SDL_atomic.h
changeset 3199 3e1bf2b8bd81
parent 3187 e041d2c603fe
child 3202 3aa519a5c676
     1.1 --- a/include/SDL_atomic.h	Wed Jun 17 04:26:19 2009 +0000
     1.2 +++ b/include/SDL_atomic.h	Wed Jun 24 20:04:08 2009 +0000
     1.3 @@ -23,7 +23,7 @@
     1.4  /**
     1.5   * \file SDL_atomic.h
     1.6   *
     1.7 - * Atomic int and pointer magic
     1.8 + * Atomic operations.
     1.9   */
    1.10  
    1.11  #ifndef _SDL_atomic_h_
    1.12 @@ -42,628 +42,232 @@
    1.13  /* *INDENT-ON* */
    1.14  #endif
    1.15  
    1.16 -/* indent is really bad at handling assembly */
    1.17  /* *INDENT-OFF* */
    1.18 +/**
    1.19 + * \def SDL_AtomicBusyWait32 (ptr)
    1.20 + *
    1.21 + * \brief Implements a simple busy wait for use with
    1.22 + * SDL_AtomicTestThenSet and SDL_AtomicClear.
    1.23 + *
    1.24 + * Note: This can be an infinite loop.
    1.25 + *
    1.26 + */
    1.27 +#define SDL_AtomicBusyWait32(ptr)		\
    1.28 +   {						\
    1.29 +   while (!SDL_AtomicTestThenSet32(ptr)		\
    1.30 +      {						\
    1.31 +      };					\
    1.32 +   };
    1.33  
    1.34 -#if defined(__GNUC__) && (defined(i386) || defined(__i386__)  || defined(__x86_64__))
    1.35 -static __inline__ void
    1.36 -SDL_atomic_int_add(volatile int* atomic, int value)
    1.37 -{
    1.38 -  __asm__ __volatile__("lock;"
    1.39 -                       "addl %1, %0"
    1.40 -                       : "=m" (*atomic)
    1.41 -                       : "ir" (value),
    1.42 -                         "m" (*atomic));
    1.43 -}
    1.44 +/**
    1.45 + * \def SDL_AtomicWait32(ptr)
    1.46 + *
    1.47 + * \brief A safer way to wait for a test-then-set lock to be cleared.
    1.48 + *
    1.49 + * This assumes that the SDL_Sleep(0) call acts as a thread_yeild
    1.50 + * operation. 
    1.51 + *
    1.52 + */
    1.53 +#define SDL_AtomicWait32(ptr)			\
    1.54 +   {						\
    1.55 +   while (!SDL_AtomicTestThenSet32(ptr)		\
    1.56 +      {						\
    1.57 +	 SDL_Sleep(0);				\
    1.58 +      };                                        \
    1.59 +   };
    1.60  
    1.61 -static __inline__ int
    1.62 -SDL_atomic_int_xchg_add(volatile int* atomic, int value)
    1.63 -{                                              
    1.64 -  int rv;                                    
    1.65 -  __asm__ __volatile__("lock;"               
    1.66 -                       "xaddl %0, %1"        
    1.67 -                       : "=r" (rv),          
    1.68 -                         "=m" (*atomic)    
    1.69 -                       : "0" (value),        
    1.70 -                         "m" (*atomic));   
    1.71 -  return rv;                                        
    1.72 -}
    1.73 +/**
    1.74 + * \def SDL_AtomicBusyWait64(ptr)
    1.75 + *
    1.76 + * \brief 64 bit version of busy wait
    1.77 + *
    1.78 + * \sa SDL_AtomicBusyWait32
    1.79 + */
    1.80 +#define SDL_AtomicBusyWait64(ptr)		\
    1.81 +   {						\
    1.82 +   while (!SDL_AtomicTestThenSet64(ptr)		\
    1.83 +      {						\
    1.84 +      };					\
    1.85 +   };
    1.86  
    1.87 -static __inline__ SDL_bool
    1.88 -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
    1.89 -{
    1.90 -  int rv;                                                      
    1.91 -  __asm__ __volatile__("lock;"                               
    1.92 -                       "cmpxchgl %2, %1"                     
    1.93 -                       : "=a" (rv),                          
    1.94 -                         "=m" (*atomic)             
    1.95 -                       : "r" (newvalue),                     
    1.96 -                         "m" (*atomic),                    
    1.97 -                         "0" (oldvalue));
    1.98 -  return (SDL_bool)(rv == oldvalue);                                          
    1.99 -}
   1.100 -
   1.101 -static __inline__ SDL_bool
   1.102 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.103 -{
   1.104 -  void* rv;
   1.105 -  __asm__ __volatile__("lock;"
   1.106 -# if defined(__x86_64__)                       
   1.107 -                       "cmpxchgq %q2, %1"
   1.108 -# else
   1.109 -                       "cmpxchgl %2, %1"
   1.110 -# endif                       
   1.111 -                       : "=a" (rv),
   1.112 -                         "=m" (*atomic)
   1.113 -                       : "r" (newvalue),
   1.114 -                         "m" (*atomic),
   1.115 -                         "0" (oldvalue));
   1.116 -  return (SDL_bool)(rv == oldvalue);
   1.117 -}
   1.118 -#elif defined(__GNUC__) && defined(__alpha__)
   1.119 -# define ATOMIC_MEMORY_BARRIER (__asm__ __volatile__ ("mb" : : : "memory"))
   1.120 -# define ATOMIC_INT_CMP_XCHG(atomic,value)              \
   1.121 -  ({                                                    \
   1.122 -    int rv,prev;                                        \
   1.123 -    __asm__ __volatile__("   mb\n"                      \
   1.124 -                         "1: ldl_l   %0,%2\n"           \
   1.125 -                         "   cmpeq   %0,%3,%1\n"        \
   1.126 -                         "   beq     %1,2f\n"           \
   1.127 -                         "   mov     %4,%1\n"           \
   1.128 -                         "   stl_c   %1,%2\n"           \
   1.129 -                         "   beq     %1,1b\n"           \
   1.130 -                         "   mb\n"                      \
   1.131 -                         "2:"                           \
   1.132 -                         : "=&r" (prev),                \
   1.133 -                           "=&r" (rv)                   \
   1.134 -                         : "m" (*(atomic)),             \
   1.135 -                           "Ir" (oldvalue),             \
   1.136 -                           "Ir" (newvalue)              \
   1.137 -                         : "memory");                   \
   1.138 -    (rv != 0);                                          \
   1.139 -  })
   1.140 -
   1.141 -# if (SIZEOF_VOIDP == 4)
   1.142 -static __inline__ SDL_bool
   1.143 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.144 -{
   1.145 -  int rv;
   1.146 -  void* prev;
   1.147 -  __asm__ __volatile__("   mb\n"
   1.148 -                       "1: ldl_l %0,%2\n"
   1.149 -                       "   cmpeq %0,%3,%1\n"
   1.150 -                       "   beq   $1,2f\n"
   1.151 -                       "   mov   %4,%1\n"
   1.152 -                       "   stl_c %1,%2\n"
   1.153 -                       "   beq   %1,1b\n"
   1.154 -                       "   mb\n"
   1.155 -                       "2:"
   1.156 -                       : "=&r" (prev),
   1.157 -                         "=&r" (rv)
   1.158 -                       : "m" (*atomic),
   1.159 -                         "Ir" (oldvalue),
   1.160 -                         "Ir" (newvalue)
   1.161 -                       : "memory");
   1.162 -  return (SDL_bool)(rv != 0);
   1.163 -}
   1.164 -# elif (SIZEOF_VOIDP == 8)
   1.165 -static __inline__ SDL_bool
   1.166 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.167 -{
   1.168 -  int rv;
   1.169 -  void* prev;
   1.170 -  __asm__ __volatile__("   mb\n"
   1.171 -                       "1: ldq_l %0,%2\n"
   1.172 -                       "   cmpeq %0,%3,%1\n"
   1.173 -                       "   beq   %1,2f\n"
   1.174 -                       "   mov   %4,%1\n"
   1.175 -                       "   stq_c %1,%2\n"
   1.176 -                       "   beq   %1,1b\n"
   1.177 -                       "   mb\n"
   1.178 -                       "2:"
   1.179 -                       : "=&r" (prev),
   1.180 -                         "=&r" (rv)
   1.181 -                       : "m" (*atomic),
   1.182 -                         "Ir" (oldvalue),
   1.183 -                         "Ir" (newvalue)
   1.184 -                       : "memory");
   1.185 -  return (SDL_bool)(rv != 0);
   1.186 -}
   1.187 -# else
   1.188 -#  error "Your system has an unsupported pointer size"  
   1.189 -# endif  /* SIZEOF_VOIDP */
   1.190 -#elif defined(__GNUC__) && defined(__sparc__)
   1.191 -# define ATOMIC_MEMORY_BARRIER                                          \
   1.192 -  (__asm__ __volatile__("membar #LoadLoad | #LoadStore"                 \
   1.193 -                        " | #StoreLoad | #StoreStore" : : : "memory"))
   1.194 -# define ATOMIC_INT_CMP_XCHG(atomic,oldvalue,newvalue)                  \
   1.195 -  ({                                                                    \
   1.196 -    int rv;                                                             \
   1.197 -    __asm__ __volatile__("cas [%4], %2, %0"                             \
   1.198 -                         : "=r" (rv), "=m" (*(atomic))                  \
   1.199 -                         : "r" (oldvalue), "m" (*(atomic)),             \
   1.200 -                         "r" (atomic), "0" (newvalue));                 \
   1.201 -    rv == oldvalue;                                                     \
   1.202 -  })
   1.203 -
   1.204 -# if (SIZEOF_VOIDP == 4)
   1.205 -static __inline__ SDL_bool
   1.206 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.207 -{
   1.208 -  void* rv;
   1.209 -  __asm__ __volatile__("cas [%4], %2, %0"
   1.210 -                       : "=r" (rv),
   1.211 -                         "=m" (*atomic)
   1.212 -                       : "r" (oldvalue),
   1.213 -                         "m" (*atomic),
   1.214 -                         "r" (atomic),
   1.215 -                         "0" (newvalue));
   1.216 -  return (SDL_bool)(rv == oldvalue);
   1.217 -}
   1.218 -# elif (SIZEOF_VOIDP == 8)
   1.219 -static __inline__ SDL_bool
   1.220 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.221 -{
   1.222 -  void* rv;
   1.223 -  void** a = atomic;
   1.224 -  __asm__ __volatile__("casx [%4], %2, %0"
   1.225 -                       : "=r" (rv),
   1.226 -                         "=m" (*a)
   1.227 -                       : "r" (oldvalue),
   1.228 -                         "m" (*a),
   1.229 -                         "r" (a),
   1.230 -                         "0" (newvalue));
   1.231 -  return (SDL_bool)(rv == oldvalue);
   1.232 -}
   1.233 -# else
   1.234 -#  error "Your system has an unsupported pointer size"
   1.235 -# endif /* SIZEOF_VOIDP */
   1.236 -#elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC))
   1.237 -# define ATOMIC_MEMORY_BARRIER \
   1.238 -  (__asm__ __volatile__ ("sync" : : : "memory"))
   1.239 -static __inline__ void
   1.240 -SDL_atomic_int_add(volatile int* atomic, int value)
   1.241 -{                                           
   1.242 -  int rv,tmp;                                   
   1.243 -  __asm__ __volatile__("1: lwarx   %0,  0, %3\n" 
   1.244 -                       "   add     %1, %0, %4\n"
   1.245 -                       "   stwcx.  %1,  0, %3\n" 
   1.246 -                       "   bne-    1b"          
   1.247 -                       : "=&b" (rv),            
   1.248 -                         "=&r" (tmp),           
   1.249 -                         "=m" (*atomic)       
   1.250 -                       : "b" (atomic),          
   1.251 -                         "r" (value),           
   1.252 -                         "m" (*atomic)        
   1.253 -                       : "cr0",                 
   1.254 -                         "memory");             
   1.255 -}
   1.256 -
   1.257 -static __inline__ int
   1.258 -SDL_atomic_int_xchg_add(volatile int* atomic, int value)
   1.259 -{                                          
   1.260 -  int rv,tmp;                               
   1.261 -  __asm__ __volatile__("1: lwarx  %0, 0, %3\n"        
   1.262 -                       "   add    %1, %0, %4\n"       
   1.263 -                       "   stwcx. %1, 0, %3\n"        
   1.264 -                       "   bne-   1b"                 
   1.265 -                       : "=&b" (rv),                  
   1.266 -                         "=&r" (tmp),                 
   1.267 -                         "=m" (*atomic)
   1.268 -                       : "b" (atomic),                
   1.269 -                         "r" (value),                 
   1.270 -                         "m" (*atomic)
   1.271 -                       : "cr0",                       
   1.272 -                       "memory");                   
   1.273 -  return rv;                                                 
   1.274 -}
   1.275 -
   1.276 -# if (SIZEOF_VOIDP == 4)
   1.277 -static __inline__ SDL_bool
   1.278 -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
   1.279 -{                                                        
   1.280 -  int rv;                                                 
   1.281 -  __asm__ __volatile__("   sync\n"                         
   1.282 -                       "1: lwarx   %0, 0, %1\n"           
   1.283 -                       "   subf.   %0, %2, %0\n"          
   1.284 -                       "   bne     2f\n"                  
   1.285 -                       "   stwcx.  %3, 0, %1\n"           
   1.286 -                       "   bne-    1b\n"                  
   1.287 -                       "2: isync"                         
   1.288 -                       : "=&r" (rv)                       
   1.289 -                       : "b" (atomic),                    
   1.290 -                         "r" (oldvalue),                  
   1.291 -                         "r"                              
   1.292 -                       : "cr0",                           
   1.293 -                         "memory");                         
   1.294 -  return (SDL_bool)(rv == 0);                                              
   1.295 -}
   1.296 -
   1.297 -static __inline__ SDL_bool
   1.298 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.299 -{
   1.300 -  void* rv;
   1.301 -  __asm__ __volatile__("sync\n"
   1.302 -                       "1: lwarx  %0,  0, %1\n"
   1.303 -                       "   subf.  %0, %2, %0\n"
   1.304 -                       "   bne    2f\n"
   1.305 -                       "   stwcx. %3,  0, %1\n"
   1.306 -                       "   bne-   1b\n"
   1.307 -                       "2: isync"
   1.308 -                       : "=&r" (rv)
   1.309 -                       : "b" (atomic),
   1.310 -                         "r" (oldvalue),
   1.311 -                         "r" (newvalue)
   1.312 -                       : "cr0",
   1.313 -                       "memory");
   1.314 -  return (SDL_bool)(rv == 0);
   1.315 -}
   1.316 -# elif (SIZEOF_VOIDP == 8)
   1.317 -static __inline__ SDL_bool
   1.318 -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
   1.319 -{                                                        
   1.320 -  int rv;                                                 
   1.321 -  __asm__ __volatile__("   sync\n"                         
   1.322 -                       "1: lwarx   %0,  0, %1\n"
   1.323 -                       "   extsw   %0, %0\n"
   1.324 -                       "   subf.   %0, %2, %0\n"          
   1.325 -                       "   bne     2f\n"                  
   1.326 -                       "   stwcx.  %3,  0, %1\n"           
   1.327 -                       "   bne-    1b\n"                  
   1.328 -                       "2: isync"                         
   1.329 -                       : "=&r" (rv)                       
   1.330 -                       : "b" (atomic),                    
   1.331 -                         "r" (oldvalue),                  
   1.332 -                         "r"                              
   1.333 -                       : "cr0",                           
   1.334 -                         "memory");                         
   1.335 -  return (SDL_bool)(rv == 0);                                              
   1.336 -}
   1.337 -
   1.338 -static __inline__ SDL_bool
   1.339 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.340 -{
   1.341 -  void* rv;
   1.342 -  __asm__ __volatile__("sync\n"
   1.343 -                       "1: ldarx  %0,  0, %1\n"
   1.344 -                       "   subf.  %0, %2, %0\n"
   1.345 -                       "   bne    2f\n"
   1.346 -                       "   stdcx. %3,  0, %1\n"
   1.347 -                       "   bne-   1b\n"
   1.348 -                       "2: isync"
   1.349 -                       : "=&r" (rv)
   1.350 -                       : "b" (atomic),
   1.351 -                         "r" (oldvalue),
   1.352 -                         "r" (newvalue)
   1.353 -                       : "cr0",
   1.354 -                       "memory");
   1.355 -  return (SDL_bool)(rv == 0);
   1.356 -}
   1.357 -# else
   1.358 -#  error "Your system has an unsupported pointer size"
   1.359 -# endif /* SIZEOF_VOIDP */
   1.360 -#elif defined(__GNUC__) && (defined(__IA64__) || defined(__ia64__))
   1.361 -# define ATOMIC_MEMORY_BARRIER (__sync_synchronize())
   1.362 -# define SDL_atomic_int_xchg_add(atomic, value)     \
   1.363 -  (__sync_fetch_and_add((atomic),(value)))
   1.364 -# define SDL_atomic_int_add(atomic, value)                  \
   1.365 -  ((void)__sync_fetch_and_add((atomic),(value)))
   1.366 -# define SDL_atomic_int_cmp_xchg(atomic,oldvalue,newvalue)  \
   1.367 -  (__sync_bool_compare_and_swap((atomic),(oldvalue),(newvalue)))
   1.368 -# define SDL_atomic_ptr_cmp_xchg(atomic,oldvalue,newvalue)              \
   1.369 -  (__sync_bool_compare_and_swap((long*)(atomic),(long)(oldvalue),(long)(newvalue)))
   1.370 -#elif defined(__GNUC__) && defined(__LINUX__) && (defined(__mips__) || defined(__MIPS__))
   1.371 -static __inline__ int
   1.372 -SDL_atomic_int_xchg_add(volatile int* atomic, int value)
   1.373 -{                                            
   1.374 -  int rv,tmp;                                 
   1.375 -  __asm__ __volatile__("1:              \n"                 
   1.376 -                       ".set  push      \n"         
   1.377 -                       ".set  mips2     \n"        
   1.378 -                       "ll    %0,%3     \n"        
   1.379 -                       "addu  %1,%4,%0  \n"     
   1.380 -                       "sc    %1,%2     \n"        
   1.381 -                       ".set  pop       \n"          
   1.382 -                       "beqz  %1,1b     \n"        
   1.383 -                       : "=&r" (rv),          
   1.384 -                         "=&r" (tmp),         
   1.385 -                         "=m" (*atomic)     
   1.386 -                       : "m" (*atomic),     
   1.387 -                         "r" (value)          
   1.388 -                       : "memory");           
   1.389 -  return rv;                                         
   1.390 -}
   1.391 -
   1.392 -static __inline__ void
   1.393 -SDL_atomic_int_add(volatile int* atomic, int value)
   1.394 -{                                           
   1.395 -  int rv;                                    
   1.396 -  __asm__ __volatile__("1:               \n"                
   1.397 -                       ".set  push       \n"        
   1.398 -                       ".set  mips2      \n"       
   1.399 -                       "ll    %0,%2      \n"       
   1.400 -                       "addu  %0,%3,%0   \n"    
   1.401 -                       "sc    %0,%1      \n"       
   1.402 -                       ".set  pop        \n"         
   1.403 -                       "beqz  %0,1b      \n"       
   1.404 -                       : "=&r" (rv),         
   1.405 -                         "=m" (*atomic)    
   1.406 -                       : "m" (*atomic),    
   1.407 -                         "r" (value)         
   1.408 -                       : "memory");          
   1.409 -}
   1.410 -
   1.411 -static __inline__ SDL_bool
   1.412 -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
   1.413 -{
   1.414 -  int rv;
   1.415 -  __asm__ __volatile__("     .set push        \n"
   1.416 -                       "     .set noat        \n"
   1.417 -                       "     .set mips3       \n"
   1.418 -                       "1:   ll   %0, %2      \n"
   1.419 -                       "     bne  %0, %z3, 2f \n"
   1.420 -                       "     .set mips0       \n"
   1.421 -                       "     move $1, %z4     \n"
   1.422 -                       "     .set mips3       \n"
   1.423 -                       "     sc   $1, %1      \n"
   1.424 -                       "     beqz $1, 1b      \n"
   1.425 -                       "     sync             \n"
   1.426 -                       "2:                    \n"
   1.427 -                       "     .set pop         \n"
   1.428 -                       : "=&r" (rv),
   1.429 -                         "=R" (*atomic)
   1.430 -                       : "R" (*atomic),
   1.431 -                         "Jr" (oldvalue),
   1.432 -                         "Jr" (newvalue)
   1.433 -                       : "memory");
   1.434 -  return (SDL_bool)rv;                  
   1.435 -}
   1.436 -
   1.437 -static __inline__ SDL_bool
   1.438 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.439 -{                                                     
   1.440 -  int rv;
   1.441 -  __asm__ __volatile__("     .set push        \n"
   1.442 -                       "     .set noat        \n"
   1.443 -                       "     .set mips3       \n"
   1.444 -# if defined(__mips64)
   1.445 -                       "1:   lld  %0, %2      \n"
   1.446 -# else
   1.447 -                       "1:   ll   %0, %2      \n"
   1.448 -# endif                       
   1.449 -                       "     bne  %0, %z3, 2f \n"
   1.450 -                       "     move $1, %z4     \n"
   1.451 -# if defined(__mips64)
   1.452 -                       "     sc   $1, %1      \n"
   1.453 -# else
   1.454 -                       "     scd  $1, %1      \n"
   1.455 -# endif                       
   1.456 -                       "     beqz $1, 1b      \n"
   1.457 -                       "     sync             \n"
   1.458 -                       "2:                    \n"
   1.459 -                       "     .set pop         \n"
   1.460 -                       : "=&r" (rv),
   1.461 -                         "=R" (*atomic)
   1.462 -                       : "R" (*atomic),
   1.463 -                         "Jr" (oldvalue),
   1.464 -                         "Jr" (newvalue)
   1.465 -                       : "memory");
   1.466 -  return (SDL_bool)rv;                                                  
   1.467 -}
   1.468 -#elif defined(__GNUC__) && defined(__m68k__)
   1.469 -static __inline__ int
   1.470 -SDL_atomic_int_xchg_add(volatile int* atomic, int value)
   1.471 -{                                          
   1.472 -  int rv = *atomic;
   1.473 -  int tmp;
   1.474 -  __asm__ __volatile__("1: move%.l %0,%1    \n"
   1.475 -                       "   add%.l  %2,%1    \n"
   1.476 -                       "   cas%.l  %0,%1,%3 \n"
   1.477 -                       "   jbne    1b       \n"
   1.478 -                       : "=d" (rv),
   1.479 -                         "=&d" (tmp)
   1.480 -                       : "d" (value),
   1.481 -                         "m" (*atomic),
   1.482 -                         "0" (rv)
   1.483 -                       : "memory");
   1.484 -  return (SDL_bool)rv;
   1.485 -}
   1.486 -
   1.487 -static __inline__ void
   1.488 -SDL_atomic_int_add(volatile int* atomic, int value)
   1.489 -{                                           
   1.490 -  __asm__ __volatile__("add%.l %0,%1"        
   1.491 -                       :                     
   1.492 -                       : "id" (value),       
   1.493 -                         "m" (*atomic)
   1.494 -                       : "memory");          
   1.495 -}
   1.496 -
   1.497 -static __inline__ SDL_bool
   1.498 -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
   1.499 -{                                           
   1.500 -  char rv;                                   
   1.501 -  int readvalue;                             
   1.502 -  __asm__ __volatile__("cas%.l %2,%3,%1\n"   
   1.503 -                       "seq    %0"           
   1.504 -                       : "=dm" (rv),         
   1.505 -                         "=m" (*atomic),   
   1.506 -                         "=d" (readvalue)    
   1.507 -                       : "d" (newvalue),     
   1.508 -                         "m" (*atomic),    
   1.509 -                         "2" (oldvalue));    
   1.510 -    return (SDL_bool)rv;                                        
   1.511 -}
   1.512 -
   1.513 -static __inline__ SDL_bool
   1.514 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.515 -{
   1.516 -  char rv;                                   
   1.517 -  int readvalue;                             
   1.518 -  __asm__ __volatile__("cas%.l %2,%3,%1\n"   
   1.519 -                       "seq    %0"           
   1.520 -                       : "=dm" (rv),         
   1.521 -                         "=m" (*atomic),   
   1.522 -                         "=d" (readvalue)    
   1.523 -                       : "d" (newvalue),     
   1.524 -                         "m" (*atomic),    
   1.525 -                         "2" (oldvalue));    
   1.526 -    return (SDL_bool)rv;                                        
   1.527 -}
   1.528 -#elif defined(__GNUC__) && defined(__s390__)
   1.529 -# define ATOMIC_INT_CMP_XCHG(atomic,oldvalue,newvalue)  \
   1.530 -  ({                                                    \
   1.531 -    int rv = oldvalue;                                  \
   1.532 -    __asm__ __volatile__("cs %0, %2, %1"                \
   1.533 -                         : "+d" (rv),                   \
   1.534 -                           "=Q" (*(atomic))             \
   1.535 -                         : "d" (newvalue),              \
   1.536 -                           "m" (*(atomic))              \
   1.537 -                         : "cc");                       \
   1.538 -    rv == oldvalue;                                     \
   1.539 -  })
   1.540 -# if (SIZEOF_VOIDP == 4)
   1.541 -static __inline__ SDL_bool
   1.542 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.543 -{
   1.544 -  void* rv = oldvalue;
   1.545 -  __asm__ __volatile__("cs %0, %2, %1"
   1.546 -                       : "+d" (rv),
   1.547 -                         "=Q" (*atomic)
   1.548 -                       : "d" (newvalue),
   1.549 -                         "m" (*atomic)
   1.550 -                       : "cc");
   1.551 -  return (SDL_bool)(rv == oldvalue);
   1.552 -}
   1.553 -# elif (SIZEOF_VOIDP == 8)
   1.554 -static __inline__ SDL_bool
   1.555 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.556 -{
   1.557 -  void* rv = oldvalue;
   1.558 -  void** a = atomic;
   1.559 -  __asm__ __volatile__("csg %0, %2, %1"
   1.560 -                       : "+d" (rv),
   1.561 -                         "=Q" (*a)
   1.562 -                       : "d" ((long)(newvalue)),
   1.563 -                         "m" (*a)
   1.564 -                       : "cc");
   1.565 -  return (SDL_bool)(rv == oldvalue);
   1.566 -}
   1.567 -# else
   1.568 -#  error "Your system has an unsupported pointer size"
   1.569 -# endif /* SIZEOF_VOIDP */
   1.570 -#elif defined(__WIN32__)
   1.571 -# include <windows.h>
   1.572 -static __inline__ int
   1.573 -SDL_atomic_int_xchg_add(volatile int* atomic, int value)
   1.574 -{
   1.575 -  return InterlockedExchangeAdd(atomic, value);
   1.576 -}
   1.577 -
   1.578 -static __inline__ void
   1.579 -SDL_atomic_int_add(volatile int* atomic, int value)
   1.580 -{
   1.581 -  InterlockedExchangeAdd(atomic, value);
   1.582 -}
   1.583 -
   1.584 -# if (WINVER > 0X0400)
   1.585 -static __inline__ SDL_bool
   1.586 -SDL_atmoic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
   1.587 -{
   1.588 -   return (SDL_bool)(InterlockedCompareExchangePointer((PVOID*)atomic,
   1.589 -                                                       (PVOID)newvalue,
   1.590 -                                                       (PVOID)oldvalue) == oldvalue);
   1.591 -}
   1.592 -
   1.593 -
   1.594 -static __inline__ SDL_bool
   1.595 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.596 -{
   1.597 -  return (InterlockedCompareExchangePointer(atomic, newvalue, oldvalue) == oldvalue);
   1.598 -}
   1.599 -# else /* WINVER <= 0x0400 */
   1.600 -#  if (SIZEOF_VOIDP != 4)
   1.601 -#   error "InterlockedCompareExchangePointer needed"
   1.602 -#  endif
   1.603 -
   1.604 -static __inline__ SDL_bool
   1.605 -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
   1.606 -{
   1.607 -  return (InterlockedCompareExchange(atomic, newvalue, oldvalue) == oldvalue);
   1.608 -}
   1.609 -
   1.610 -static __inline__ SDL_bool
   1.611 -SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue)
   1.612 -{
   1.613 -  return (InterlockedCompareExchange(atomic, newvalue, oldvalue) == oldvalue);
   1.614 -}
   1.615 -# endif
   1.616 -#else /* when all else fails */
   1.617 -# define SDL_ATOMIC_OPS_NOT_SUPPORTED
   1.618 -# warning "Atomic Ops for this platform not supported!"
   1.619 -static __inline__ int
   1.620 -SDL_atomic_int_xchg_add(volatile int* atomic, int value)
   1.621 -{                                           
   1.622 -  int rv = *atomic;                          
   1.623 -  *(atomic) += value;                        
   1.624 -  return rv;                                        
   1.625 -}
   1.626 -
   1.627 -static __inline__ SDL_bool
   1.628 -SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
   1.629 -{
   1.630 -  return (*atomic == oldvalue) ?  
   1.631 -    ((*atomic = newvalue), SDL_TRUE) : SDL_FALSE;
   1.632 -}
   1.633 -
   1.634 -static __inline__ void
   1.635 -SDL_atomic_int_add(volatile int* atomic, int value)
   1.636 -{
   1.637 -  *atomic += value;
   1.638 -}
   1.639 -#endif /* arch & platforms */
   1.640 -  
   1.641 +/**
   1.642 + * \def SDL_AtomicWait64(ptr)
   1.643 + *
   1.644 + * \brief 64 bit version of SDL_AtomicWait32
   1.645 + *
   1.646 + * \sa SDL_AtomicWait32
   1.647 + */
   1.648 +#define SDL_AtomicWait64(ptr)			\
   1.649 +   {						\
   1.650 +   while (!SDL_AtomicTestThenSet64(ptr)		\
   1.651 +      {						\
   1.652 +	 SDL_Sleep(0);				\
   1.653 +      };                                        \
   1.654 +   };
   1.655  /* *INDENT-ON* */
   1.656  
   1.657 -#ifdef ATOMIC_INT_CMP_XCHG
   1.658 -static __inline__ SDL_bool
   1.659 -SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue)
   1.660 -{
   1.661 -    return (SDL_bool) ATOMIC_INT_CMP_XCHG(atomic, oldvalue, newvalue);
   1.662 -}
   1.663 +/* Function prototypes */
   1.664  
   1.665 -static __inline__ int
   1.666 -SDL_atomic_int_xchg_add(volatile int *atomic, int value)
   1.667 -{
   1.668 -    int rv;
   1.669 -    do
   1.670 -        rv = *atomic;
   1.671 -    while (!ATOMIC_INT_CMP_XCHG(atomic, rv, rv + value));
   1.672 -    return rv;
   1.673 -}
   1.674 +/**
   1.675 + * \fn int SDL_AtomicExchange32(Uint32 * ptr, Uint32 value)
   1.676 + *
   1.677 + * \brief Atomically exchange two 32 bit values.
   1.678 + *
   1.679 + * \return the value point to by ptr.
   1.680 + *
   1.681 + * \param ptr points to the value to be fetched from *ptr.  
   1.682 + * \param value is value to be stored at *ptr.
   1.683 + *
   1.684 + * The current value stored at *ptr is returned and it is replaced
   1.685 + * with value. This function can be used to implement SDL_TestThenSet.
   1.686 + *
   1.687 + */
   1.688 +extern DECLSPEC Uint32 SDLCALL SDL_AtomicExchange32(Uint32 * ptr, Uint32 value);
   1.689 +/**
   1.690 + * \fn int SDL_AtomicCompareThenSet32(Uint32 * ptr, Uint32 oldvalue, Uint32 newvalue)
   1.691 + *
   1.692 + * \brief If *ptr == oldvalue then replace the contents of *ptr by new value. 
   1.693 + *
   1.694 + * \return true if the newvalue was stored.
   1.695 + *
   1.696 + * \param *ptr is the value to be compared and replaced.
   1.697 + * \param oldvalue is value to be compared to *ptr.
   1.698 + * \param newvalue is value to be stored at *ptr.
   1.699 + *
   1.700 + */
   1.701 +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCompareThenSet32(Uint32 * ptr,
   1.702 +                                                            Uint32 oldvalue, Uint32 newvalue);
   1.703 +/**
   1.704 + * \fn  SDL_bool SDL_AtomicTestThenSet32(Uint32 * ptr);
   1.705 + *
   1.706 + * \brief Check to see if *ptr == 0 and set it to non-zero.
   1.707 + *
   1.708 + * \return SDL_True if the value pointed to by ptr was zero and
   1.709 + * SDL_False if it was not zero
   1.710 + *
   1.711 + * \param ptr points to the value to be tested and set.
   1.712 + *
   1.713 + */
   1.714 +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTestThenSet32(Uint32 * ptr);
   1.715 +/**
   1.716 + * \fn  void SDL_AtomicClear32(Uint32 * ptr);
   1.717 + *
   1.718 + * \brief set the value pointed to by ptr to be zero.
   1.719 + *
   1.720 + * \param ptr address of the value to be set to zero
   1.721 + *
   1.722 + */
   1.723 +extern DECLSPEC void SDLCALL SDL_AtomicClear32(Uint32 * ptr);
   1.724 +/**
   1.725 + * \fn  Uint32 SDL_AtomicFetchThenIncrement32(Uint32 * ptr);
   1.726 + *
   1.727 + * \brief fetch the current value of *ptr and then increment that
   1.728 + * value in place.
   1.729 + *
   1.730 + * \return the value before it was incremented.
   1.731 + *
   1.732 + * \param ptr address of the value to fetch and increment
   1.733 + *
   1.734 + */
   1.735 +extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenIncrement32(Uint32 * ptr);
   1.736 +/**
   1.737 + * \fn  Uint32 SDL_AtomicFetchThenDecrement32(Uint32 * ptr);
   1.738 + *
   1.739 + * \brief fetch *ptr and then decrement the value in place.
   1.740 + *
   1.741 + * \return the value before it was decremented.
   1.742 + *
   1.743 + * \param ptr address of the value to fetch and drement
   1.744 + *
   1.745 + */
   1.746 +extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenDecrement32(Uint32 * ptr);
   1.747 +/**
   1.748 + * \fn  Uint32 SDL_AtomicFetchThenAdd32(Uint32 * ptr, Uint32 value);
   1.749 + *
   1.750 + * \brief fetch the current value at ptr and then add value to *ptr.
   1.751 + *
   1.752 + * \return *ptr before the addition took place.
   1.753 + *
   1.754 + * \param ptr the address of data we are changing.
   1.755 + * \param value the value to add to *ptr. 
   1.756 + *
   1.757 + */
   1.758 +extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenAdd32(Uint32 * ptr, Uint32 value);
   1.759 +/**
   1.760 + * \fn  Uint32 SDL_AtomicFetchThenSubtract32(Uint32 * ptr, Uint32 value);
   1.761 + *
   1.762 + * \brief Fetch *ptr and then subtract value from it.
   1.763 + *
   1.764 + * \return *ptr before the subtraction took place.
   1.765 + *
   1.766 + * \param ptr the address of the data being changed.
   1.767 + * \param value the value to subtract from *ptr.
   1.768 + *
   1.769 + */
   1.770 +extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenSubtract32(Uint32 * ptr, Uint32 value);
   1.771 +/**
   1.772 + * \fn  Uint32 SDL_AtomicIncrementThenFetch32(Uint32 * ptr);
   1.773 + *
   1.774 + * \brief Add one to the data pointed to by ptr and return that value.
   1.775 + *
   1.776 + * \return the incremented value.
   1.777 + *
   1.778 + * \param ptr address of the data to increment.
   1.779 + *
   1.780 + */
   1.781 +extern DECLSPEC Uint32 SDLCALL SDL_AtomicIncrementThenFetch32(Uint32 * ptr);
   1.782 +/**
   1.783 + * \fn  Uint32 SDL_AtomicDecrementThenFetch32(Uint32 * ptr);
   1.784 + *
   1.785 + * \brief Subtract one from data pointed to by ptr and return the new value.
   1.786 + *
   1.787 + * \return The decremented value.
   1.788 + *
   1.789 + * \param ptr The address of the data to decrement.
   1.790 + *
   1.791 + */
   1.792 +extern DECLSPEC Uint32 SDLCALL SDL_AtomicDecrementThenFetch32(Uint32 * ptr);
   1.793 +/**
   1.794 + * \fn  Uint32 SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 value);
   1.795 + *
   1.796 + * \brief Add value to the data pointed to by ptr and return result.
   1.797 + *
   1.798 + * \return The sum of *ptr and value.
   1.799 + *
   1.800 + * \param ptr The address of the data to be modified.
   1.801 + * \param value The value to be added.
   1.802 + *
   1.803 + */
   1.804 +extern DECLSPEC Uint32 SDLCALL SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 value);
   1.805 +/**
   1.806 + * \fn  Uint32 SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value);
   1.807 + *
   1.808 + * \brief Subtract value from the data pointed to by ptr and return the result.
   1.809 + *
   1.810 + * \return the difference between *ptr and value.
   1.811 + *
   1.812 + * \param ptr The address of the data to be modified.
   1.813 + * \param value The value to be subtracted.
   1.814 + *
   1.815 + */
   1.816 +extern DECLSPEC Uint32 SDLCALL SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value);
   1.817  
   1.818 -static __inline__ void
   1.819 -SDL_atomic_int_add(volatile int *atomic, int value)
   1.820 -{
   1.821 -    int rv;
   1.822 -    do
   1.823 -        rv = *atomic;
   1.824 -    while (!ATOMIC_INT_CMP_XCHG(atomic, rv, rv + value));
   1.825 -}
   1.826 -#endif /* ATOMIC_CMP_XCHG */
   1.827 +#ifdef SDL_HAS_64BIT_TYPE
   1.828  
   1.829 -#ifdef ATOMIC_MEMORY_BARRIER
   1.830 -# define SDL_atomic_int_get(atomic) \
   1.831 -  (ATOMIC_MEMORY_BARRIER,*(atomic))
   1.832 -# define SDL_atomic_int_set(atomic,value) \
   1.833 -  (*(atomic)=value,ATOMIC_MEMORY_BARRIER)
   1.834 -#else
   1.835 -# define SDL_atomic_int_get(atomic) (*(atomic))
   1.836 -# define SDL_atomic_int_set(atomic, newvalue) ((void)(*(atomic) = (newvalue)))
   1.837 -#endif /* MEMORY_BARRIER_NEEDED */
   1.838 -
   1.839 -#define SDL_atomic_int_inc(atomic) (SDL_atomic_int_add((atomic),1))
   1.840 -#define SDL_atomic_int_dec_test(atomic) (SDL_atomic_int_xchg_add((atomic),-1) == 1)
   1.841 +extern DECLSPEC Uint64 SDLCALL SDL_AtomicExchange64(Uint64 * ptr, Uint64 value);
   1.842 +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCompareThenSet64(Uint64 * ptr,
   1.843 +                                                            Uint64 oldvalue, Uint64 newvalue);
   1.844 +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTestThenSet64(Uint64 * ptr);
   1.845 +extern DECLSPEC void SDLCALL SDL_AtomicClear64(Uint64 * ptr);
   1.846 +extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenIncrement64(Uint64 * ptr);
   1.847 +extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenDecrement64(Uint64 * ptr);
   1.848 +extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenAdd64(Uint64 * ptr, Uint64 value);
   1.849 +extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenSubtract64(Uint64 * ptr, Uint64 value);
   1.850 +extern DECLSPEC Uint64 SDLCALL SDL_AtomicIncrementThenFetch64(Uint64 * ptr);
   1.851 +extern DECLSPEC Uint64 SDLCALL SDL_AtomicDecrementThenFetch64(Uint64 * ptr);
   1.852 +extern DECLSPEC Uint64 SDLCALL SDL_AtomicAddThenFetch64(Uint64 * ptr, Uint64 value);
   1.853 +extern DECLSPEC Uint64 SDLCALL SDL_AtomicSubtractThenFetch64(Uint64 * ptr, Uint64 value);
   1.854 +#endif
   1.855  
   1.856  /* Ends C function definitions when using C++ */
   1.857  #ifdef __cplusplus