src/atomic/linux/SDL_atomic.c
changeset 3202 3aa519a5c676
parent 3201 c297230efc75
child 3212 759032c318d8
     1.1 --- a/src/atomic/linux/SDL_atomic.c	Wed Jun 24 22:24:23 2009 +0000
     1.2 +++ b/src/atomic/linux/SDL_atomic.c	Mon Jun 29 19:54:43 2009 +0000
     1.3 @@ -20,154 +20,955 @@
     1.4      slouken@libsdl.org
     1.5  */
     1.6  
     1.7 -#include "SDL.h"
     1.8 -#include "SDL_config.h"
     1.9 +#include "SDL_stdinc.h"
    1.10  #include "SDL_atomic.h"
    1.11  
    1.12 +/*
    1.13 +  This file provides 8, 16, 32, and 64 bit atomic operations. If the
    1.14 +  operations are provided by the native hardware and operating system
    1.15 +  they are used. If they are not then the operations are emulated
    1.16 +  using the SDL mutex operations. 
    1.17 + */
    1.18 +
    1.19 +/* 
    1.20 +  First, detect whether the operations are supported and create
    1.21 +  #defines that indicate that they do exist. The goal is to have all
    1.22 +  the system dependent code in the top part of the file so that the
    1.23 +  bottom can be use unchanged across all platforms.
    1.24 +
    1.25 +  Second, #define all the operations in each size class that are
    1.26 +  supported. Doing this allows supported operations to be used along
    1.27 +  side of emulated operations.
    1.28 +*/
    1.29 +
    1.30 +/* 
    1.31 +   Linux version.
    1.32 +
    1.33 +   Test for gnu C builtin support for atomic operations. The only way
    1.34 +   I know of is to check to see if the
    1.35 +   __GCC_HAVE_SYNC_COMPARE_AND_SWAP_* macros are defined.
    1.36 + */
    1.37 +
    1.38 +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
    1.39 +#define HAVE_ALL_8_BIT_OPS
    1.40 +
    1.41 +#define nativeExchange8(ptr, value)			(__sync_lock_test_and_set(ptr, value))
    1.42 +#define nativeCompareThenSet8(ptr, oldvalue, newvalue) 	(oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
    1.43 +#define nativeTestThenSet8(ptr)    	     		(0 == __sync_lock_test_and_set(ptr, 1))
    1.44 +#define nativeClear8(ptr)				(__sync_lock_release(ptr))
    1.45 +#define nativeFetchThenIncrement8(ptr)   		(__sync_fetch_and_add(ptr, 1))
    1.46 +#define nativeFetchThenDecrement8(ptr) 			(__sync_fetch_and_sub(ptr, 1))
    1.47 +#define nativeFetchThenAdd8(ptr, value) 		(__sync_fetch_and_add(ptr, value))
    1.48 +#define nativeFetchThenSubtract8(ptr, value) 		(__sync_fetch_and_sub(ptr, value))
    1.49 +#define nativeIncrementThenFetch8(ptr) 			(__sync_add_and_fetch(ptr, 1))
    1.50 +#define nativeDecrementThenFetch8(ptr) 			(__sync_sub_and_fetch(ptr, 1))
    1.51 +#define nativeAddThenFetch8(ptr, value) 		(__sync_add_and_fetch(ptr, value))
    1.52 +#define nativeSubtractThenFetch8(ptr, value) 		(__sync_sub_and_fetch(ptr, value))
    1.53 +#endif
    1.54 +
    1.55 +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
    1.56 +#define HAVE_ALL_16_BIT_OPS
    1.57 +
    1.58 +#define nativeExchange16(ptr, value)			(__sync_lock_test_and_set(ptr, value))
    1.59 +#define nativeCompareThenSet16(ptr, oldvalue, newvalue) (oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
    1.60 +#define nativeTestThenSet16(ptr)    	     		(0 == __sync_lock_test_and_set(ptr, 1))
    1.61 +#define nativeClear16(ptr)				(__sync_lock_release(ptr))
    1.62 +#define nativeFetchThenIncrement16(ptr)   		(__sync_fetch_and_add(ptr, 1))
    1.63 +#define nativeFetchThenDecrement16(ptr) 		(__sync_fetch_and_sub(ptr, 1))
    1.64 +#define nativeFetchThenAdd16(ptr, value) 		(__sync_fetch_and_add(ptr, value))
    1.65 +#define nativeFetchThenSubtract16(ptr, value) 		(__sync_fetch_and_sub(ptr, value))
    1.66 +#define nativeIncrementThenFetch16(ptr) 		(__sync_add_and_fetch(ptr, 1))
    1.67 +#define nativeDecrementThenFetch16(ptr) 		(__sync_sub_and_fetch(ptr, 1))
    1.68 +#define nativeAddThenFetch16(ptr, value) 		(__sync_add_and_fetch(ptr, value))
    1.69 +#define nativeSubtractThenFetch16(ptr, value) 		(__sync_sub_and_fetch(ptr, value))
    1.70 +#endif
    1.71 +
    1.72 +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
    1.73 +#define HAVE_ALL_32_BIT_OPS
    1.74 +
    1.75 +#define nativeExchange32(ptr, value)			(__sync_lock_test_and_set(ptr, value))
    1.76 +#define nativeCompareThenSet32(ptr, oldvalue, newvalue) (oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
    1.77 +#define nativeTestThenSet32(ptr)    	     		(0 == __sync_lock_test_and_set(ptr, 1))
    1.78 +#define nativeClear32(ptr)				(__sync_lock_release(ptr))
    1.79 +#define nativeFetchThenIncrement32(ptr)   		(__sync_fetch_and_add(ptr, 1))
    1.80 +#define nativeFetchThenDecrement32(ptr) 		(__sync_fetch_and_sub(ptr, 1))
    1.81 +#define nativeFetchThenAdd32(ptr, value) 		(__sync_fetch_and_add(ptr, value))
    1.82 +#define nativeFetchThenSubtract32(ptr, value) 		(__sync_fetch_and_sub(ptr, value))
    1.83 +#define nativeIncrementThenFetch32(ptr) 		(__sync_add_and_fetch(ptr, 1))
    1.84 +#define nativeDecrementThenFetch32(ptr) 		(__sync_sub_and_fetch(ptr, 1))
    1.85 +#define nativeAddThenFetch32(ptr, value) 		(__sync_add_and_fetch(ptr, value))
    1.86 +#define nativeSubtractThenFetch32(ptr, value) 		(__sync_sub_and_fetch(ptr, value))
    1.87 +#endif
    1.88 +
    1.89 +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
    1.90 +#define HAVE_ALL_64_BIT_OPS
    1.91 +
    1.92 +#define nativeExchange64(ptr, value)			(__sync_lock_test_and_set(ptr, value))
    1.93 +#define nativeCompareThenSet64(ptr, oldvalue, newvalue) (oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
    1.94 +#define nativeTestThenSet64(ptr)    	     		(0 == __sync_lock_test_and_set(ptr, 1))
    1.95 +#define nativeClear64(ptr)				(__sync_lock_release(ptr))
    1.96 +#define nativeFetchThenIncrement64(ptr)   		(__sync_fetch_and_add(ptr, 1))
    1.97 +#define nativeFetchThenDecrement64(ptr) 		(__sync_fetch_and_sub(ptr, 1))
    1.98 +#define nativeFetchThenAdd64(ptr, value) 		(__sync_fetch_and_add(ptr, value))
    1.99 +#define nativeFetchThenSubtract64(ptr, value) 		(__sync_fetch_and_sub(ptr, value))
   1.100 +#define nativeIncrementThenFetch64(ptr) 		(__sync_add_and_fetch(ptr, 1))
   1.101 +#define nativeDecrementThenFetch64(ptr) 		(__sync_sub_and_fetch(ptr, 1))
   1.102 +#define nativeAddThenFetch64(ptr, value) 		(__sync_add_and_fetch(ptr, value))
   1.103 +#define nativeSubtractThenFetch64(ptr, value) 		(__sync_sub_and_fetch(ptr, value))
   1.104 +#endif
   1.105 +
   1.106 +/* 
   1.107 +If any of the operations are not provided then we must emulate some of
   1.108 +them.
   1.109 + */
   1.110 +
   1.111 +#if !defined(HAVE_ALL_8_BIT_OPS) || !defined(HAVE_ALL_16_BIT_OPS) || !defined(HAVE_ALL_32_BIT_OPS) || !defined(HAVE_ALL_64_BIT_OPS)
   1.112 +
   1.113 +static Uint32 lock = 0;
   1.114 +
   1.115 +#define privateWaitLock()	       \
   1.116 +   while (nativeTestThenSet32(&lock))  \
   1.117 +   {				       \
   1.118 +   };
   1.119 +
   1.120 +#define privateUnlock() (nativeClear32(&lock))
   1.121 +#endif
   1.122 +
   1.123 +/* 8 bit atomic operations */
   1.124 +
   1.125 +Uint8
   1.126 +SDL_AtomicExchange8(Uint8 * ptr, Uint8 value)
   1.127 +{
   1.128 +#ifdef nativeExchange8
   1.129 +   return nativeExchange8(ptr, value);
   1.130 +#else
   1.131 +   Uint8 tmp = 0;;
   1.132 +
   1.133 +   privateWaitLock();
   1.134 +   tmp = *ptr;
   1.135 +   *ptr = value;
   1.136 +   privateUnlock();
   1.137 +
   1.138 +   return tmp;
   1.139 +#endif
   1.140 +}
   1.141 +
   1.142 +SDL_bool
   1.143 +SDL_AtomicCompareThenSet8(Uint8 * ptr, Uint8 oldvalue, Uint8 newvalue)
   1.144 +{
   1.145 +#ifdef nativeCompareThenSet8
   1.146 +   return (SDL_bool)nativeCompareThenSet8(ptr, oldvalue, newvalue);
   1.147 +#else
   1.148 +   SDL_bool result = SDL_FALSE;
   1.149 +
   1.150 +   privateWaitLock();
   1.151 +   result = (*ptr == oldvalue);
   1.152 +   if (result)
   1.153 +   {
   1.154 +      *ptr = newvalue;
   1.155 +   }
   1.156 +   privateUnlock();
   1.157 +
   1.158 +   return result;
   1.159 +#endif
   1.160 +}
   1.161 +
   1.162 +SDL_bool
   1.163 +SDL_AtomicTestThenSet8(Uint8 * ptr)
   1.164 +{
   1.165 +#ifdef nativeTestThenSet8
   1.166 +   return (SDL_bool)nativeTestThenSet8(ptr);
   1.167 +#else
   1.168 +   SDL_bool result = SDL_FALSE;
   1.169 +
   1.170 +   privateWaitLock();
   1.171 +   result = (*ptr == 0);
   1.172 +   if (result)
   1.173 +   {
   1.174 +      *ptr = 1;
   1.175 +   }
   1.176 +   privateUnlock();
   1.177 +
   1.178 +   return result;
   1.179 +#endif
   1.180 +}
   1.181 +
   1.182 +void
   1.183 +SDL_AtomicClear8(Uint8 * ptr)
   1.184 +{
   1.185 +#ifdef nativeClear8
   1.186 +   nativeClear8(ptr);
   1.187 +#else
   1.188 +   privateWaitLock();
   1.189 +   *ptr = 0;
   1.190 +   privateUnlock();
   1.191 +
   1.192 +   return;
   1.193 +#endif
   1.194 +}
   1.195 +
   1.196 +Uint8
   1.197 +SDL_AtomicFetchThenIncrement8(Uint8 * ptr)
   1.198 +{
   1.199 +#ifdef nativeFetchThenIncrement8
   1.200 +   return nativeFetchThenIncrement8(ptr);
   1.201 +#else
   1.202 +   Uint8 tmp = 0;;
   1.203 +
   1.204 +   privateWaitLock();
   1.205 +   tmp = *ptr;
   1.206 +   (*ptr)+= 1;
   1.207 +   privateUnlock();
   1.208 +
   1.209 +   return tmp;
   1.210 +#endif
   1.211 +}
   1.212 +
   1.213 +Uint8
   1.214 +SDL_AtomicFetchThenDecrement8(Uint8 * ptr)
   1.215 +{
   1.216 +#ifdef nativeFetchThenDecrement8
   1.217 +   return nativeFetchThenDecrement8(ptr);
   1.218 +#else
   1.219 +   Uint8 tmp = 0;;
   1.220 +
   1.221 +   privateWaitLock();
   1.222 +   tmp = *ptr;
   1.223 +   (*ptr) -= 1;
   1.224 +   privateUnlock();
   1.225 +
   1.226 +   return tmp;
   1.227 +#endif
   1.228 +}
   1.229 +
   1.230 +Uint8
   1.231 +SDL_AtomicFetchThenAdd8(Uint8 * ptr, Uint8 value)
   1.232 +{
   1.233 +#ifdef nativeFetchThenAdd8
   1.234 +   return nativeFetchThenAdd8(ptr, value);
   1.235 +#else
   1.236 +   Uint8 tmp = 0;;
   1.237 +
   1.238 +   privateWaitLock();
   1.239 +   tmp = *ptr;
   1.240 +   (*ptr)+= value;
   1.241 +   privateUnlock();
   1.242 +
   1.243 +   return tmp;
   1.244 +#endif
   1.245 +}
   1.246 +
   1.247 +Uint8
   1.248 +SDL_AtomicFetchThenSubtract8(Uint8 * ptr, Uint8 value)
   1.249 +{
   1.250 +#ifdef nativeFetchThenSubtract8
   1.251 +   return nativeFetchThenSubtract8(ptr, value);
   1.252 +#else
   1.253 +   Uint8 tmp = 0;;
   1.254 +
   1.255 +   privateWaitLock();
   1.256 +   tmp = *ptr;
   1.257 +   (*ptr)-= value;
   1.258 +   privateUnlock();
   1.259 +
   1.260 +   return tmp;
   1.261 +#endif
   1.262 +}
   1.263 +
   1.264 +Uint8
   1.265 +SDL_AtomicIncrementThenFetch8(Uint8 * ptr)
   1.266 +{
   1.267 +#ifdef nativeIncrementThenFetch8
   1.268 +   return nativeIncrementThenFetch8(ptr);
   1.269 +#else
   1.270 +   Uint8 tmp = 0;;
   1.271 +
   1.272 +   privateWaitLock();
   1.273 +   (*ptr)+= 1;
   1.274 +   tmp = *ptr;
   1.275 +   privateUnlock();
   1.276 +
   1.277 +   return tmp;
   1.278 +#endif
   1.279 +}
   1.280 +
   1.281 +Uint8
   1.282 +SDL_AtomicDecrementThenFetch8(Uint8 * ptr)
   1.283 +{
   1.284 +#ifdef nativeDecrementThenFetch8
   1.285 +   return nativeDecrementThenFetch8(ptr);
   1.286 +#else
   1.287 +   Uint8 tmp = 0;;
   1.288 +
   1.289 +   privateWaitLock();
   1.290 +   (*ptr)-= 1;
   1.291 +   tmp = *ptr;
   1.292 +   privateUnlock();
   1.293 +
   1.294 +   return tmp;
   1.295 +#endif
   1.296 +}
   1.297 +
   1.298 +Uint8
   1.299 +SDL_AtomicAddThenFetch8(Uint8 * ptr, Uint8 value)
   1.300 +{
   1.301 +#ifdef nativeAddThenFetch8
   1.302 +   return nativeAddThenFetch8(ptr, value);
   1.303 +#else
   1.304 +   Uint8 tmp = 0;;
   1.305 +
   1.306 +   privateWaitLock();
   1.307 +   (*ptr)+= value;
   1.308 +   tmp = *ptr;
   1.309 +   privateUnlock();
   1.310 +
   1.311 +   return tmp;
   1.312 +#endif
   1.313 +}
   1.314 +
   1.315 +Uint8
   1.316 +SDL_AtomicSubtractThenFetch8(Uint8 * ptr, Uint8 value)
   1.317 +{
   1.318 +#ifdef nativeSubtractThenFetch8
   1.319 +   return nativeSubtractThenFetch8(ptr, value);
   1.320 +#else
   1.321 +   Uint8 tmp = 0;;
   1.322 +
   1.323 +   privateWaitLock();
   1.324 +   (*ptr)-= value;
   1.325 +   tmp = *ptr;
   1.326 +   privateUnlock();
   1.327 +
   1.328 +   return tmp;
   1.329 +#endif
   1.330 +}
   1.331 +
   1.332 +/* 16 bit atomic operations */
   1.333 +
   1.334 +Uint16
   1.335 +SDL_AtomicExchange16(Uint16 * ptr, Uint16 value)
   1.336 +{
   1.337 +#ifdef nativeExchange16
   1.338 +   return nativeExchange16(ptr, value);
   1.339 +#else
   1.340 +   Uint16 tmp = 0;;
   1.341 +
   1.342 +   privateWaitLock();
   1.343 +   tmp = *ptr;
   1.344 +   *ptr = value;
   1.345 +   privateUnlock();
   1.346 +
   1.347 +   return tmp;
   1.348 +#endif
   1.349 +}
   1.350 +
   1.351 +SDL_bool
   1.352 +SDL_AtomicCompareThenSet16(Uint16 * ptr, Uint16 oldvalue, Uint16 newvalue)
   1.353 +{
   1.354 +#ifdef nativeCompareThenSet16
   1.355 +   return (SDL_bool)nativeCompareThenSet16(ptr, oldvalue, newvalue);
   1.356 +#else
   1.357 +   SDL_bool result = SDL_FALSE;
   1.358 +
   1.359 +   privateWaitLock();
   1.360 +   result = (*ptr == oldvalue);
   1.361 +   if (result)
   1.362 +   {
   1.363 +      *ptr = newvalue;
   1.364 +   }
   1.365 +   privateUnlock();
   1.366 +
   1.367 +   return result;
   1.368 +#endif
   1.369 +}
   1.370 +
   1.371 +SDL_bool
   1.372 +SDL_AtomicTestThenSet16(Uint16 * ptr)
   1.373 +{
   1.374 +#ifdef nativeTestThenSet16
   1.375 +   return (SDL_bool)nativeTestThenSet16(ptr);
   1.376 +#else
   1.377 +   SDL_bool result = SDL_FALSE;
   1.378 +
   1.379 +   privateWaitLock();
   1.380 +   result = (*ptr == 0);
   1.381 +   if (result)
   1.382 +   {
   1.383 +      *ptr = 1;
   1.384 +   }
   1.385 +   privateUnlock();
   1.386 +
   1.387 +   return result;
   1.388 +#endif
   1.389 +}
   1.390 +
   1.391 +void
   1.392 +SDL_AtomicClear16(Uint16 * ptr)
   1.393 +{
   1.394 +#ifdef nativeClear16
   1.395 +   nativeClear16(ptr);
   1.396 +#else
   1.397 +   privateWaitLock();
   1.398 +   *ptr = 0;
   1.399 +   privateUnlock();
   1.400 +
   1.401 +   return;
   1.402 +#endif
   1.403 +}
   1.404 +
   1.405 +Uint16
   1.406 +SDL_AtomicFetchThenIncrement16(Uint16 * ptr)
   1.407 +{
   1.408 +#ifdef nativeFetchThenIncrement16
   1.409 +   return nativeFetchThenIncrement16(ptr);
   1.410 +#else
   1.411 +   Uint16 tmp = 0;;
   1.412 +
   1.413 +   privateWaitLock();
   1.414 +   tmp = *ptr;
   1.415 +   (*ptr)+= 1;
   1.416 +   privateUnlock();
   1.417 +
   1.418 +   return tmp;
   1.419 +#endif
   1.420 +}
   1.421 +
   1.422 +Uint16
   1.423 +SDL_AtomicFetchThenDecrement16(Uint16 * ptr)
   1.424 +{
   1.425 +#ifdef nativeFetchThenDecrement16
   1.426 +   return nativeFetchThenDecrement16(ptr);
   1.427 +#else
   1.428 +   Uint16 tmp = 0;;
   1.429 +
   1.430 +   privateWaitLock();
   1.431 +   tmp = *ptr;
   1.432 +   (*ptr) -= 1;
   1.433 +   privateUnlock();
   1.434 +
   1.435 +   return tmp;
   1.436 +#endif
   1.437 +}
   1.438 +
   1.439 +Uint16
   1.440 +SDL_AtomicFetchThenAdd16(Uint16 * ptr, Uint16 value)
   1.441 +{
   1.442 +#ifdef nativeFetchThenAdd16
   1.443 +   return nativeFetchThenAdd16(ptr, value);
   1.444 +#else
   1.445 +   Uint16 tmp = 0;;
   1.446 +
   1.447 +   privateWaitLock();
   1.448 +   tmp = *ptr;
   1.449 +   (*ptr)+= value;
   1.450 +   privateUnlock();
   1.451 +
   1.452 +   return tmp;
   1.453 +#endif
   1.454 +}
   1.455 +
   1.456 +Uint16
   1.457 +SDL_AtomicFetchThenSubtract16(Uint16 * ptr, Uint16 value)
   1.458 +{
   1.459 +#ifdef nativeFetchThenSubtract16
   1.460 +   return nativeFetchThenSubtract16(ptr, value);
   1.461 +#else
   1.462 +   Uint16 tmp = 0;;
   1.463 +
   1.464 +   privateWaitLock();
   1.465 +   tmp = *ptr;
   1.466 +   (*ptr)-= value;
   1.467 +   privateUnlock();
   1.468 +
   1.469 +   return tmp;
   1.470 +#endif
   1.471 +}
   1.472 +
   1.473 +Uint16
   1.474 +SDL_AtomicIncrementThenFetch16(Uint16 * ptr)
   1.475 +{
   1.476 +#ifdef nativeIncrementThenFetch16
   1.477 +   return nativeIncrementThenFetch16(ptr);
   1.478 +#else
   1.479 +   Uint16 tmp = 0;;
   1.480 +
   1.481 +   privateWaitLock();
   1.482 +   (*ptr)+= 1;
   1.483 +   tmp = *ptr;
   1.484 +   privateUnlock();
   1.485 +
   1.486 +   return tmp;
   1.487 +#endif
   1.488 +}
   1.489 +
   1.490 +Uint16
   1.491 +SDL_AtomicDecrementThenFetch16(Uint16 * ptr)
   1.492 +{
   1.493 +#ifdef nativeDecrementThenFetch16
   1.494 +   return nativeDecrementThenFetch16(ptr);
   1.495 +#else
   1.496 +   Uint16 tmp = 0;;
   1.497 +
   1.498 +   privateWaitLock();
   1.499 +   (*ptr)-= 1;
   1.500 +   tmp = *ptr;
   1.501 +   privateUnlock();
   1.502 +
   1.503 +   return tmp;
   1.504 +#endif
   1.505 +}
   1.506 +
   1.507 +Uint16
   1.508 +SDL_AtomicAddThenFetch16(Uint16 * ptr, Uint16 value)
   1.509 +{
   1.510 +#ifdef nativeAddThenFetch16
   1.511 +   return nativeAddThenFetch16(ptr, value);
   1.512 +#else
   1.513 +   Uint16 tmp = 0;;
   1.514 +
   1.515 +   privateWaitLock();
   1.516 +   (*ptr)+= value;
   1.517 +   tmp = *ptr;
   1.518 +   privateUnlock();
   1.519 +
   1.520 +   return tmp;
   1.521 +#endif
   1.522 +}
   1.523 +
   1.524 +Uint16
   1.525 +SDL_AtomicSubtractThenFetch16(Uint16 * ptr, Uint16 value)
   1.526 +{
   1.527 +#ifdef nativeSubtractThenFetch16
   1.528 +   return nativeSubtractThenFetch16(ptr, value);
   1.529 +#else
   1.530 +   Uint16 tmp = 0;;
   1.531 +
   1.532 +   privateWaitLock();
   1.533 +   (*ptr)-= value;
   1.534 +   tmp = *ptr;
   1.535 +   privateUnlock();
   1.536 +
   1.537 +   return tmp;
   1.538 +#endif
   1.539 +}
   1.540 +
   1.541 +/* 32 bit atomic operations */
   1.542 +
   1.543  Uint32
   1.544  SDL_AtomicExchange32(Uint32 * ptr, Uint32 value)
   1.545  {
   1.546 -   return __sync_lock_test_and_set(ptr, value);
   1.547 +#ifdef nativeExchange32
   1.548 +   return nativeExchange32(ptr, value);
   1.549 +#else
   1.550 +   Uint32 tmp = 0;;
   1.551 +
   1.552 +   privateWaitLock();
   1.553 +   tmp = *ptr;
   1.554 +   *ptr = value;
   1.555 +   privateUnlock();
   1.556 +
   1.557 +   return tmp;
   1.558 +#endif
   1.559  }
   1.560  
   1.561  SDL_bool
   1.562  SDL_AtomicCompareThenSet32(Uint32 * ptr, Uint32 oldvalue, Uint32 newvalue)
   1.563  {
   1.564 -   return (SDL_bool)__sync_bool_compare_and_swap(ptr, oldvalue, newvalue);
   1.565 +#ifdef nativeCompareThenSet32
   1.566 +   return (SDL_bool)nativeCompareThenSet32(ptr, oldvalue, newvalue);
   1.567 +#else
   1.568 +   SDL_bool result = SDL_FALSE;
   1.569 +
   1.570 +   privateWaitLock();
   1.571 +   result = (*ptr == oldvalue);
   1.572 +   if (result)
   1.573 +   {
   1.574 +      *ptr = newvalue;
   1.575 +   }
   1.576 +   privateUnlock();
   1.577 +
   1.578 +   return result;
   1.579 +#endif
   1.580  }
   1.581  
   1.582  SDL_bool
   1.583  SDL_AtomicTestThenSet32(Uint32 * ptr)
   1.584  {
   1.585 -   return (SDL_bool)(0 == __sync_lock_test_and_set(ptr, 1));
   1.586 +#ifdef nativeTestThenSet32
   1.587 +   return (SDL_bool)nativeTestThenSet32(ptr);
   1.588 +#else
   1.589 +   SDL_bool result = SDL_FALSE;
   1.590 +
   1.591 +   privateWaitLock();
   1.592 +   result = (*ptr == 0);
   1.593 +   if (result)
   1.594 +   {
   1.595 +      *ptr = 1;
   1.596 +   }
   1.597 +   privateUnlock();
   1.598 +
   1.599 +   return result;
   1.600 +#endif
   1.601  }
   1.602  
   1.603  void
   1.604  SDL_AtomicClear32(Uint32 * ptr)
   1.605  {
   1.606 -   __sync_lock_release(ptr);
   1.607 +#ifdef nativeClear32
   1.608 +   nativeClear32(ptr);
   1.609 +#else
   1.610 +   privateWaitLock();
   1.611 +   *ptr = 0;
   1.612 +   privateUnlock();
   1.613 +
   1.614 +   return;
   1.615 +#endif
   1.616  }
   1.617  
   1.618  Uint32
   1.619  SDL_AtomicFetchThenIncrement32(Uint32 * ptr)
   1.620  {
   1.621 -   return __sync_fetch_and_add(ptr, 1);
   1.622 +#ifdef nativeFetchThenIncrement32
   1.623 +   return nativeFetchThenIncrement32(ptr);
   1.624 +#else
   1.625 +   Uint32 tmp = 0;;
   1.626 +
   1.627 +   privateWaitLock();
   1.628 +   tmp = *ptr;
   1.629 +   (*ptr)+= 1;
   1.630 +   privateUnlock();
   1.631 +
   1.632 +   return tmp;
   1.633 +#endif
   1.634  }
   1.635  
   1.636  Uint32
   1.637  SDL_AtomicFetchThenDecrement32(Uint32 * ptr)
   1.638  {
   1.639 -   return __sync_fetch_and_sub(ptr, 1);
   1.640 +#ifdef nativeFetchThenDecrement32
   1.641 +   return nativeFetchThenDecrement32(ptr);
   1.642 +#else
   1.643 +   Uint32 tmp = 0;;
   1.644 +
   1.645 +   privateWaitLock();
   1.646 +   tmp = *ptr;
   1.647 +   (*ptr) -= 1;
   1.648 +   privateUnlock();
   1.649 +
   1.650 +   return tmp;
   1.651 +#endif
   1.652  }
   1.653  
   1.654  Uint32
   1.655  SDL_AtomicFetchThenAdd32(Uint32 * ptr, Uint32 value)
   1.656  {
   1.657 -   return __sync_fetch_and_add(ptr, value);
   1.658 +#ifdef nativeFetchThenAdd32
   1.659 +   return nativeFetchThenAdd32(ptr, value);
   1.660 +#else
   1.661 +   Uint32 tmp = 0;;
   1.662 +
   1.663 +   privateWaitLock();
   1.664 +   tmp = *ptr;
   1.665 +   (*ptr)+= value;
   1.666 +   privateUnlock();
   1.667 +
   1.668 +   return tmp;
   1.669 +#endif
   1.670  }
   1.671  
   1.672  Uint32
   1.673  SDL_AtomicFetchThenSubtract32(Uint32 * ptr, Uint32 value)
   1.674  {
   1.675 -   return __sync_fetch_and_sub(ptr, value);
   1.676 +#ifdef nativeFetchThenSubtract32
   1.677 +   return nativeFetchThenSubtract32(ptr, value);
   1.678 +#else
   1.679 +   Uint32 tmp = 0;;
   1.680 +
   1.681 +   privateWaitLock();
   1.682 +   tmp = *ptr;
   1.683 +   (*ptr)-= value;
   1.684 +   privateUnlock();
   1.685 +
   1.686 +   return tmp;
   1.687 +#endif
   1.688  }
   1.689  
   1.690  Uint32
   1.691  SDL_AtomicIncrementThenFetch32(Uint32 * ptr)
   1.692  {
   1.693 -   return __sync_add_and_fetch(ptr, 1);
   1.694 +#ifdef nativeIncrementThenFetch32
   1.695 +   return nativeIncrementThenFetch32(ptr);
   1.696 +#else
   1.697 +   Uint32 tmp = 0;;
   1.698 +
   1.699 +   privateWaitLock();
   1.700 +   (*ptr)+= 1;
   1.701 +   tmp = *ptr;
   1.702 +   privateUnlock();
   1.703 +
   1.704 +   return tmp;
   1.705 +#endif
   1.706  }
   1.707  
   1.708  Uint32
   1.709  SDL_AtomicDecrementThenFetch32(Uint32 * ptr)
   1.710  {
   1.711 -   return __sync_sub_and_fetch(ptr, 1);
   1.712 +#ifdef nativeDecrementThenFetch32
   1.713 +   return nativeDecrementThenFetch32(ptr);
   1.714 +#else
   1.715 +   Uint32 tmp = 0;;
   1.716 +
   1.717 +   privateWaitLock();
   1.718 +   (*ptr)-= 1;
   1.719 +   tmp = *ptr;
   1.720 +   privateUnlock();
   1.721 +
   1.722 +   return tmp;
   1.723 +#endif
   1.724  }
   1.725  
   1.726  Uint32
   1.727  SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 value)
   1.728  {
   1.729 -   return __sync_add_and_fetch(ptr, value);
   1.730 +#ifdef nativeAddThenFetch32
   1.731 +   return nativeAddThenFetch32(ptr, value);
   1.732 +#else
   1.733 +   Uint32 tmp = 0;;
   1.734 +
   1.735 +   privateWaitLock();
   1.736 +   (*ptr)+= value;
   1.737 +   tmp = *ptr;
   1.738 +   privateUnlock();
   1.739 +
   1.740 +   return tmp;
   1.741 +#endif
   1.742  }
   1.743  
   1.744  Uint32
   1.745  SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value)
   1.746  {
   1.747 -   return __sync_sub_and_fetch(ptr, value);
   1.748 +#ifdef nativeSubtractThenFetch32
   1.749 +   return nativeSubtractThenFetch32(ptr, value);
   1.750 +#else
   1.751 +   Uint32 tmp = 0;;
   1.752 +
   1.753 +   privateWaitLock();
   1.754 +   (*ptr)-= value;
   1.755 +   tmp = *ptr;
   1.756 +   privateUnlock();
   1.757 +
   1.758 +   return tmp;
   1.759 +#endif
   1.760  }
   1.761  
   1.762 -/* #ifdef SDL_HAS_64BIT_TYPE */
   1.763 -#if 0
   1.764 +/* 64 bit atomic operations */
   1.765 +#ifdef SDL_HAS_64BIT_TYPE
   1.766  
   1.767  Uint64
   1.768  SDL_AtomicExchange64(Uint64 * ptr, Uint64 value)
   1.769  {
   1.770 -   return __sync_lock_test_and_set(ptr, value);
   1.771 +#ifdef nativeExchange64
   1.772 +   return nativeExchange64(ptr, value);
   1.773 +#else
   1.774 +   Uint64 tmp = 0;;
   1.775 +
   1.776 +   privateWaitLock();
   1.777 +   tmp = *ptr;
   1.778 +   *ptr = value;
   1.779 +   privateUnlock();
   1.780 +
   1.781 +   return tmp;
   1.782 +#endif
   1.783  }
   1.784  
   1.785  SDL_bool
   1.786  SDL_AtomicCompareThenSet64(Uint64 * ptr, Uint64 oldvalue, Uint64 newvalue)
   1.787  {
   1.788 -   return (SDL_bool)__sync_bool_compare_and_swap(ptr, oldvalue, newvalue);
   1.789 +#ifdef nativeCompareThenSet64
   1.790 +   return (SDL_bool)nativeCompareThenSet64(ptr, oldvalue, newvalue);
   1.791 +#else
   1.792 +   SDL_bool result = SDL_FALSE;
   1.793 +
   1.794 +   privateWaitLock();
   1.795 +   result = (*ptr == oldvalue);
   1.796 +   if (result)
   1.797 +   {
   1.798 +      *ptr = newvalue;
   1.799 +   }
   1.800 +   privateUnlock();
   1.801 +
   1.802 +   return result;
   1.803 +#endif
   1.804  }
   1.805  
   1.806  SDL_bool
   1.807  SDL_AtomicTestThenSet64(Uint64 * ptr)
   1.808  {
   1.809 -   return (SDL_bool)(0 == __sync_lock_test_and_set(ptr, 1));
   1.810 +#ifdef nativeTestThenSet64
   1.811 +   return (SDL_bool)nativeTestThenSet64(ptr);
   1.812 +#else
   1.813 +   SDL_bool result = SDL_FALSE;
   1.814 +
   1.815 +   privateWaitLock();
   1.816 +   result = (*ptr == 0);
   1.817 +   if (result)
   1.818 +   {
   1.819 +      *ptr = 1;
   1.820 +   }
   1.821 +   privateUnlock();
   1.822 +
   1.823 +   return result;
   1.824 +#endif
   1.825  }
   1.826  
   1.827  void
   1.828  SDL_AtomicClear64(Uint64 * ptr)
   1.829  {
   1.830 -   __sync_lock_release(ptr);
   1.831 +#ifdef nativeClear64
   1.832 +   nativeClear64(ptr);
   1.833 +#else
   1.834 +   privateWaitLock();
   1.835 +   *ptr = 0;
   1.836 +   privateUnlock();
   1.837 +
   1.838 +   return;
   1.839 +#endif
   1.840  }
   1.841  
   1.842  Uint64
   1.843  SDL_AtomicFetchThenIncrement64(Uint64 * ptr)
   1.844  {
   1.845 -   return __sync_fetch_and_add(ptr, 1);
   1.846 +#ifdef nativeFetchThenIncrement64
   1.847 +   return nativeFetchThenIncrement64(ptr);
   1.848 +#else
   1.849 +   Uint64 tmp = 0;;
   1.850 +
   1.851 +   privateWaitLock();
   1.852 +   tmp = *ptr;
   1.853 +   (*ptr)+= 1;
   1.854 +   privateUnlock();
   1.855 +
   1.856 +   return tmp;
   1.857 +#endif
   1.858  }
   1.859  
   1.860  Uint64
   1.861  SDL_AtomicFetchThenDecrement64(Uint64 * ptr)
   1.862  {
   1.863 -   return __sync_fetch_and_sub(ptr, 1);
   1.864 +#ifdef nativeFetchThenDecrement64
   1.865 +   return nativeFetchThenDecrement64(ptr);
   1.866 +#else
   1.867 +   Uint64 tmp = 0;;
   1.868 +
   1.869 +   privateWaitLock();
   1.870 +   tmp = *ptr;
   1.871 +   (*ptr) -= 1;
   1.872 +   privateUnlock();
   1.873 +
   1.874 +   return tmp;
   1.875 +#endif
   1.876  }
   1.877  
   1.878  Uint64
   1.879  SDL_AtomicFetchThenAdd64(Uint64 * ptr, Uint64 value)
   1.880  {
   1.881 -   return __sync_fetch_and_add(ptr, value);
   1.882 +#ifdef nativeFetchThenAdd64
   1.883 +   return nativeFetchThenAdd64(ptr, value);
   1.884 +#else
   1.885 +   Uint64 tmp = 0;;
   1.886 +
   1.887 +   privateWaitLock();
   1.888 +   tmp = *ptr;
   1.889 +   (*ptr)+= value;
   1.890 +   privateUnlock();
   1.891 +
   1.892 +   return tmp;
   1.893 +#endif
   1.894  }
   1.895  
   1.896  Uint64
   1.897  SDL_AtomicFetchThenSubtract64(Uint64 * ptr, Uint64 value)
   1.898  {
   1.899 -   return __sync_fetch_and_sub(ptr, value);
   1.900 +#ifdef nativeFetchThenSubtract64
   1.901 +   return nativeFetchThenSubtract64(ptr, value);
   1.902 +#else
   1.903 +   Uint64 tmp = 0;;
   1.904 +
   1.905 +   privateWaitLock();
   1.906 +   tmp = *ptr;
   1.907 +   (*ptr)-= value;
   1.908 +   privateUnlock();
   1.909 +
   1.910 +   return tmp;
   1.911 +#endif
   1.912  }
   1.913  
   1.914  Uint64
   1.915  SDL_AtomicIncrementThenFetch64(Uint64 * ptr)
   1.916  {
   1.917 -   return __sync_add_and_fetch(ptr, 1);
   1.918 +#ifdef nativeIncrementThenFetch64
   1.919 +   return nativeIncrementThenFetch64(ptr);
   1.920 +#else
   1.921 +   Uint64 tmp = 0;;
   1.922 +
   1.923 +   privateWaitLock();
   1.924 +   (*ptr)+= 1;
   1.925 +   tmp = *ptr;
   1.926 +   privateUnlock();
   1.927 +
   1.928 +   return tmp;
   1.929 +#endif
   1.930  }
   1.931  
   1.932  Uint64
   1.933  SDL_AtomicDecrementThenFetch64(Uint64 * ptr)
   1.934  {
   1.935 -   return __sync_sub_and_fetch(ptr, 1);
   1.936 +#ifdef nativeDecrementThenFetch64
   1.937 +   return nativeDecrementThenFetch64(ptr);
   1.938 +#else
   1.939 +   Uint64 tmp = 0;;
   1.940 +
   1.941 +   privateWaitLock();
   1.942 +   (*ptr)-= 1;
   1.943 +   tmp = *ptr;
   1.944 +   privateUnlock();
   1.945 +
   1.946 +   return tmp;
   1.947 +#endif
   1.948  }
   1.949  
   1.950  Uint64
   1.951  SDL_AtomicAddThenFetch64(Uint64 * ptr, Uint64 value)
   1.952  {
   1.953 -   return __sync_add_and_fetch(ptr, value);
   1.954 +#ifdef nativeAddThenFetch64
   1.955 +   return nativeAddThenFetch64(ptr, value);
   1.956 +#else
   1.957 +   Uint64 tmp = 0;;
   1.958 +
   1.959 +   privateWaitLock();
   1.960 +   (*ptr)+= value;
   1.961 +   tmp = *ptr;
   1.962 +   privateUnlock();
   1.963 +
   1.964 +   return tmp;
   1.965 +#endif
   1.966  }
   1.967  
   1.968  Uint64
   1.969  SDL_AtomicSubtractThenFetch64(Uint64 * ptr, Uint64 value)
   1.970  {
   1.971 -   return __sync_sub_and_fetch(ptr, value);
   1.972 +#ifdef nativeSubtractThenFetch64
   1.973 +   return nativeSubtractThenFetch64(ptr, value);
   1.974 +#else
   1.975 +   Uint64 tmp = 0;;
   1.976 +
   1.977 +   privateWaitLock();
   1.978 +   (*ptr)-= value;
   1.979 +   tmp = *ptr;
   1.980 +   privateUnlock();
   1.981 +
   1.982 +   return tmp;
   1.983 +#endif
   1.984  }
   1.985  #endif
   1.986 +