testatomic.c File Reference
`#include <stdio.h>`
`#include "SDL.h"`
Include dependency graph for testatomic.c:

Go to the source code of this file.

## Data Structures

struct | SDL_EventQueueEntry
struct | SDL_EventQueue
struct | WriterData
struct | ReaderData

## Macros

#define | NThreads 2
#define | CountInc 100
#define | VALBITS (sizeof(atomicValue)*8)
#define | atomicValue int
#define | CountTo ((atomicValue)((unsigned int)(1<<(VALBITS-1))-1))
#define | NInter (CountTo/CountInc/NThreads)
#define | Expect (CountTo-NInter*CountInc*NThreads)
#define | TEST_SPINLOCK_FIFO
#define | NUM_READERS 4
#define | NUM_WRITERS 4
#define | EVENTS_PER_WRITER 1000000
#define | MAX_ENTRIES 256
#define | WRAP_MASK (MAX_ENTRIES-1)

## Enumerations

enum |

## Functions

static char * | tf (SDL_bool tf)
static void | RunBasicTest ()
| SDL_COMPILE_TIME_ASSERT (size, CountTo_GreaterThanZero)
static int | adder (void *junk)
static void | runAdder (void)
static void | RunEpicTest ()
static void | InitEventQueue (SDL_EventQueue *queue)
static SDL_bool | EnqueueEvent_LockFree (SDL_EventQueue *queue, const SDL_Event *event)
static SDL_bool | DequeueEvent_LockFree (SDL_EventQueue *queue, SDL_Event *event)
static SDL_bool | EnqueueEvent_Mutex (SDL_EventQueue *queue, const SDL_Event *event)
static SDL_bool | DequeueEvent_Mutex (SDL_EventQueue *queue, SDL_Event *event)
static int | FIFO_Writer (void *_data)
static int | FIFO_Reader (void *_data)
static int | FIFO_Watcher (void *_data)
static void | RunFIFOTest (SDL_bool lock_free)
int | main (int argc, char *argv[])

## Variables

static SDL_atomic_t | good = { 42 }
static atomicValue | bad = 42
static SDL_atomic_t | threadsRunning
static SDL_sem * | threadDone
static SDL_sem * | writersDone
static SDL_sem * | readersDone
static SDL_atomic_t | writersRunning
static SDL_atomic_t | readersRunning

## Macro Definition Documentation

## atomicValue

#define atomicValue int

Definition at line 101 of file testatomic.c.

## CountInc

#define CountInc 100

Definition at line 98 of file testatomic.c.

## CountTo

#define CountTo ((atomicValue)((unsigned int)(1<<(VALBITS-1))-1))

Definition at line 102 of file testatomic.c.

## EVENTS_PER_WRITER

#define EVENTS_PER_WRITER 1000000

Definition at line 256 of file testatomic.c.

## Expect

#define Expect (CountTo-NInter*CountInc*NThreads)

Definition at line 104 of file testatomic.c.

## MAX_ENTRIES

#define MAX_ENTRIES 256

Definition at line 259 of file testatomic.c.

## NInter

#define NInter (CountTo/CountInc/NThreads)

Definition at line 103 of file testatomic.c.

## NThreads

#define NThreads 2

Definition at line 97 of file testatomic.c.

## NUM_READERS

#define NUM_READERS 4

Definition at line 254 of file testatomic.c.

## NUM_WRITERS

#define NUM_WRITERS 4

Definition at line 255 of file testatomic.c.

## TEST_SPINLOCK_FIFO

#define TEST_SPINLOCK_FIFO

Definition at line 252 of file testatomic.c.

## VALBITS

#define VALBITS (sizeof(atomicValue)*8)

Definition at line 99 of file testatomic.c.

## WRAP_MASK

#define WRAP_MASK (MAX_ENTRIES-1)

Definition at line 260 of file testatomic.c.

## Enumeration Type Documentation

## anonymous enum

anonymous enum

Definition at line 106 of file testatomic.c.

{
CountTo_GreaterThanZero = CountTo > 0,
};

## Function Documentation

## adder()

static int adder | ( | void * | junk | ) |

static

Definition at line 120 of file testatomic.c.

{
unsigned long N=NInter;
SDL_Log("Thread subtracting %d %lu times\n",CountInc,N);
while (N--) {
SDL_AtomicAdd(&good, -CountInc);
bad-=CountInc;
}
SDL_AtomicAdd(&threadsRunning, -1);
SDL_SemPost(threadDone);
return 0;
}

References bad, CountInc, good, NInter, SDL_AtomicAdd, SDL_Log, SDL_SemPost, threadDone, and threadsRunning.

Referenced by runAdder().

## DequeueEvent_LockFree()

static SDL_bool DequeueEvent_LockFree | ( | SDL_EventQueue * | queue,
|  | SDL_Event * | event
| ) |  |

static

Definition at line 361 of file testatomic.c.

{
SDL_EventQueueEntry *entry;
unsigned queue_pos;
unsigned entry_seq;
int delta;
SDL_bool status;
#ifdef TEST_SPINLOCK_FIFO
/* This is a gate so an external thread can lock the queue */
SDL_AtomicLock(&queue->lock);
SDL_assert(SDL_AtomicGet(&queue->watcher) == 0);
SDL_AtomicIncRef(&queue->rwcount);
SDL_AtomicUnlock(&queue->lock);
#endif
queue_pos = (unsigned)SDL_AtomicGet(&queue->dequeue_pos);
for ( ; ; ) {
entry = &queue->entries[queue_pos & WRAP_MASK];
entry_seq = (unsigned)SDL_AtomicGet(&entry->sequence);
delta = (int)(entry_seq - (queue_pos + 1));
if (delta == 0) {
/* The entry and the queue position match, try to increment the queue position */
if (SDL_AtomicCAS(&queue->dequeue_pos, (int)queue_pos, (int)(queue_pos+1))) {
/* We own the object, fill it! */
*event = entry->event;
SDL_AtomicSet(&entry->sequence, (int)(queue_pos+MAX_ENTRIES));
status = SDL_TRUE;
break;
}
} else if (delta < 0) {
/* We ran into an old queue entry, which means we've hit empty */
status = SDL_FALSE;
break;
} else {
/* We ran into a new queue entry, get the new queue position */
queue_pos = (unsigned)SDL_AtomicGet(&queue->dequeue_pos);
}
}
#ifdef TEST_SPINLOCK_FIFO
SDL_AtomicDecRef(&queue->rwcount);
#endif
return status;
}

References SDL_EventQueue::dequeue_pos, SDL_EventQueue::entries, SDL_EventQueueEntry::event, SDL_EventQueue::lock, MAX_ENTRIES, SDL_EventQueue::rwcount, SDL_assert, SDL_AtomicCAS, SDL_AtomicDecRef, SDL_AtomicGet, SDL_AtomicIncRef, SDL_AtomicLock, SDL_AtomicSet, SDL_AtomicUnlock, SDL_FALSE, SDL_TRUE, SDL_EventQueueEntry::sequence, SDL_EventQueue::watcher, and WRAP_MASK.

Referenced by FIFO_Reader().

## DequeueEvent_Mutex()

static SDL_bool DequeueEvent_Mutex | ( | SDL_EventQueue * | queue,
|  | SDL_Event * | event
| ) |  |

static

Definition at line 441 of file testatomic.c.

{
SDL_EventQueueEntry *entry;
unsigned queue_pos;
unsigned entry_seq;
int delta;
SDL_bool status = SDL_FALSE;
SDL_LockMutex(queue->mutex);
queue_pos = (unsigned)queue->dequeue_pos.value;
entry = &queue->entries[queue_pos & WRAP_MASK];
entry_seq = (unsigned)entry->sequence.value;
delta = (int)(entry_seq - (queue_pos + 1));
if (delta == 0) {
++queue->dequeue_pos.value;
/* We own the object, fill it! */
*event = entry->event;
entry->sequence.value = (int)(queue_pos + MAX_ENTRIES);
status = SDL_TRUE;
} else if (delta < 0) {
/* We ran into an old queue entry, which means we've hit empty */
} else {
SDL_Log("ERROR: mutex failed!\n");
}
SDL_UnlockMutex(queue->mutex);
return status;
}

References SDL_EventQueue::dequeue_pos, SDL_EventQueue::entries, SDL_EventQueueEntry::event, MAX_ENTRIES, SDL_EventQueue::mutex, SDL_FALSE, SDL_LockMutex, SDL_Log, SDL_TRUE, SDL_UnlockMutex, SDL_EventQueueEntry::sequence, SDL_atomic_t::value, and WRAP_MASK.

Referenced by FIFO_Reader().

## EnqueueEvent_LockFree()

static SDL_bool EnqueueEvent_LockFree | ( | SDL_EventQueue * | queue,
|  | const SDL_Event * | event
| ) |  |

static

Definition at line 314 of file testatomic.c.

{
SDL_EventQueueEntry *entry;
unsigned queue_pos;
unsigned entry_seq;
int delta;
SDL_bool status;
#ifdef TEST_SPINLOCK_FIFO
/* This is a gate so an external thread can lock the queue */
SDL_AtomicLock(&queue->lock);
SDL_assert(SDL_AtomicGet(&queue->watcher) == 0);
SDL_AtomicIncRef(&queue->rwcount);
SDL_AtomicUnlock(&queue->lock);
#endif
queue_pos = (unsigned)SDL_AtomicGet(&queue->enqueue_pos);
for ( ; ; ) {
entry = &queue->entries[queue_pos & WRAP_MASK];
entry_seq = (unsigned)SDL_AtomicGet(&entry->sequence);
delta = (int)(entry_seq - queue_pos);
if (delta == 0) {
/* The entry and the queue position match, try to increment the queue position */
if (SDL_AtomicCAS(&queue->enqueue_pos, (int)queue_pos, (int)(queue_pos+1))) {
/* We own the object, fill it! */
entry->event = *event;
SDL_AtomicSet(&entry->sequence, (int)(queue_pos + 1));
status = SDL_TRUE;
break;
}
} else if (delta < 0) {
/* We ran into an old queue entry, which means it still needs to be dequeued */
status = SDL_FALSE;
break;
} else {
/* We ran into a new queue entry, get the new queue position */
queue_pos = (unsigned)SDL_AtomicGet(&queue->enqueue_pos);
}
}
#ifdef TEST_SPINLOCK_FIFO
SDL_AtomicDecRef(&queue->rwcount);
#endif
return status;
}

References SDL_EventQueue::enqueue_pos, SDL_EventQueue::entries, SDL_EventQueueEntry::event, SDL_EventQueue::lock, SDL_EventQueue::rwcount, SDL_assert, SDL_AtomicCAS, SDL_AtomicDecRef, SDL_AtomicGet, SDL_AtomicIncRef, SDL_AtomicLock, SDL_AtomicSet, SDL_AtomicUnlock, SDL_FALSE, SDL_TRUE, SDL_EventQueueEntry::sequence, SDL_EventQueue::watcher, and WRAP_MASK.

Referenced by FIFO_Writer().

## EnqueueEvent_Mutex()

static SDL_bool EnqueueEvent_Mutex | ( | SDL_EventQueue * | queue,
|  | const SDL_Event * | event
| ) |  |

static

Definition at line 408 of file testatomic.c.

{
SDL_EventQueueEntry *entry;
unsigned queue_pos;
unsigned entry_seq;
int delta;
SDL_bool status = SDL_FALSE;
SDL_LockMutex(queue->mutex);
queue_pos = (unsigned)queue->enqueue_pos.value;
entry = &queue->entries[queue_pos & WRAP_MASK];
entry_seq = (unsigned)entry->sequence.value;
delta = (int)(entry_seq - queue_pos);
if (delta == 0) {
++queue->enqueue_pos.value;
/* We own the object, fill it! */
entry->event = *event;
entry->sequence.value = (int)(queue_pos + 1);
status = SDL_TRUE;
} else if (delta < 0) {
/* We ran into an old queue entry, which means it still needs to be dequeued */
} else {
SDL_Log("ERROR: mutex failed!\n");
}
SDL_UnlockMutex(queue->mutex);
return status;
}

References SDL_EventQueue::enqueue_pos, SDL_EventQueue::entries, SDL_EventQueueEntry::event, SDL_EventQueue::mutex, SDL_FALSE, SDL_LockMutex, SDL_Log, SDL_TRUE, SDL_UnlockMutex, SDL_EventQueueEntry::sequence, SDL_atomic_t::value, and WRAP_MASK.

Referenced by FIFO_Writer().

## FIFO_Reader()

static int FIFO_Reader | ( | void * | _data | ) |

static

Definition at line 533 of file testatomic.c.

{
ReaderData *data = (ReaderData *)_data;
SDL_EventQueue *queue = data->queue;
SDL_Event event;
if (data->lock_free) {
for ( ; ; ) {
if (DequeueEvent_LockFree(queue, &event)) {
WriterData *writer = (WriterData*)event.user.data1;
++data->counters[writer->index];
} else if (SDL_AtomicGet(&queue->active)) {
++data->waits;
SDL_Delay(0);
} else {
/* We drained the queue, we're done! */
break;
}
}
} else {
for ( ; ; ) {
if (DequeueEvent_Mutex(queue, &event)) {
WriterData *writer = (WriterData*)event.user.data1;
++data->counters[writer->index];
} else if (SDL_AtomicGet(&queue->active)) {
++data->waits;
SDL_Delay(0);
} else {
/* We drained the queue, we're done! */
break;
}
}
}
SDL_AtomicAdd(&readersRunning, -1);
SDL_SemPost(readersDone);
return 0;
}

References SDL_EventQueue::active, DequeueEvent_LockFree(), DequeueEvent_Mutex(), WriterData::index, readersDone, readersRunning, SDL_AtomicAdd, SDL_AtomicGet, SDL_Delay, SDL_SemPost, and WriterData::waits.

Referenced by RunFIFOTest().

## FIFO_Watcher()

static int FIFO_Watcher | ( | void * | _data | ) |

static

Definition at line 573 of file testatomic.c.

{
SDL_EventQueue *queue = (SDL_EventQueue *)_data;
while (SDL_AtomicGet(&queue->active)) {
SDL_AtomicLock(&queue->lock);
SDL_AtomicIncRef(&queue->watcher);
while (SDL_AtomicGet(&queue->rwcount) > 0) {
SDL_Delay(0);
}
/* Do queue manipulation here... */
SDL_AtomicDecRef(&queue->watcher);
SDL_AtomicUnlock(&queue->lock);
/* Wait a bit... */
SDL_Delay(1);
}
return 0;
}

References SDL_EventQueue::active, SDL_EventQueue::lock, SDL_EventQueue::rwcount, SDL_AtomicDecRef, SDL_AtomicGet, SDL_AtomicIncRef, SDL_AtomicLock, SDL_AtomicUnlock, SDL_Delay, and SDL_EventQueue::watcher.

Referenced by RunFIFOTest().

## FIFO_Writer()

static int FIFO_Writer | ( | void * | _data | ) |

static

Definition at line 498 of file testatomic.c.

{
WriterData *data = (WriterData *)_data;
SDL_EventQueue *queue = data->queue;
int i;
SDL_Event event;
event.type = SDL_USEREVENT;
event.user.windowID = 0;
event.user.code = 0;
event.user.data1 = data;
event.user.data2 = NULL;
if (data->lock_free) {
for (i = 0; i < EVENTS_PER_WRITER; ++i) {
event.user.code = i;
while (!EnqueueEvent_LockFree(queue, &event)) {
++data->waits;
SDL_Delay(0);
}
}
} else {
for (i = 0; i < EVENTS_PER_WRITER; ++i) {
event.user.code = i;
while (!EnqueueEvent_Mutex(queue, &event)) {
++data->waits;
SDL_Delay(0);
}
}
}
SDL_AtomicAdd(&writersRunning, -1);
SDL_SemPost(writersDone);
return 0;
}

References EnqueueEvent_LockFree(), EnqueueEvent_Mutex(), EVENTS_PER_WRITER, i, NULL, SDL_AtomicAdd, SDL_Delay, SDL_SemPost, SDL_USEREVENT, writersDone, and writersRunning.

Referenced by RunFIFOTest().

## InitEventQueue()

static void InitEventQueue | ( | SDL_EventQueue * | queue | ) |

static

Definition at line 297 of file testatomic.c.

{
int i;
for (i = 0; i < MAX_ENTRIES; ++i) {
SDL_AtomicSet(&queue->entries[i].sequence, i);
}
SDL_AtomicSet(&queue->enqueue_pos, 0);
SDL_AtomicSet(&queue->dequeue_pos, 0);
#ifdef TEST_SPINLOCK_FIFO
queue->lock = 0;
SDL_AtomicSet(&queue->rwcount, 0);
SDL_AtomicSet(&queue->watcher, 0);
#endif
SDL_AtomicSet(&queue->active, 1);
}

References SDL_EventQueue::active, SDL_EventQueue::dequeue_pos, SDL_EventQueue::enqueue_pos, SDL_EventQueue::entries, i, SDL_EventQueue::lock, MAX_ENTRIES, SDL_EventQueue::rwcount, SDL_AtomicSet, SDL_EventQueueEntry::sequence, and SDL_EventQueue::watcher.

Referenced by RunFIFOTest().

## main()

int main | ( | int | argc,
|  | char * | argv[]
| ) |  |

Definition at line 712 of file testatomic.c.

{
/* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
RunBasicTest();
RunEpicTest();
/* This test is really slow, so don't run it by default */
#if 0
RunFIFOTest(SDL_FALSE);
#endif
RunFIFOTest(SDL_TRUE);
return 0;
}

References RunBasicTest(), RunEpicTest(), RunFIFOTest(), SDL_FALSE, SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, SDL_LogSetPriority, and SDL_TRUE.

## runAdder()

static void runAdder | ( | void |  | ) |

static

Definition at line 134 of file testatomic.c.

{
Uint32 start, end;
int T=NThreads;
start = SDL_GetTicks();
threadDone = SDL_CreateSemaphore(0);
SDL_AtomicSet(&threadsRunning, NThreads);
while (T--)
SDL_CreateThread(adder, "Adder", NULL);
while (SDL_AtomicGet(&threadsRunning) > 0)
SDL_SemWait(threadDone);
SDL_DestroySemaphore(threadDone);
end = SDL_GetTicks();
SDL_Log("Finished in %f sec\n", (end - start) / 1000.f);
}

References adder(), NThreads, NULL, SDL_AtomicGet, SDL_AtomicSet, SDL_CreateSemaphore, SDL_CreateThread, SDL_DestroySemaphore, SDL_GetTicks(), SDL_Log, SDL_SemWait, T, threadDone, and threadsRunning.

Referenced by RunEpicTest().

## RunBasicTest()

static void RunBasicTest | ( |  | ) |

static

Definition at line 37 of file testatomic.c.

{
int value;
SDL_SpinLock lock = 0;
SDL_atomic_t v;
SDL_bool tfret = SDL_FALSE;
SDL_Log("\nspin lock---------------------------------------\n\n");
SDL_AtomicLock(&lock);
SDL_Log("AtomicLock lock=%d\n", lock);
SDL_AtomicUnlock(&lock);
SDL_Log("AtomicUnlock lock=%d\n", lock);
SDL_Log("\natomic -----------------------------------------\n\n");
SDL_AtomicSet(&v, 0);
tfret = SDL_AtomicSet(&v, 10) == 0 ? SDL_TRUE : SDL_FALSE;
SDL_Log("AtomicSet(10) tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
tfret = SDL_AtomicAdd(&v, 10) == 10 ? SDL_TRUE : SDL_FALSE;
SDL_Log("AtomicAdd(10) tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
SDL_AtomicSet(&v, 0);
SDL_AtomicIncRef(&v);
tfret = (SDL_AtomicGet(&v) == 1) ? SDL_TRUE : SDL_FALSE;
SDL_Log("AtomicIncRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
SDL_AtomicIncRef(&v);
tfret = (SDL_AtomicGet(&v) == 2) ? SDL_TRUE : SDL_FALSE;
SDL_Log("AtomicIncRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
tfret = (SDL_AtomicDecRef(&v) == SDL_FALSE) ? SDL_TRUE : SDL_FALSE;
SDL_Log("AtomicDecRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
tfret = (SDL_AtomicDecRef(&v) == SDL_TRUE) ? SDL_TRUE : SDL_FALSE;
SDL_Log("AtomicDecRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
SDL_AtomicSet(&v, 10);
tfret = (SDL_AtomicCAS(&v, 0, 20) == SDL_FALSE) ? SDL_TRUE : SDL_FALSE;
SDL_Log("AtomicCAS() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
value = SDL_AtomicGet(&v);
tfret = (SDL_AtomicCAS(&v, value, 20) == SDL_TRUE) ? SDL_TRUE : SDL_FALSE;
SDL_Log("AtomicCAS() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
}

References lock, SDL_AtomicAdd, SDL_AtomicCAS, SDL_AtomicDecRef, SDL_AtomicGet, SDL_AtomicIncRef, SDL_AtomicLock, SDL_AtomicSet, SDL_AtomicUnlock, SDL_FALSE, SDL_Log, SDL_TRUE, and tf().

Referenced by main().

## RunEpicTest()

static void RunEpicTest | ( |  | ) |

static

Definition at line 159 of file testatomic.c.

{
int b;
atomicValue v;
SDL_Log("\nepic test---------------------------------------\n\n");
SDL_Log("Size asserted to be >= 32-bit\n");
SDL_assert(sizeof(atomicValue)>=4);
SDL_Log("Check static initializer\n");
v=SDL_AtomicGet(&good);
SDL_assert(v==42);
SDL_assert(bad==42);
SDL_Log("Test negative values\n");
SDL_AtomicSet(&good, -5);
v=SDL_AtomicGet(&good);
SDL_assert(v==-5);
SDL_Log("Verify maximum value\n");
SDL_AtomicSet(&good, CountTo);
v=SDL_AtomicGet(&good);
SDL_assert(v==CountTo);
SDL_Log("Test compare and exchange\n");
b=SDL_AtomicCAS(&good, 500, 43);
SDL_assert(!b); /* no swap since CountTo!=500 */
v=SDL_AtomicGet(&good);
SDL_assert(v==CountTo); /* ensure no swap */
b=SDL_AtomicCAS(&good, CountTo, 44);
SDL_assert(!!b); /* will swap */
v=SDL_AtomicGet(&good);
SDL_assert(v==44);
SDL_Log("Test Add\n");
v=SDL_AtomicAdd(&good, 1);
SDL_assert(v==44);
v=SDL_AtomicGet(&good);
SDL_assert(v==45);
v=SDL_AtomicAdd(&good, 10);
SDL_assert(v==45);
v=SDL_AtomicGet(&good);
SDL_assert(v==55);
SDL_Log("Test Add (Negative values)\n");
v=SDL_AtomicAdd(&good, -20);
SDL_assert(v==55);
v=SDL_AtomicGet(&good);
SDL_assert(v==35);
v=SDL_AtomicAdd(&good, -50); /* crossing zero down */
SDL_assert(v==35);
v=SDL_AtomicGet(&good);
SDL_assert(v==-15);
v=SDL_AtomicAdd(&good, 30); /* crossing zero up */
SDL_assert(v==-15);
v=SDL_AtomicGet(&good);
SDL_assert(v==15);
SDL_Log("Reset before count down test\n");
SDL_AtomicSet(&good, CountTo);
v=SDL_AtomicGet(&good);
SDL_assert(v==CountTo);
bad=CountTo;
SDL_assert(bad==CountTo);
SDL_Log("Counting down from %d, Expect %d remaining\n",CountTo,Expect);
runAdder();
v=SDL_AtomicGet(&good);
SDL_Log("Atomic %d Non-Atomic %d\n",v,bad);
SDL_assert(v==Expect);
SDL_assert(bad!=Expect);
}

References atomicValue, bad, CountTo, Expect, good, runAdder(), SDL_assert, SDL_AtomicAdd, SDL_AtomicCAS, SDL_AtomicGet, SDL_AtomicSet, and SDL_Log.

Referenced by main().

## RunFIFOTest()

static void RunFIFOTest | ( | SDL_bool | lock_free | ) |

static

Definition at line 594 of file testatomic.c.

{
SDL_EventQueue queue;
WriterData writerData[NUM_WRITERS];
ReaderData readerData[NUM_READERS];
Uint32 start, end;
int i, j;
int grand_total;
char textBuffer[1024];
size_t len;
SDL_Log("\nFIFO test---------------------------------------\n\n");
SDL_Log("Mode: %s\n", lock_free ? "LockFree" : "Mutex");
readersDone = SDL_CreateSemaphore(0);
writersDone = SDL_CreateSemaphore(0);
SDL_memset(&queue, 0xff, sizeof(queue));
InitEventQueue(&queue);
if (!lock_free) {
queue.mutex = SDL_CreateMutex();
}
start = SDL_GetTicks();
#ifdef TEST_SPINLOCK_FIFO
/* Start a monitoring thread */
if (lock_free) {
SDL_CreateThread(FIFO_Watcher, "FIFOWatcher", &queue);
}
#endif
/* Start the readers first */
SDL_Log("Starting %d readers\n", NUM_READERS);
SDL_zero(readerData);
SDL_AtomicSet(&readersRunning, NUM_READERS);
for (i = 0; i < NUM_READERS; ++i) {
char name[64];
SDL_snprintf(name, sizeof (name), "FIFOReader%d", i);
readerData[i].queue = &queue;
readerData[i].lock_free = lock_free;
SDL_CreateThread(FIFO_Reader, name, &readerData[i]);
}
/* Start up the writers */
SDL_Log("Starting %d writers\n", NUM_WRITERS);
SDL_zero(writerData);
SDL_AtomicSet(&writersRunning, NUM_WRITERS);
for (i = 0; i < NUM_WRITERS; ++i) {
char name[64];
SDL_snprintf(name, sizeof (name), "FIFOWriter%d", i);
writerData[i].queue = &queue;
writerData[i].index = i;
writerData[i].lock_free = lock_free;
SDL_CreateThread(FIFO_Writer, name, &writerData[i]);
}
/* Wait for the writers */
while (SDL_AtomicGet(&writersRunning) > 0) {
SDL_SemWait(writersDone);
}
/* Shut down the queue so readers exit */
SDL_AtomicSet(&queue.active, 0);
/* Wait for the readers */
while (SDL_AtomicGet(&readersRunning) > 0) {
SDL_SemWait(readersDone);
}
end = SDL_GetTicks();
SDL_DestroySemaphore(readersDone);
SDL_DestroySemaphore(writersDone);
if (!lock_free) {
SDL_DestroyMutex(queue.mutex);
}
SDL_Log("Finished in %f sec\n", (end - start) / 1000.f);
SDL_Log("\n");
for (i = 0; i < NUM_WRITERS; ++i) {
SDL_Log("Writer %d wrote %d events, had %d waits\n", i, EVENTS_PER_WRITER, writerData[i].waits);
}
SDL_Log("Writers wrote %d total events\n", NUM_WRITERS*EVENTS_PER_WRITER);
/* Print a breakdown of which readers read messages from which writer */
SDL_Log("\n");
grand_total = 0;
for (i = 0; i < NUM_READERS; ++i) {
int total = 0;
for (j = 0; j < NUM_WRITERS; ++j) {
total += readerData[i].counters[j];
}
grand_total += total;
SDL_Log("Reader %d read %d events, had %d waits\n", i, total, readerData[i].waits);
SDL_snprintf(textBuffer, sizeof(textBuffer), " { ");
for (j = 0; j < NUM_WRITERS; ++j) {
if (j > 0) {
len = SDL_strlen(textBuffer);
SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, ", ");
}
len = SDL_strlen(textBuffer);
SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, "%d", readerData[i].counters[j]);
}
len = SDL_strlen(textBuffer);
SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, " }\n");
SDL_Log("%s", textBuffer);
}
SDL_Log("Readers read %d total events\n", grand_total);
}

References SDL_EventQueue::active, ReaderData::counters, EVENTS_PER_WRITER, FIFO_Reader(), FIFO_Watcher(), FIFO_Writer(), i, WriterData::index, InitEventQueue(), j, WriterData::lock_free, ReaderData::lock_free, SDL_EventQueue::mutex, NUM_READERS, NUM_WRITERS, WriterData::queue, ReaderData::queue, readersDone, readersRunning, SDL_AtomicGet, SDL_AtomicSet, SDL_CreateMutex, SDL_CreateSemaphore, SDL_CreateThread, SDL_DestroyMutex, SDL_DestroySemaphore, SDL_GetTicks(), SDL_Log, SDL_memset, SDL_SemWait, SDL_snprintf, SDL_strlen, SDL_zero, writersDone, and writersRunning.

Referenced by main().

## SDL_COMPILE_TIME_ASSERT()

SDL_COMPILE_TIME_ASSERT | ( | size | ,
|  | CountTo_GreaterThanZero |
| ) |  |

## tf()

static char* tf | ( | SDL_bool | tf | ) |

static

Definition at line 23 of file testatomic.c.

{
static char *t = "TRUE";
static char *f = "FALSE";
if (tf)
{
return t;
}
return f;
}

Referenced by RunBasicTest().

## Variable Documentation

## bad

atomicValue bad = 42

static

Definition at line 113 of file testatomic.c.

Referenced by adder(), and RunEpicTest().

## good

SDL_atomic_t good = { 42 }

static

Definition at line 111 of file testatomic.c.

Referenced by adder(), and RunEpicTest().

## readersDone

SDL_sem* readersDone

static

Definition at line 475 of file testatomic.c.

Referenced by FIFO_Reader(), and RunFIFOTest().

## readersRunning

SDL_atomic_t readersRunning

static

Definition at line 477 of file testatomic.c.

Referenced by FIFO_Reader(), and RunFIFOTest().

## threadDone

SDL_sem* threadDone

static

Definition at line 117 of file testatomic.c.

Referenced by adder(), and runAdder().

## threadsRunning

SDL_atomic_t threadsRunning

static

Definition at line 115 of file testatomic.c.

Referenced by adder(), and runAdder().

## writersDone

SDL_sem* writersDone

static

Definition at line 474 of file testatomic.c.

Referenced by FIFO_Writer(), and RunFIFOTest().

## writersRunning

SDL_atomic_t writersRunning

static

Definition at line 476 of file testatomic.c.

Referenced by FIFO_Writer(), and RunFIFOTest().

SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:386
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
RunBasicTest
static void RunBasicTest()
Definition: testatomic.c:37
RunFIFOTest
static void RunFIFOTest(SDL_bool lock_free)
Definition: testatomic.c:594
adder
static int adder(void *junk)
Definition: testatomic.c:120
end
GLuint GLuint end
Definition: SDL_opengl.h:1571
SDL_LOG_CATEGORY_APPLICATION
@ SDL_LOG_CATEGORY_APPLICATION
Definition: SDL_log.h:66
SDL_CreateSemaphore
#define SDL_CreateSemaphore
Definition: SDL_dynapi_overrides.h:264
SDL_AtomicCAS
#define SDL_AtomicCAS
Definition: SDL_dynapi_overrides.h:66
SDL_LockMutex
#define SDL_LockMutex
Definition: SDL_dynapi_overrides.h:260
NULL
#define NULL
Definition: begin_code.h:167
b
GLboolean GLboolean GLboolean b
Definition: SDL_opengl_glext.h:1109
Expect
#define Expect
Definition: testatomic.c:104
SDL_AtomicLock
#define SDL_AtomicLock
Definition: SDL_dynapi_overrides.h:64
WRAP_MASK
#define WRAP_MASK
Definition: testatomic.c:260
CountTo
#define CountTo
Definition: testatomic.c:102
EVENTS_PER_WRITER
#define EVENTS_PER_WRITER
Definition: testatomic.c:256
readersRunning
static SDL_atomic_t readersRunning
Definition: testatomic.c:477
SDL_AtomicIncRef
#define SDL_AtomicIncRef(a)
Increment an atomic variable used as a reference count.
Definition: SDL_atomic.h:252
SDL_EventQueue::entries
SDL_EventQueueEntry entries[MAX_ENTRIES]
Definition: testatomic.c:270
SDL_CreateMutex
#define SDL_CreateMutex
Definition: SDL_dynapi_overrides.h:259
writersRunning
static SDL_atomic_t writersRunning
Definition: testatomic.c:476
threadDone
static SDL_sem * threadDone
Definition: testatomic.c:117
FIFO_Watcher
static int FIFO_Watcher(void *_data)
Definition: testatomic.c:573
atomicValue
#define atomicValue
Definition: testatomic.c:101
writersDone
static SDL_sem * writersDone
Definition: testatomic.c:474
v
const GLdouble * v
Definition: SDL_opengl.h:2064
SDL_SemPost
#define SDL_SemPost
Definition: SDL_dynapi_overrides.h:269
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_atomic_t::value
int value
Definition: SDL_atomic.h:216
counters
GLint GLint GLsizei GLuint * counters
Definition: SDL_opengl_glext.h:4990
InitEventQueue
static void InitEventQueue(SDL_EventQueue *queue)
Definition: testatomic.c:297
ReaderData
Definition: testatomic.c:489
SDL_AtomicDecRef
#define SDL_AtomicDecRef(a)
Decrement an atomic variable used as a reference count.
Definition: SDL_atomic.h:262
good
static SDL_atomic_t good
Definition: testatomic.c:111
threadsRunning
static SDL_atomic_t threadsRunning
Definition: testatomic.c:115
len
GLenum GLsizei len
Definition: SDL_opengl_glext.h:2926
NInter
#define NInter
Definition: testatomic.c:103
event
struct _cl_event * event
Definition: SDL_opengl_glext.h:2649
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_AtomicUnlock
#define SDL_AtomicUnlock
Definition: SDL_dynapi_overrides.h:65
WriterData::queue
SDL_EventQueue * queue
Definition: testatomic.c:481
SDL_Log
#define SDL_Log
Definition: SDL_dynapi_overrides.h:31
SDL_EventQueueEntry
Definition: testatomic.c:262
f
GLfloat f
Definition: SDL_opengl_glext.h:1870
t
GLdouble GLdouble t
Definition: SDL_opengl.h:2071
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
RunEpicTest
static void RunEpicTest()
Definition: testatomic.c:159
SDL_EventQueue::lock
SDL_SpinLock lock
Definition: testatomic.c:283
SDL_GetTicks
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
ReaderData::counters
int counters[NUM_WRITERS]
Definition: testatomic.c:492
tf
static char * tf(SDL_bool tf)
Definition: testatomic.c:23
EnqueueEvent_Mutex
static SDL_bool EnqueueEvent_Mutex(SDL_EventQueue *queue, const SDL_Event *event)
Definition: testatomic.c:408
SDL_EventQueue::active
SDL_atomic_t active
Definition: testatomic.c:290
SDL_Delay
#define SDL_Delay
Definition: SDL_dynapi_overrides.h:486
SDL_CreateThread
#define SDL_CreateThread
Definition: SDL_dynapi_overrides.h:41
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
start
GLuint start
Definition: SDL_opengl.h:1571
EnqueueEvent_LockFree
static SDL_bool EnqueueEvent_LockFree(SDL_EventQueue *queue, const SDL_Event *event)
Definition: testatomic.c:314
SDL_SpinLock
int SDL_SpinLock
Definition: SDL_atomic.h:89
WriterData::index
int index
Definition: testatomic.c:482
FIFO_Reader
static int FIFO_Reader(void *_data)
Definition: testatomic.c:533
SDL_EventQueue::rwcount
SDL_atomic_t rwcount
Definition: testatomic.c:284
WriterData::lock_free
SDL_bool lock_free
Definition: testatomic.c:485
DequeueEvent_Mutex
static SDL_bool DequeueEvent_Mutex(SDL_EventQueue *queue, SDL_Event *event)
Definition: testatomic.c:441
readersDone
static SDL_sem * readersDone
Definition: testatomic.c:475
SDL_LOG_PRIORITY_INFO
@ SDL_LOG_PRIORITY_INFO
Definition: SDL_log.h:106
SDL_EventQueue::dequeue_pos
SDL_atomic_t dequeue_pos
Definition: testatomic.c:278
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_SemWait
#define SDL_SemWait
Definition: SDL_dynapi_overrides.h:266
ReaderData::queue
SDL_EventQueue * queue
Definition: testatomic.c:491
SDL_AtomicAdd
#define SDL_AtomicAdd
Definition: SDL_dynapi_overrides.h:69
bad
static atomicValue bad
Definition: testatomic.c:113
SDL_LogSetPriority
#define SDL_LogSetPriority
Definition: SDL_dynapi_overrides.h:236
value
GLsizei const GLfloat * value
Definition: SDL_opengl_glext.h:698
FIFO_Writer
static int FIFO_Writer(void *_data)
Definition: testatomic.c:498
CountInc
#define CountInc
Definition: testatomic.c:98
SDL_snprintf
#define SDL_snprintf
Definition: SDL_dynapi_overrides.h:40
j
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
Definition: SDL_x11sym.h:50
NUM_WRITERS
#define NUM_WRITERS
Definition: testatomic.c:255
SDL_atomic_t
A type representing an atomic integer value. It is a struct so people don't accidentally use numeric ...
Definition: SDL_atomic.h:216
SDL_DestroyMutex
#define SDL_DestroyMutex
Definition: SDL_dynapi_overrides.h:263
WriterData
Definition: testatomic.c:479
runAdder
static void runAdder(void)
Definition: testatomic.c:134
WriterData::waits
int waits
Definition: testatomic.c:484
NThreads
#define NThreads
Definition: testatomic.c:97
SDL_DestroySemaphore
#define SDL_DestroySemaphore
Definition: SDL_dynapi_overrides.h:265
SDL_strlen
#define SDL_strlen
Definition: SDL_dynapi_overrides.h:393
SDL_Event
General event structure.
Definition: SDL_events.h:557
SDL_AtomicSet
#define SDL_AtomicSet
Definition: SDL_dynapi_overrides.h:67
NUM_READERS
#define NUM_READERS
Definition: testatomic.c:254
SDL_AtomicGet
#define SDL_AtomicGet
Definition: SDL_dynapi_overrides.h:68
SDL_EventQueue::mutex
SDL_mutex * mutex
Definition: testatomic.c:293
T
static const double T[]
Definition: k_tan.c:53
DequeueEvent_LockFree
static SDL_bool DequeueEvent_LockFree(SDL_EventQueue *queue, SDL_Event *event)
Definition: testatomic.c:361
SDL_UnlockMutex
#define SDL_UnlockMutex
Definition: SDL_dynapi_overrides.h:262
SDL_EventQueueEntry::sequence
SDL_atomic_t sequence
Definition: testatomic.c:264
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_EventQueue
Definition: testatomic.c:268
ReaderData::lock_free
SDL_bool lock_free
Definition: testatomic.c:494
SDL_EventQueueEntry::event
SDL_Event event
Definition: testatomic.c:265
SDL_EventQueue::enqueue_pos
SDL_atomic_t enqueue_pos
Definition: testatomic.c:274
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
SDL_USEREVENT
@ SDL_USEREVENT
Definition: SDL_events.h:160
lock
SDL_mutex * lock
Definition: SDL_events.c:76
MAX_ENTRIES
#define MAX_ENTRIES
Definition: testatomic.c:259
SDL_EventQueue::watcher
SDL_atomic_t watcher
Definition: testatomic.c:285