test/testatomic.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 17 Jan 2011 13:54:13 -0800
changeset 5013 9d6b527e0912
parent 5006 8e8876e4aec6
child 5018 342b158efbbe
permissions -rw-r--r--
Fixed compiler errors
     1 #include <stdio.h>
     2 
     3 #include "SDL.h"
     4 #include "SDL_atomic.h"
     5 #include "SDL_assert.h"
     6 
     7 /*
     8   Absolutely basic tests just to see if we get the expected value
     9   after calling each function.
    10 */
    11 
    12 static
    13 char *
    14 tf(SDL_bool tf)
    15 {
    16     static char *t = "TRUE";
    17     static char *f = "FALSE";
    18 
    19     if (tf)
    20     {
    21        return t;
    22     }
    23 
    24     return f;
    25 }
    26 
    27 static
    28 void RunBasicTest()
    29 {
    30     int value;
    31     SDL_SpinLock lock = 0;
    32 
    33     SDL_atomic_t v;
    34     SDL_bool tfret = SDL_FALSE;
    35 
    36     printf("\nspin lock---------------------------------------\n\n");
    37 
    38     SDL_AtomicLock(&lock);
    39     printf("AtomicLock                   lock=%d\n", lock);
    40     SDL_AtomicUnlock(&lock);
    41     printf("AtomicUnlock                 lock=%d\n", lock);
    42 
    43     printf("\natomic -----------------------------------------\n\n");
    44      
    45     SDL_AtomicSet(&v, 0);
    46     tfret = SDL_AtomicSet(&v, 10) == 0;
    47     printf("AtomicSet(10)        tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    48     tfret = SDL_AtomicAdd(&v, 10) == 10;
    49     printf("AtomicAdd(10)        tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    50 
    51     SDL_AtomicSet(&v, 0);
    52     SDL_AtomicIncRef(&v);
    53     tfret = (SDL_AtomicGet(&v) == 1);
    54     printf("AtomicIncRef()       tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    55     SDL_AtomicIncRef(&v);
    56     tfret = (SDL_AtomicGet(&v) == 2);
    57     printf("AtomicIncRef()       tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    58     tfret = (SDL_AtomicDecRef(&v) == SDL_FALSE);
    59     printf("AtomicDecRef()       tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    60     tfret = (SDL_AtomicDecRef(&v) == SDL_TRUE);
    61     printf("AtomicDecRef()       tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    62 
    63     SDL_AtomicSet(&v, 10);
    64     tfret = (SDL_AtomicCAS(&v, 0, 20) == SDL_FALSE);
    65     printf("AtomicCAS()          tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    66     value = SDL_AtomicGet(&v);
    67     tfret = (SDL_AtomicCAS(&v, value, 20) == SDL_TRUE);
    68     printf("AtomicCAS()          tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
    69 }
    70 
    71 /* Atomic operation test, adapted from code by Michael Davidsaver at:
    72     http://bazaar.launchpad.net/~mdavidsaver/epics-base/atomic/revision/12105#src/libCom/test/epicsAtomicTest.c
    73 */
    74 
    75 /* Tests semantics of atomic operations.  Also a stress test
    76  * to see if they are really atomic.
    77  *
    78  * Serveral threads adding to the same variable.
    79  * at the end the value is compared with the expected
    80  * and with a non-atomic counter.
    81  */
    82  
    83 /* Number of concurrent incrementers */
    84 #define NThreads 2
    85 #define CountInc 100
    86 #define VALBITS (sizeof(atomicValue)*8)
    87  
    88 #define atomicValue int
    89 #define CountTo ((atomicValue)((unsigned int)(1<<(VALBITS-1))-1))
    90 #define NInter (CountTo/CountInc/NThreads)
    91 #define Expect (CountTo-NInter*CountInc*NThreads)
    92  
    93 SDL_COMPILE_TIME_ASSERT(size, CountTo>0); /* check for rollover */
    94  
    95 static SDL_atomic_t good = { 42 };
    96  
    97 static atomicValue bad = 42;
    98  
    99 static SDL_atomic_t threadsRunning;
   100 
   101 static SDL_sem *threadDone;
   102  
   103 static
   104 int adder(void* junk)
   105 {
   106     unsigned long N=NInter;
   107     printf("Thread subtracting %d %lu times\n",CountInc,N);
   108     while (N--) {
   109         SDL_AtomicAdd(&good, -CountInc);
   110         bad-=CountInc;
   111     }
   112     SDL_AtomicAdd(&threadsRunning, -1);
   113     SDL_SemPost(threadDone);
   114     return 0;
   115 }
   116  
   117 static
   118 void runAdder(void)
   119 {
   120     Uint32 start, end;
   121     int T=NThreads;
   122  
   123     start = SDL_GetTicks();
   124  
   125     threadDone = SDL_CreateSemaphore(0);
   126 
   127     SDL_AtomicSet(&threadsRunning, NThreads);
   128 
   129     while (T--)
   130         SDL_CreateThread(adder, NULL);
   131  
   132     while (SDL_AtomicGet(&threadsRunning) > 0)
   133         SDL_SemWait(threadDone);
   134  
   135     SDL_DestroySemaphore(threadDone);
   136 
   137     end = SDL_GetTicks();
   138  
   139     printf("Finished in %f sec\n", (end - start) / 1000.f);
   140 }
   141  
   142 static
   143 void RunEpicTest()
   144 {
   145     int b;
   146     atomicValue v;
   147  
   148     printf("\nepic test---------------------------------------\n\n");
   149 
   150     printf("Size asserted to be >= 32-bit\n");
   151     SDL_assert(sizeof(atomicValue)>=4);
   152  
   153     printf("Check static initializer\n");
   154     v=SDL_AtomicGet(&good);
   155     SDL_assert(v==42);
   156  
   157     SDL_assert(bad==42);
   158  
   159     printf("Test negative values\n");
   160     SDL_AtomicSet(&good, -5);
   161     v=SDL_AtomicGet(&good);
   162     SDL_assert(v==-5);
   163  
   164     printf("Verify maximum value\n");
   165     SDL_AtomicSet(&good, CountTo);
   166     v=SDL_AtomicGet(&good);
   167     SDL_assert(v==CountTo);
   168  
   169     printf("Test compare and exchange\n");
   170  
   171     b=SDL_AtomicCAS(&good, 500, 43);
   172     SDL_assert(!b); /* no swap since CountTo!=500 */
   173     v=SDL_AtomicGet(&good);
   174     SDL_assert(v==CountTo); /* ensure no swap */
   175  
   176     b=SDL_AtomicCAS(&good, CountTo, 44);
   177     SDL_assert(!!b); /* will swap */
   178     v=SDL_AtomicGet(&good);
   179     SDL_assert(v==44);
   180  
   181     printf("Test Add\n");
   182  
   183     v=SDL_AtomicAdd(&good, 1);
   184     SDL_assert(v==44);
   185     v=SDL_AtomicGet(&good);
   186     SDL_assert(v==45);
   187  
   188     v=SDL_AtomicAdd(&good, 10);
   189     SDL_assert(v==45);
   190     v=SDL_AtomicGet(&good);
   191     SDL_assert(v==55);
   192  
   193     printf("Test Add (Negative values)\n");
   194  
   195     v=SDL_AtomicAdd(&good, -20);
   196     SDL_assert(v==55);
   197     v=SDL_AtomicGet(&good);
   198     SDL_assert(v==35);
   199  
   200     v=SDL_AtomicAdd(&good, -50); /* crossing zero down */
   201     SDL_assert(v==35);
   202     v=SDL_AtomicGet(&good);
   203     SDL_assert(v==-15);
   204  
   205     v=SDL_AtomicAdd(&good, 30); /* crossing zero up */
   206     SDL_assert(v==-15);
   207     v=SDL_AtomicGet(&good);
   208     SDL_assert(v==15);
   209  
   210     printf("Reset before count down test\n");
   211     SDL_AtomicSet(&good, CountTo);
   212     v=SDL_AtomicGet(&good);
   213     SDL_assert(v==CountTo);
   214  
   215     bad=CountTo;
   216     SDL_assert(bad==CountTo);
   217  
   218     printf("Counting down from %d, Expect %d remaining\n",CountTo,Expect);
   219     runAdder();
   220  
   221     v=SDL_AtomicGet(&good);
   222     printf("Atomic %d Non-Atomic %d\n",v,bad);
   223     SDL_assert(v==Expect);
   224     SDL_assert(bad!=Expect);
   225 }
   226 
   227 int
   228 main(int argc, char *argv[])
   229 {
   230     RunBasicTest();
   231     RunEpicTest();
   232     return 0;
   233 }