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