src/atomic/linux/SDL_atomic.c
author Bob Pendleton <bob@pendleton.com>
Mon, 29 Jun 2009 19:54:43 +0000
changeset 3202 3aa519a5c676
parent 3201 c297230efc75
child 3212 759032c318d8
permissions -rw-r--r--
I've made so many changes I don't dare continue until I check the current stuff in.

/test/testatomic.c performs absolutely basic tests to show that the function work as expected. Need a second test to do more detailed tests.

/include/SDL_atomic.h provides declarations for all included functions.

/src/atomic/linux/SDL_atomic.c provided all the functions. On a generic built the 64 bit functions work, but they are emulated. On a build for -march=pentium and above the 64 bit functions use native instructions
/src/atomic/dummy/SDL_atomic.c emulates all the operations using SDL_mutex.h.
/src/atomic/win32/SDL_atomic.c is a copy of dummy
/src/atomic/macosx/SDL_atomic.s is a copy of dummy

These versions of SDL_atomic.c provide a frame work for building the library with a mixture of native and emulated functions. This allows the whole library to be provided on all platforms. (I hope.)
I hope this fits with the SDL philosophy of either providing a common subset or emulating when the platform is missing a feature.

I have not added dummy, macosx, or win32 to the build. They are there as place holders for future work.

I have modified congifure.in to compile sources in /src/atomic/linux. (The SDL configure.in file is an amazing piece of work and I hope I didn't mess it up. :-)
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 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 #include "SDL_stdinc.h"
    24 #include "SDL_atomic.h"
    25 
    26 /*
    27   This file provides 8, 16, 32, and 64 bit atomic operations. If the
    28   operations are provided by the native hardware and operating system
    29   they are used. If they are not then the operations are emulated
    30   using the SDL mutex operations. 
    31  */
    32 
    33 /* 
    34   First, detect whether the operations are supported and create
    35   #defines that indicate that they do exist. The goal is to have all
    36   the system dependent code in the top part of the file so that the
    37   bottom can be use unchanged across all platforms.
    38 
    39   Second, #define all the operations in each size class that are
    40   supported. Doing this allows supported operations to be used along
    41   side of emulated operations.
    42 */
    43 
    44 /* 
    45    Linux version.
    46 
    47    Test for gnu C builtin support for atomic operations. The only way
    48    I know of is to check to see if the
    49    __GCC_HAVE_SYNC_COMPARE_AND_SWAP_* macros are defined.
    50  */
    51 
    52 #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
    53 #define HAVE_ALL_8_BIT_OPS
    54 
    55 #define nativeExchange8(ptr, value)			(__sync_lock_test_and_set(ptr, value))
    56 #define nativeCompareThenSet8(ptr, oldvalue, newvalue) 	(oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
    57 #define nativeTestThenSet8(ptr)    	     		(0 == __sync_lock_test_and_set(ptr, 1))
    58 #define nativeClear8(ptr)				(__sync_lock_release(ptr))
    59 #define nativeFetchThenIncrement8(ptr)   		(__sync_fetch_and_add(ptr, 1))
    60 #define nativeFetchThenDecrement8(ptr) 			(__sync_fetch_and_sub(ptr, 1))
    61 #define nativeFetchThenAdd8(ptr, value) 		(__sync_fetch_and_add(ptr, value))
    62 #define nativeFetchThenSubtract8(ptr, value) 		(__sync_fetch_and_sub(ptr, value))
    63 #define nativeIncrementThenFetch8(ptr) 			(__sync_add_and_fetch(ptr, 1))
    64 #define nativeDecrementThenFetch8(ptr) 			(__sync_sub_and_fetch(ptr, 1))
    65 #define nativeAddThenFetch8(ptr, value) 		(__sync_add_and_fetch(ptr, value))
    66 #define nativeSubtractThenFetch8(ptr, value) 		(__sync_sub_and_fetch(ptr, value))
    67 #endif
    68 
    69 #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
    70 #define HAVE_ALL_16_BIT_OPS
    71 
    72 #define nativeExchange16(ptr, value)			(__sync_lock_test_and_set(ptr, value))
    73 #define nativeCompareThenSet16(ptr, oldvalue, newvalue) (oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
    74 #define nativeTestThenSet16(ptr)    	     		(0 == __sync_lock_test_and_set(ptr, 1))
    75 #define nativeClear16(ptr)				(__sync_lock_release(ptr))
    76 #define nativeFetchThenIncrement16(ptr)   		(__sync_fetch_and_add(ptr, 1))
    77 #define nativeFetchThenDecrement16(ptr) 		(__sync_fetch_and_sub(ptr, 1))
    78 #define nativeFetchThenAdd16(ptr, value) 		(__sync_fetch_and_add(ptr, value))
    79 #define nativeFetchThenSubtract16(ptr, value) 		(__sync_fetch_and_sub(ptr, value))
    80 #define nativeIncrementThenFetch16(ptr) 		(__sync_add_and_fetch(ptr, 1))
    81 #define nativeDecrementThenFetch16(ptr) 		(__sync_sub_and_fetch(ptr, 1))
    82 #define nativeAddThenFetch16(ptr, value) 		(__sync_add_and_fetch(ptr, value))
    83 #define nativeSubtractThenFetch16(ptr, value) 		(__sync_sub_and_fetch(ptr, value))
    84 #endif
    85 
    86 #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
    87 #define HAVE_ALL_32_BIT_OPS
    88 
    89 #define nativeExchange32(ptr, value)			(__sync_lock_test_and_set(ptr, value))
    90 #define nativeCompareThenSet32(ptr, oldvalue, newvalue) (oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
    91 #define nativeTestThenSet32(ptr)    	     		(0 == __sync_lock_test_and_set(ptr, 1))
    92 #define nativeClear32(ptr)				(__sync_lock_release(ptr))
    93 #define nativeFetchThenIncrement32(ptr)   		(__sync_fetch_and_add(ptr, 1))
    94 #define nativeFetchThenDecrement32(ptr) 		(__sync_fetch_and_sub(ptr, 1))
    95 #define nativeFetchThenAdd32(ptr, value) 		(__sync_fetch_and_add(ptr, value))
    96 #define nativeFetchThenSubtract32(ptr, value) 		(__sync_fetch_and_sub(ptr, value))
    97 #define nativeIncrementThenFetch32(ptr) 		(__sync_add_and_fetch(ptr, 1))
    98 #define nativeDecrementThenFetch32(ptr) 		(__sync_sub_and_fetch(ptr, 1))
    99 #define nativeAddThenFetch32(ptr, value) 		(__sync_add_and_fetch(ptr, value))
   100 #define nativeSubtractThenFetch32(ptr, value) 		(__sync_sub_and_fetch(ptr, value))
   101 #endif
   102 
   103 #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
   104 #define HAVE_ALL_64_BIT_OPS
   105 
   106 #define nativeExchange64(ptr, value)			(__sync_lock_test_and_set(ptr, value))
   107 #define nativeCompareThenSet64(ptr, oldvalue, newvalue) (oldvalue == __sync_val_compare_and_swap(ptr, oldvalue, newvalue))
   108 #define nativeTestThenSet64(ptr)    	     		(0 == __sync_lock_test_and_set(ptr, 1))
   109 #define nativeClear64(ptr)				(__sync_lock_release(ptr))
   110 #define nativeFetchThenIncrement64(ptr)   		(__sync_fetch_and_add(ptr, 1))
   111 #define nativeFetchThenDecrement64(ptr) 		(__sync_fetch_and_sub(ptr, 1))
   112 #define nativeFetchThenAdd64(ptr, value) 		(__sync_fetch_and_add(ptr, value))
   113 #define nativeFetchThenSubtract64(ptr, value) 		(__sync_fetch_and_sub(ptr, value))
   114 #define nativeIncrementThenFetch64(ptr) 		(__sync_add_and_fetch(ptr, 1))
   115 #define nativeDecrementThenFetch64(ptr) 		(__sync_sub_and_fetch(ptr, 1))
   116 #define nativeAddThenFetch64(ptr, value) 		(__sync_add_and_fetch(ptr, value))
   117 #define nativeSubtractThenFetch64(ptr, value) 		(__sync_sub_and_fetch(ptr, value))
   118 #endif
   119 
   120 /* 
   121 If any of the operations are not provided then we must emulate some of
   122 them.
   123  */
   124 
   125 #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)
   126 
   127 static Uint32 lock = 0;
   128 
   129 #define privateWaitLock()	       \
   130    while (nativeTestThenSet32(&lock))  \
   131    {				       \
   132    };
   133 
   134 #define privateUnlock() (nativeClear32(&lock))
   135 #endif
   136 
   137 /* 8 bit atomic operations */
   138 
   139 Uint8
   140 SDL_AtomicExchange8(Uint8 * ptr, Uint8 value)
   141 {
   142 #ifdef nativeExchange8
   143    return nativeExchange8(ptr, value);
   144 #else
   145    Uint8 tmp = 0;;
   146 
   147    privateWaitLock();
   148    tmp = *ptr;
   149    *ptr = value;
   150    privateUnlock();
   151 
   152    return tmp;
   153 #endif
   154 }
   155 
   156 SDL_bool
   157 SDL_AtomicCompareThenSet8(Uint8 * ptr, Uint8 oldvalue, Uint8 newvalue)
   158 {
   159 #ifdef nativeCompareThenSet8
   160    return (SDL_bool)nativeCompareThenSet8(ptr, oldvalue, newvalue);
   161 #else
   162    SDL_bool result = SDL_FALSE;
   163 
   164    privateWaitLock();
   165    result = (*ptr == oldvalue);
   166    if (result)
   167    {
   168       *ptr = newvalue;
   169    }
   170    privateUnlock();
   171 
   172    return result;
   173 #endif
   174 }
   175 
   176 SDL_bool
   177 SDL_AtomicTestThenSet8(Uint8 * ptr)
   178 {
   179 #ifdef nativeTestThenSet8
   180    return (SDL_bool)nativeTestThenSet8(ptr);
   181 #else
   182    SDL_bool result = SDL_FALSE;
   183 
   184    privateWaitLock();
   185    result = (*ptr == 0);
   186    if (result)
   187    {
   188       *ptr = 1;
   189    }
   190    privateUnlock();
   191 
   192    return result;
   193 #endif
   194 }
   195 
   196 void
   197 SDL_AtomicClear8(Uint8 * ptr)
   198 {
   199 #ifdef nativeClear8
   200    nativeClear8(ptr);
   201 #else
   202    privateWaitLock();
   203    *ptr = 0;
   204    privateUnlock();
   205 
   206    return;
   207 #endif
   208 }
   209 
   210 Uint8
   211 SDL_AtomicFetchThenIncrement8(Uint8 * ptr)
   212 {
   213 #ifdef nativeFetchThenIncrement8
   214    return nativeFetchThenIncrement8(ptr);
   215 #else
   216    Uint8 tmp = 0;;
   217 
   218    privateWaitLock();
   219    tmp = *ptr;
   220    (*ptr)+= 1;
   221    privateUnlock();
   222 
   223    return tmp;
   224 #endif
   225 }
   226 
   227 Uint8
   228 SDL_AtomicFetchThenDecrement8(Uint8 * ptr)
   229 {
   230 #ifdef nativeFetchThenDecrement8
   231    return nativeFetchThenDecrement8(ptr);
   232 #else
   233    Uint8 tmp = 0;;
   234 
   235    privateWaitLock();
   236    tmp = *ptr;
   237    (*ptr) -= 1;
   238    privateUnlock();
   239 
   240    return tmp;
   241 #endif
   242 }
   243 
   244 Uint8
   245 SDL_AtomicFetchThenAdd8(Uint8 * ptr, Uint8 value)
   246 {
   247 #ifdef nativeFetchThenAdd8
   248    return nativeFetchThenAdd8(ptr, value);
   249 #else
   250    Uint8 tmp = 0;;
   251 
   252    privateWaitLock();
   253    tmp = *ptr;
   254    (*ptr)+= value;
   255    privateUnlock();
   256 
   257    return tmp;
   258 #endif
   259 }
   260 
   261 Uint8
   262 SDL_AtomicFetchThenSubtract8(Uint8 * ptr, Uint8 value)
   263 {
   264 #ifdef nativeFetchThenSubtract8
   265    return nativeFetchThenSubtract8(ptr, value);
   266 #else
   267    Uint8 tmp = 0;;
   268 
   269    privateWaitLock();
   270    tmp = *ptr;
   271    (*ptr)-= value;
   272    privateUnlock();
   273 
   274    return tmp;
   275 #endif
   276 }
   277 
   278 Uint8
   279 SDL_AtomicIncrementThenFetch8(Uint8 * ptr)
   280 {
   281 #ifdef nativeIncrementThenFetch8
   282    return nativeIncrementThenFetch8(ptr);
   283 #else
   284    Uint8 tmp = 0;;
   285 
   286    privateWaitLock();
   287    (*ptr)+= 1;
   288    tmp = *ptr;
   289    privateUnlock();
   290 
   291    return tmp;
   292 #endif
   293 }
   294 
   295 Uint8
   296 SDL_AtomicDecrementThenFetch8(Uint8 * ptr)
   297 {
   298 #ifdef nativeDecrementThenFetch8
   299    return nativeDecrementThenFetch8(ptr);
   300 #else
   301    Uint8 tmp = 0;;
   302 
   303    privateWaitLock();
   304    (*ptr)-= 1;
   305    tmp = *ptr;
   306    privateUnlock();
   307 
   308    return tmp;
   309 #endif
   310 }
   311 
   312 Uint8
   313 SDL_AtomicAddThenFetch8(Uint8 * ptr, Uint8 value)
   314 {
   315 #ifdef nativeAddThenFetch8
   316    return nativeAddThenFetch8(ptr, value);
   317 #else
   318    Uint8 tmp = 0;;
   319 
   320    privateWaitLock();
   321    (*ptr)+= value;
   322    tmp = *ptr;
   323    privateUnlock();
   324 
   325    return tmp;
   326 #endif
   327 }
   328 
   329 Uint8
   330 SDL_AtomicSubtractThenFetch8(Uint8 * ptr, Uint8 value)
   331 {
   332 #ifdef nativeSubtractThenFetch8
   333    return nativeSubtractThenFetch8(ptr, value);
   334 #else
   335    Uint8 tmp = 0;;
   336 
   337    privateWaitLock();
   338    (*ptr)-= value;
   339    tmp = *ptr;
   340    privateUnlock();
   341 
   342    return tmp;
   343 #endif
   344 }
   345 
   346 /* 16 bit atomic operations */
   347 
   348 Uint16
   349 SDL_AtomicExchange16(Uint16 * ptr, Uint16 value)
   350 {
   351 #ifdef nativeExchange16
   352    return nativeExchange16(ptr, value);
   353 #else
   354    Uint16 tmp = 0;;
   355 
   356    privateWaitLock();
   357    tmp = *ptr;
   358    *ptr = value;
   359    privateUnlock();
   360 
   361    return tmp;
   362 #endif
   363 }
   364 
   365 SDL_bool
   366 SDL_AtomicCompareThenSet16(Uint16 * ptr, Uint16 oldvalue, Uint16 newvalue)
   367 {
   368 #ifdef nativeCompareThenSet16
   369    return (SDL_bool)nativeCompareThenSet16(ptr, oldvalue, newvalue);
   370 #else
   371    SDL_bool result = SDL_FALSE;
   372 
   373    privateWaitLock();
   374    result = (*ptr == oldvalue);
   375    if (result)
   376    {
   377       *ptr = newvalue;
   378    }
   379    privateUnlock();
   380 
   381    return result;
   382 #endif
   383 }
   384 
   385 SDL_bool
   386 SDL_AtomicTestThenSet16(Uint16 * ptr)
   387 {
   388 #ifdef nativeTestThenSet16
   389    return (SDL_bool)nativeTestThenSet16(ptr);
   390 #else
   391    SDL_bool result = SDL_FALSE;
   392 
   393    privateWaitLock();
   394    result = (*ptr == 0);
   395    if (result)
   396    {
   397       *ptr = 1;
   398    }
   399    privateUnlock();
   400 
   401    return result;
   402 #endif
   403 }
   404 
   405 void
   406 SDL_AtomicClear16(Uint16 * ptr)
   407 {
   408 #ifdef nativeClear16
   409    nativeClear16(ptr);
   410 #else
   411    privateWaitLock();
   412    *ptr = 0;
   413    privateUnlock();
   414 
   415    return;
   416 #endif
   417 }
   418 
   419 Uint16
   420 SDL_AtomicFetchThenIncrement16(Uint16 * ptr)
   421 {
   422 #ifdef nativeFetchThenIncrement16
   423    return nativeFetchThenIncrement16(ptr);
   424 #else
   425    Uint16 tmp = 0;;
   426 
   427    privateWaitLock();
   428    tmp = *ptr;
   429    (*ptr)+= 1;
   430    privateUnlock();
   431 
   432    return tmp;
   433 #endif
   434 }
   435 
   436 Uint16
   437 SDL_AtomicFetchThenDecrement16(Uint16 * ptr)
   438 {
   439 #ifdef nativeFetchThenDecrement16
   440    return nativeFetchThenDecrement16(ptr);
   441 #else
   442    Uint16 tmp = 0;;
   443 
   444    privateWaitLock();
   445    tmp = *ptr;
   446    (*ptr) -= 1;
   447    privateUnlock();
   448 
   449    return tmp;
   450 #endif
   451 }
   452 
   453 Uint16
   454 SDL_AtomicFetchThenAdd16(Uint16 * ptr, Uint16 value)
   455 {
   456 #ifdef nativeFetchThenAdd16
   457    return nativeFetchThenAdd16(ptr, value);
   458 #else
   459    Uint16 tmp = 0;;
   460 
   461    privateWaitLock();
   462    tmp = *ptr;
   463    (*ptr)+= value;
   464    privateUnlock();
   465 
   466    return tmp;
   467 #endif
   468 }
   469 
   470 Uint16
   471 SDL_AtomicFetchThenSubtract16(Uint16 * ptr, Uint16 value)
   472 {
   473 #ifdef nativeFetchThenSubtract16
   474    return nativeFetchThenSubtract16(ptr, value);
   475 #else
   476    Uint16 tmp = 0;;
   477 
   478    privateWaitLock();
   479    tmp = *ptr;
   480    (*ptr)-= value;
   481    privateUnlock();
   482 
   483    return tmp;
   484 #endif
   485 }
   486 
   487 Uint16
   488 SDL_AtomicIncrementThenFetch16(Uint16 * ptr)
   489 {
   490 #ifdef nativeIncrementThenFetch16
   491    return nativeIncrementThenFetch16(ptr);
   492 #else
   493    Uint16 tmp = 0;;
   494 
   495    privateWaitLock();
   496    (*ptr)+= 1;
   497    tmp = *ptr;
   498    privateUnlock();
   499 
   500    return tmp;
   501 #endif
   502 }
   503 
   504 Uint16
   505 SDL_AtomicDecrementThenFetch16(Uint16 * ptr)
   506 {
   507 #ifdef nativeDecrementThenFetch16
   508    return nativeDecrementThenFetch16(ptr);
   509 #else
   510    Uint16 tmp = 0;;
   511 
   512    privateWaitLock();
   513    (*ptr)-= 1;
   514    tmp = *ptr;
   515    privateUnlock();
   516 
   517    return tmp;
   518 #endif
   519 }
   520 
   521 Uint16
   522 SDL_AtomicAddThenFetch16(Uint16 * ptr, Uint16 value)
   523 {
   524 #ifdef nativeAddThenFetch16
   525    return nativeAddThenFetch16(ptr, value);
   526 #else
   527    Uint16 tmp = 0;;
   528 
   529    privateWaitLock();
   530    (*ptr)+= value;
   531    tmp = *ptr;
   532    privateUnlock();
   533 
   534    return tmp;
   535 #endif
   536 }
   537 
   538 Uint16
   539 SDL_AtomicSubtractThenFetch16(Uint16 * ptr, Uint16 value)
   540 {
   541 #ifdef nativeSubtractThenFetch16
   542    return nativeSubtractThenFetch16(ptr, value);
   543 #else
   544    Uint16 tmp = 0;;
   545 
   546    privateWaitLock();
   547    (*ptr)-= value;
   548    tmp = *ptr;
   549    privateUnlock();
   550 
   551    return tmp;
   552 #endif
   553 }
   554 
   555 /* 32 bit atomic operations */
   556 
   557 Uint32
   558 SDL_AtomicExchange32(Uint32 * ptr, Uint32 value)
   559 {
   560 #ifdef nativeExchange32
   561    return nativeExchange32(ptr, value);
   562 #else
   563    Uint32 tmp = 0;;
   564 
   565    privateWaitLock();
   566    tmp = *ptr;
   567    *ptr = value;
   568    privateUnlock();
   569 
   570    return tmp;
   571 #endif
   572 }
   573 
   574 SDL_bool
   575 SDL_AtomicCompareThenSet32(Uint32 * ptr, Uint32 oldvalue, Uint32 newvalue)
   576 {
   577 #ifdef nativeCompareThenSet32
   578    return (SDL_bool)nativeCompareThenSet32(ptr, oldvalue, newvalue);
   579 #else
   580    SDL_bool result = SDL_FALSE;
   581 
   582    privateWaitLock();
   583    result = (*ptr == oldvalue);
   584    if (result)
   585    {
   586       *ptr = newvalue;
   587    }
   588    privateUnlock();
   589 
   590    return result;
   591 #endif
   592 }
   593 
   594 SDL_bool
   595 SDL_AtomicTestThenSet32(Uint32 * ptr)
   596 {
   597 #ifdef nativeTestThenSet32
   598    return (SDL_bool)nativeTestThenSet32(ptr);
   599 #else
   600    SDL_bool result = SDL_FALSE;
   601 
   602    privateWaitLock();
   603    result = (*ptr == 0);
   604    if (result)
   605    {
   606       *ptr = 1;
   607    }
   608    privateUnlock();
   609 
   610    return result;
   611 #endif
   612 }
   613 
   614 void
   615 SDL_AtomicClear32(Uint32 * ptr)
   616 {
   617 #ifdef nativeClear32
   618    nativeClear32(ptr);
   619 #else
   620    privateWaitLock();
   621    *ptr = 0;
   622    privateUnlock();
   623 
   624    return;
   625 #endif
   626 }
   627 
   628 Uint32
   629 SDL_AtomicFetchThenIncrement32(Uint32 * ptr)
   630 {
   631 #ifdef nativeFetchThenIncrement32
   632    return nativeFetchThenIncrement32(ptr);
   633 #else
   634    Uint32 tmp = 0;;
   635 
   636    privateWaitLock();
   637    tmp = *ptr;
   638    (*ptr)+= 1;
   639    privateUnlock();
   640 
   641    return tmp;
   642 #endif
   643 }
   644 
   645 Uint32
   646 SDL_AtomicFetchThenDecrement32(Uint32 * ptr)
   647 {
   648 #ifdef nativeFetchThenDecrement32
   649    return nativeFetchThenDecrement32(ptr);
   650 #else
   651    Uint32 tmp = 0;;
   652 
   653    privateWaitLock();
   654    tmp = *ptr;
   655    (*ptr) -= 1;
   656    privateUnlock();
   657 
   658    return tmp;
   659 #endif
   660 }
   661 
   662 Uint32
   663 SDL_AtomicFetchThenAdd32(Uint32 * ptr, Uint32 value)
   664 {
   665 #ifdef nativeFetchThenAdd32
   666    return nativeFetchThenAdd32(ptr, value);
   667 #else
   668    Uint32 tmp = 0;;
   669 
   670    privateWaitLock();
   671    tmp = *ptr;
   672    (*ptr)+= value;
   673    privateUnlock();
   674 
   675    return tmp;
   676 #endif
   677 }
   678 
   679 Uint32
   680 SDL_AtomicFetchThenSubtract32(Uint32 * ptr, Uint32 value)
   681 {
   682 #ifdef nativeFetchThenSubtract32
   683    return nativeFetchThenSubtract32(ptr, value);
   684 #else
   685    Uint32 tmp = 0;;
   686 
   687    privateWaitLock();
   688    tmp = *ptr;
   689    (*ptr)-= value;
   690    privateUnlock();
   691 
   692    return tmp;
   693 #endif
   694 }
   695 
   696 Uint32
   697 SDL_AtomicIncrementThenFetch32(Uint32 * ptr)
   698 {
   699 #ifdef nativeIncrementThenFetch32
   700    return nativeIncrementThenFetch32(ptr);
   701 #else
   702    Uint32 tmp = 0;;
   703 
   704    privateWaitLock();
   705    (*ptr)+= 1;
   706    tmp = *ptr;
   707    privateUnlock();
   708 
   709    return tmp;
   710 #endif
   711 }
   712 
   713 Uint32
   714 SDL_AtomicDecrementThenFetch32(Uint32 * ptr)
   715 {
   716 #ifdef nativeDecrementThenFetch32
   717    return nativeDecrementThenFetch32(ptr);
   718 #else
   719    Uint32 tmp = 0;;
   720 
   721    privateWaitLock();
   722    (*ptr)-= 1;
   723    tmp = *ptr;
   724    privateUnlock();
   725 
   726    return tmp;
   727 #endif
   728 }
   729 
   730 Uint32
   731 SDL_AtomicAddThenFetch32(Uint32 * ptr, Uint32 value)
   732 {
   733 #ifdef nativeAddThenFetch32
   734    return nativeAddThenFetch32(ptr, value);
   735 #else
   736    Uint32 tmp = 0;;
   737 
   738    privateWaitLock();
   739    (*ptr)+= value;
   740    tmp = *ptr;
   741    privateUnlock();
   742 
   743    return tmp;
   744 #endif
   745 }
   746 
   747 Uint32
   748 SDL_AtomicSubtractThenFetch32(Uint32 * ptr, Uint32 value)
   749 {
   750 #ifdef nativeSubtractThenFetch32
   751    return nativeSubtractThenFetch32(ptr, value);
   752 #else
   753    Uint32 tmp = 0;;
   754 
   755    privateWaitLock();
   756    (*ptr)-= value;
   757    tmp = *ptr;
   758    privateUnlock();
   759 
   760    return tmp;
   761 #endif
   762 }
   763 
   764 /* 64 bit atomic operations */
   765 #ifdef SDL_HAS_64BIT_TYPE
   766 
   767 Uint64
   768 SDL_AtomicExchange64(Uint64 * ptr, Uint64 value)
   769 {
   770 #ifdef nativeExchange64
   771    return nativeExchange64(ptr, value);
   772 #else
   773    Uint64 tmp = 0;;
   774 
   775    privateWaitLock();
   776    tmp = *ptr;
   777    *ptr = value;
   778    privateUnlock();
   779 
   780    return tmp;
   781 #endif
   782 }
   783 
   784 SDL_bool
   785 SDL_AtomicCompareThenSet64(Uint64 * ptr, Uint64 oldvalue, Uint64 newvalue)
   786 {
   787 #ifdef nativeCompareThenSet64
   788    return (SDL_bool)nativeCompareThenSet64(ptr, oldvalue, newvalue);
   789 #else
   790    SDL_bool result = SDL_FALSE;
   791 
   792    privateWaitLock();
   793    result = (*ptr == oldvalue);
   794    if (result)
   795    {
   796       *ptr = newvalue;
   797    }
   798    privateUnlock();
   799 
   800    return result;
   801 #endif
   802 }
   803 
   804 SDL_bool
   805 SDL_AtomicTestThenSet64(Uint64 * ptr)
   806 {
   807 #ifdef nativeTestThenSet64
   808    return (SDL_bool)nativeTestThenSet64(ptr);
   809 #else
   810    SDL_bool result = SDL_FALSE;
   811 
   812    privateWaitLock();
   813    result = (*ptr == 0);
   814    if (result)
   815    {
   816       *ptr = 1;
   817    }
   818    privateUnlock();
   819 
   820    return result;
   821 #endif
   822 }
   823 
   824 void
   825 SDL_AtomicClear64(Uint64 * ptr)
   826 {
   827 #ifdef nativeClear64
   828    nativeClear64(ptr);
   829 #else
   830    privateWaitLock();
   831    *ptr = 0;
   832    privateUnlock();
   833 
   834    return;
   835 #endif
   836 }
   837 
   838 Uint64
   839 SDL_AtomicFetchThenIncrement64(Uint64 * ptr)
   840 {
   841 #ifdef nativeFetchThenIncrement64
   842    return nativeFetchThenIncrement64(ptr);
   843 #else
   844    Uint64 tmp = 0;;
   845 
   846    privateWaitLock();
   847    tmp = *ptr;
   848    (*ptr)+= 1;
   849    privateUnlock();
   850 
   851    return tmp;
   852 #endif
   853 }
   854 
   855 Uint64
   856 SDL_AtomicFetchThenDecrement64(Uint64 * ptr)
   857 {
   858 #ifdef nativeFetchThenDecrement64
   859    return nativeFetchThenDecrement64(ptr);
   860 #else
   861    Uint64 tmp = 0;;
   862 
   863    privateWaitLock();
   864    tmp = *ptr;
   865    (*ptr) -= 1;
   866    privateUnlock();
   867 
   868    return tmp;
   869 #endif
   870 }
   871 
   872 Uint64
   873 SDL_AtomicFetchThenAdd64(Uint64 * ptr, Uint64 value)
   874 {
   875 #ifdef nativeFetchThenAdd64
   876    return nativeFetchThenAdd64(ptr, value);
   877 #else
   878    Uint64 tmp = 0;;
   879 
   880    privateWaitLock();
   881    tmp = *ptr;
   882    (*ptr)+= value;
   883    privateUnlock();
   884 
   885    return tmp;
   886 #endif
   887 }
   888 
   889 Uint64
   890 SDL_AtomicFetchThenSubtract64(Uint64 * ptr, Uint64 value)
   891 {
   892 #ifdef nativeFetchThenSubtract64
   893    return nativeFetchThenSubtract64(ptr, value);
   894 #else
   895    Uint64 tmp = 0;;
   896 
   897    privateWaitLock();
   898    tmp = *ptr;
   899    (*ptr)-= value;
   900    privateUnlock();
   901 
   902    return tmp;
   903 #endif
   904 }
   905 
   906 Uint64
   907 SDL_AtomicIncrementThenFetch64(Uint64 * ptr)
   908 {
   909 #ifdef nativeIncrementThenFetch64
   910    return nativeIncrementThenFetch64(ptr);
   911 #else
   912    Uint64 tmp = 0;;
   913 
   914    privateWaitLock();
   915    (*ptr)+= 1;
   916    tmp = *ptr;
   917    privateUnlock();
   918 
   919    return tmp;
   920 #endif
   921 }
   922 
   923 Uint64
   924 SDL_AtomicDecrementThenFetch64(Uint64 * ptr)
   925 {
   926 #ifdef nativeDecrementThenFetch64
   927    return nativeDecrementThenFetch64(ptr);
   928 #else
   929    Uint64 tmp = 0;;
   930 
   931    privateWaitLock();
   932    (*ptr)-= 1;
   933    tmp = *ptr;
   934    privateUnlock();
   935 
   936    return tmp;
   937 #endif
   938 }
   939 
   940 Uint64
   941 SDL_AtomicAddThenFetch64(Uint64 * ptr, Uint64 value)
   942 {
   943 #ifdef nativeAddThenFetch64
   944    return nativeAddThenFetch64(ptr, value);
   945 #else
   946    Uint64 tmp = 0;;
   947 
   948    privateWaitLock();
   949    (*ptr)+= value;
   950    tmp = *ptr;
   951    privateUnlock();
   952 
   953    return tmp;
   954 #endif
   955 }
   956 
   957 Uint64
   958 SDL_AtomicSubtractThenFetch64(Uint64 * ptr, Uint64 value)
   959 {
   960 #ifdef nativeSubtractThenFetch64
   961    return nativeSubtractThenFetch64(ptr, value);
   962 #else
   963    Uint64 tmp = 0;;
   964 
   965    privateWaitLock();
   966    (*ptr)-= value;
   967    tmp = *ptr;
   968    privateUnlock();
   969 
   970    return tmp;
   971 #endif
   972 }
   973 #endif
   974