SDL 2.0
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.

106 {
107 CountTo_GreaterThanZero = CountTo > 0,
108};
#define CountTo
Definition: testatomic.c:102

Function Documentation

◆ adder()

static int adder ( void junk)
static

Definition at line 120 of file testatomic.c.

121{
122 unsigned long N=NInter;
123 SDL_Log("Thread subtracting %d %lu times\n",CountInc,N);
124 while (N--) {
126 bad-=CountInc;
127 }
130 return 0;
131}
#define SDL_SemPost
#define SDL_Log
#define SDL_AtomicAdd
static SDL_atomic_t good
Definition: testatomic.c:111
static SDL_sem * threadDone
Definition: testatomic.c:117
static atomicValue bad
Definition: testatomic.c:113
#define CountInc
Definition: testatomic.c:98
static SDL_atomic_t threadsRunning
Definition: testatomic.c:115
#define NInter
Definition: testatomic.c:103

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.

362{
363 SDL_EventQueueEntry *entry;
364 unsigned queue_pos;
365 unsigned entry_seq;
366 int delta;
367 SDL_bool status;
368
369#ifdef TEST_SPINLOCK_FIFO
370 /* This is a gate so an external thread can lock the queue */
371 SDL_AtomicLock(&queue->lock);
372 SDL_assert(SDL_AtomicGet(&queue->watcher) == 0);
373 SDL_AtomicIncRef(&queue->rwcount);
374 SDL_AtomicUnlock(&queue->lock);
375#endif
376
377 queue_pos = (unsigned)SDL_AtomicGet(&queue->dequeue_pos);
378 for ( ; ; ) {
379 entry = &queue->entries[queue_pos & WRAP_MASK];
380 entry_seq = (unsigned)SDL_AtomicGet(&entry->sequence);
381
382 delta = (int)(entry_seq - (queue_pos + 1));
383 if (delta == 0) {
384 /* The entry and the queue position match, try to increment the queue position */
385 if (SDL_AtomicCAS(&queue->dequeue_pos, (int)queue_pos, (int)(queue_pos+1))) {
386 /* We own the object, fill it! */
387 *event = entry->event;
388 SDL_AtomicSet(&entry->sequence, (int)(queue_pos+MAX_ENTRIES));
389 status = SDL_TRUE;
390 break;
391 }
392 } else if (delta < 0) {
393 /* We ran into an old queue entry, which means we've hit empty */
394 status = SDL_FALSE;
395 break;
396 } else {
397 /* We ran into a new queue entry, get the new queue position */
398 queue_pos = (unsigned)SDL_AtomicGet(&queue->dequeue_pos);
399 }
400 }
401
402#ifdef TEST_SPINLOCK_FIFO
403 SDL_AtomicDecRef(&queue->rwcount);
404#endif
405 return status;
406}
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define SDL_AtomicDecRef(a)
Decrement an atomic variable used as a reference count.
Definition: SDL_atomic.h:262
#define SDL_AtomicIncRef(a)
Increment an atomic variable used as a reference count.
Definition: SDL_atomic.h:252
#define SDL_AtomicSet
#define SDL_AtomicLock
#define SDL_AtomicCAS
#define SDL_AtomicUnlock
#define SDL_AtomicGet
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
Definition: testatomic.c:263
SDL_atomic_t sequence
Definition: testatomic.c:264
SDL_Event event
Definition: testatomic.c:265
SDL_atomic_t watcher
Definition: testatomic.c:285
SDL_atomic_t rwcount
Definition: testatomic.c:284
SDL_EventQueueEntry entries[MAX_ENTRIES]
Definition: testatomic.c:270
SDL_atomic_t dequeue_pos
Definition: testatomic.c:278
SDL_SpinLock lock
Definition: testatomic.c:283
#define MAX_ENTRIES
Definition: testatomic.c:259
#define WRAP_MASK
Definition: testatomic.c:260

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.

442{
443 SDL_EventQueueEntry *entry;
444 unsigned queue_pos;
445 unsigned entry_seq;
446 int delta;
447 SDL_bool status = SDL_FALSE;
448
449 SDL_LockMutex(queue->mutex);
450
451 queue_pos = (unsigned)queue->dequeue_pos.value;
452 entry = &queue->entries[queue_pos & WRAP_MASK];
453 entry_seq = (unsigned)entry->sequence.value;
454
455 delta = (int)(entry_seq - (queue_pos + 1));
456 if (delta == 0) {
457 ++queue->dequeue_pos.value;
458
459 /* We own the object, fill it! */
460 *event = entry->event;
461 entry->sequence.value = (int)(queue_pos + MAX_ENTRIES);
462 status = SDL_TRUE;
463 } else if (delta < 0) {
464 /* We ran into an old queue entry, which means we've hit empty */
465 } else {
466 SDL_Log("ERROR: mutex failed!\n");
467 }
468
469 SDL_UnlockMutex(queue->mutex);
470
471 return status;
472}
#define SDL_LockMutex
#define SDL_UnlockMutex
SDL_mutex * mutex
Definition: testatomic.c:293

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.

315{
316 SDL_EventQueueEntry *entry;
317 unsigned queue_pos;
318 unsigned entry_seq;
319 int delta;
320 SDL_bool status;
321
322#ifdef TEST_SPINLOCK_FIFO
323 /* This is a gate so an external thread can lock the queue */
324 SDL_AtomicLock(&queue->lock);
325 SDL_assert(SDL_AtomicGet(&queue->watcher) == 0);
326 SDL_AtomicIncRef(&queue->rwcount);
327 SDL_AtomicUnlock(&queue->lock);
328#endif
329
330 queue_pos = (unsigned)SDL_AtomicGet(&queue->enqueue_pos);
331 for ( ; ; ) {
332 entry = &queue->entries[queue_pos & WRAP_MASK];
333 entry_seq = (unsigned)SDL_AtomicGet(&entry->sequence);
334
335 delta = (int)(entry_seq - queue_pos);
336 if (delta == 0) {
337 /* The entry and the queue position match, try to increment the queue position */
338 if (SDL_AtomicCAS(&queue->enqueue_pos, (int)queue_pos, (int)(queue_pos+1))) {
339 /* We own the object, fill it! */
340 entry->event = *event;
341 SDL_AtomicSet(&entry->sequence, (int)(queue_pos + 1));
342 status = SDL_TRUE;
343 break;
344 }
345 } else if (delta < 0) {
346 /* We ran into an old queue entry, which means it still needs to be dequeued */
347 status = SDL_FALSE;
348 break;
349 } else {
350 /* We ran into a new queue entry, get the new queue position */
351 queue_pos = (unsigned)SDL_AtomicGet(&queue->enqueue_pos);
352 }
353 }
354
355#ifdef TEST_SPINLOCK_FIFO
356 SDL_AtomicDecRef(&queue->rwcount);
357#endif
358 return status;
359}
struct _cl_event * event
SDL_atomic_t enqueue_pos
Definition: testatomic.c:274

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.

409{
410 SDL_EventQueueEntry *entry;
411 unsigned queue_pos;
412 unsigned entry_seq;
413 int delta;
414 SDL_bool status = SDL_FALSE;
415
416 SDL_LockMutex(queue->mutex);
417
418 queue_pos = (unsigned)queue->enqueue_pos.value;
419 entry = &queue->entries[queue_pos & WRAP_MASK];
420 entry_seq = (unsigned)entry->sequence.value;
421
422 delta = (int)(entry_seq - queue_pos);
423 if (delta == 0) {
424 ++queue->enqueue_pos.value;
425
426 /* We own the object, fill it! */
427 entry->event = *event;
428 entry->sequence.value = (int)(queue_pos + 1);
429 status = SDL_TRUE;
430 } else if (delta < 0) {
431 /* We ran into an old queue entry, which means it still needs to be dequeued */
432 } else {
433 SDL_Log("ERROR: mutex failed!\n");
434 }
435
436 SDL_UnlockMutex(queue->mutex);
437
438 return status;
439}

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.

534{
535 ReaderData *data = (ReaderData *)_data;
536 SDL_EventQueue *queue = data->queue;
538
539 if (data->lock_free) {
540 for ( ; ; ) {
541 if (DequeueEvent_LockFree(queue, &event)) {
542 WriterData *writer = (WriterData*)event.user.data1;
543 ++data->counters[writer->index];
544 } else if (SDL_AtomicGet(&queue->active)) {
545 ++data->waits;
546 SDL_Delay(0);
547 } else {
548 /* We drained the queue, we're done! */
549 break;
550 }
551 }
552 } else {
553 for ( ; ; ) {
554 if (DequeueEvent_Mutex(queue, &event)) {
555 WriterData *writer = (WriterData*)event.user.data1;
556 ++data->counters[writer->index];
557 } else if (SDL_AtomicGet(&queue->active)) {
558 ++data->waits;
559 SDL_Delay(0);
560 } else {
561 /* We drained the queue, we're done! */
562 break;
563 }
564 }
565 }
568 return 0;
569}
#define SDL_Delay
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_atomic_t active
Definition: testatomic.c:290
static SDL_bool DequeueEvent_Mutex(SDL_EventQueue *queue, SDL_Event *event)
Definition: testatomic.c:441
static SDL_atomic_t readersRunning
Definition: testatomic.c:477
static SDL_bool DequeueEvent_LockFree(SDL_EventQueue *queue, SDL_Event *event)
Definition: testatomic.c:361
static SDL_sem * readersDone
Definition: testatomic.c:475
General event structure.
Definition: SDL_events.h:558

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.

574{
575 SDL_EventQueue *queue = (SDL_EventQueue *)_data;
576
577 while (SDL_AtomicGet(&queue->active)) {
578 SDL_AtomicLock(&queue->lock);
579 SDL_AtomicIncRef(&queue->watcher);
580 while (SDL_AtomicGet(&queue->rwcount) > 0) {
581 SDL_Delay(0);
582 }
583 /* Do queue manipulation here... */
584 SDL_AtomicDecRef(&queue->watcher);
585 SDL_AtomicUnlock(&queue->lock);
586
587 /* Wait a bit... */
588 SDL_Delay(1);
589 }
590 return 0;
591}

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.

499{
500 WriterData *data = (WriterData *)_data;
501 SDL_EventQueue *queue = data->queue;
502 int i;
504
505 event.type = SDL_USEREVENT;
506 event.user.windowID = 0;
507 event.user.code = 0;
508 event.user.data1 = data;
509 event.user.data2 = NULL;
510
511 if (data->lock_free) {
512 for (i = 0; i < EVENTS_PER_WRITER; ++i) {
513 event.user.code = i;
514 while (!EnqueueEvent_LockFree(queue, &event)) {
515 ++data->waits;
516 SDL_Delay(0);
517 }
518 }
519 } else {
520 for (i = 0; i < EVENTS_PER_WRITER; ++i) {
521 event.user.code = i;
522 while (!EnqueueEvent_Mutex(queue, &event)) {
523 ++data->waits;
524 SDL_Delay(0);
525 }
526 }
527 }
530 return 0;
531}
@ SDL_USEREVENT
Definition: SDL_events.h:160
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
#define NULL
Definition: begin_code.h:167
static SDL_atomic_t writersRunning
Definition: testatomic.c:476
static SDL_sem * writersDone
Definition: testatomic.c:474
#define EVENTS_PER_WRITER
Definition: testatomic.c:256
static SDL_bool EnqueueEvent_LockFree(SDL_EventQueue *queue, const SDL_Event *event)
Definition: testatomic.c:314
static SDL_bool EnqueueEvent_Mutex(SDL_EventQueue *queue, const SDL_Event *event)
Definition: testatomic.c:408

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.

298{
299 int i;
300
301 for (i = 0; i < MAX_ENTRIES; ++i) {
302 SDL_AtomicSet(&queue->entries[i].sequence, i);
303 }
304 SDL_AtomicSet(&queue->enqueue_pos, 0);
305 SDL_AtomicSet(&queue->dequeue_pos, 0);
306#ifdef TEST_SPINLOCK_FIFO
307 queue->lock = 0;
308 SDL_AtomicSet(&queue->rwcount, 0);
309 SDL_AtomicSet(&queue->watcher, 0);
310#endif
311 SDL_AtomicSet(&queue->active, 1);
312}

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.

713{
714 /* Enable standard application logging */
716
717 RunBasicTest();
718 RunEpicTest();
719/* This test is really slow, so don't run it by default */
720#if 0
722#endif
724 return 0;
725}
#define SDL_LogSetPriority
@ SDL_LOG_PRIORITY_INFO
Definition: SDL_log.h:106
@ SDL_LOG_CATEGORY_APPLICATION
Definition: SDL_log.h:66
static void RunFIFOTest(SDL_bool lock_free)
Definition: testatomic.c:594
static void RunEpicTest()
Definition: testatomic.c:159
static void RunBasicTest()
Definition: testatomic.c:37

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.

135{
137 int T=NThreads;
138
140
142
144
145 while (T--)
146 SDL_CreateThread(adder, "Adder", NULL);
147
148 while (SDL_AtomicGet(&threadsRunning) > 0)
150
152
153 end = SDL_GetTicks();
154
155 SDL_Log("Finished in %f sec\n", (end - start) / 1000.f);
156}
#define SDL_CreateThread
#define SDL_SemWait
#define SDL_DestroySemaphore
#define SDL_CreateSemaphore
GLuint GLuint end
Definition: SDL_opengl.h:1571
GLuint start
Definition: SDL_opengl.h:1571
uint32_t Uint32
Definition: SDL_stdinc.h:203
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
static const double T[]
Definition: k_tan.c:53
#define NThreads
Definition: testatomic.c:97
static int adder(void *junk)
Definition: testatomic.c:120

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.

38{
39 int value;
41
43 SDL_bool tfret = SDL_FALSE;
44
45 SDL_Log("\nspin lock---------------------------------------\n\n");
46
48 SDL_Log("AtomicLock lock=%d\n", lock);
50 SDL_Log("AtomicUnlock lock=%d\n", lock);
51
52 SDL_Log("\natomic -----------------------------------------\n\n");
53
54 SDL_AtomicSet(&v, 0);
55 tfret = SDL_AtomicSet(&v, 10) == 0 ? SDL_TRUE : SDL_FALSE;
56 SDL_Log("AtomicSet(10) tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
57 tfret = SDL_AtomicAdd(&v, 10) == 10 ? SDL_TRUE : SDL_FALSE;
58 SDL_Log("AtomicAdd(10) tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
59
60 SDL_AtomicSet(&v, 0);
62 tfret = (SDL_AtomicGet(&v) == 1) ? SDL_TRUE : SDL_FALSE;
63 SDL_Log("AtomicIncRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
65 tfret = (SDL_AtomicGet(&v) == 2) ? SDL_TRUE : SDL_FALSE;
66 SDL_Log("AtomicIncRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
68 SDL_Log("AtomicDecRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
69 tfret = (SDL_AtomicDecRef(&v) == SDL_TRUE) ? SDL_TRUE : SDL_FALSE;
70 SDL_Log("AtomicDecRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
71
72 SDL_AtomicSet(&v, 10);
73 tfret = (SDL_AtomicCAS(&v, 0, 20) == SDL_FALSE) ? SDL_TRUE : SDL_FALSE;
74 SDL_Log("AtomicCAS() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
76 tfret = (SDL_AtomicCAS(&v, value, 20) == SDL_TRUE) ? SDL_TRUE : SDL_FALSE;
77 SDL_Log("AtomicCAS() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
78}
int SDL_SpinLock
Definition: SDL_atomic.h:89
SDL_mutex * lock
Definition: SDL_events.c:76
const GLdouble * v
Definition: SDL_opengl.h:2064
GLsizei const GLfloat * value
A type representing an atomic integer value. It is a struct so people don't accidentally use numeric ...
Definition: SDL_atomic.h:216
static char * tf(SDL_bool tf)
Definition: testatomic.c:23

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.

160{
161 int b;
163
164 SDL_Log("\nepic test---------------------------------------\n\n");
165
166 SDL_Log("Size asserted to be >= 32-bit\n");
167 SDL_assert(sizeof(atomicValue)>=4);
168
169 SDL_Log("Check static initializer\n");
171 SDL_assert(v==42);
172
173 SDL_assert(bad==42);
174
175 SDL_Log("Test negative values\n");
176 SDL_AtomicSet(&good, -5);
178 SDL_assert(v==-5);
179
180 SDL_Log("Verify maximum value\n");
184
185 SDL_Log("Test compare and exchange\n");
186
187 b=SDL_AtomicCAS(&good, 500, 43);
188 SDL_assert(!b); /* no swap since CountTo!=500 */
190 SDL_assert(v==CountTo); /* ensure no swap */
191
193 SDL_assert(!!b); /* will swap */
195 SDL_assert(v==44);
196
197 SDL_Log("Test Add\n");
198
199 v=SDL_AtomicAdd(&good, 1);
200 SDL_assert(v==44);
202 SDL_assert(v==45);
203
204 v=SDL_AtomicAdd(&good, 10);
205 SDL_assert(v==45);
207 SDL_assert(v==55);
208
209 SDL_Log("Test Add (Negative values)\n");
210
211 v=SDL_AtomicAdd(&good, -20);
212 SDL_assert(v==55);
214 SDL_assert(v==35);
215
216 v=SDL_AtomicAdd(&good, -50); /* crossing zero down */
217 SDL_assert(v==35);
219 SDL_assert(v==-15);
220
221 v=SDL_AtomicAdd(&good, 30); /* crossing zero up */
222 SDL_assert(v==-15);
224 SDL_assert(v==15);
225
226 SDL_Log("Reset before count down test\n");
230
231 bad=CountTo;
233
234 SDL_Log("Counting down from %d, Expect %d remaining\n",CountTo,Expect);
235 runAdder();
236
238 SDL_Log("Atomic %d Non-Atomic %d\n",v,bad);
241}
GLboolean GLboolean GLboolean b
#define Expect
Definition: testatomic.c:104
static void runAdder(void)
Definition: testatomic.c:134
#define atomicValue
Definition: testatomic.c:101

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.

595{
596 SDL_EventQueue queue;
597 WriterData writerData[NUM_WRITERS];
598 ReaderData readerData[NUM_READERS];
600 int i, j;
601 int grand_total;
602 char textBuffer[1024];
603 size_t len;
604
605 SDL_Log("\nFIFO test---------------------------------------\n\n");
606 SDL_Log("Mode: %s\n", lock_free ? "LockFree" : "Mutex");
607
610
611 SDL_memset(&queue, 0xff, sizeof(queue));
612
613 InitEventQueue(&queue);
614 if (!lock_free) {
615 queue.mutex = SDL_CreateMutex();
616 }
617
619
620#ifdef TEST_SPINLOCK_FIFO
621 /* Start a monitoring thread */
622 if (lock_free) {
623 SDL_CreateThread(FIFO_Watcher, "FIFOWatcher", &queue);
624 }
625#endif
626
627 /* Start the readers first */
628 SDL_Log("Starting %d readers\n", NUM_READERS);
629 SDL_zero(readerData);
631 for (i = 0; i < NUM_READERS; ++i) {
632 char name[64];
633 SDL_snprintf(name, sizeof (name), "FIFOReader%d", i);
634 readerData[i].queue = &queue;
635 readerData[i].lock_free = lock_free;
636 SDL_CreateThread(FIFO_Reader, name, &readerData[i]);
637 }
638
639 /* Start up the writers */
640 SDL_Log("Starting %d writers\n", NUM_WRITERS);
641 SDL_zero(writerData);
643 for (i = 0; i < NUM_WRITERS; ++i) {
644 char name[64];
645 SDL_snprintf(name, sizeof (name), "FIFOWriter%d", i);
646 writerData[i].queue = &queue;
647 writerData[i].index = i;
648 writerData[i].lock_free = lock_free;
649 SDL_CreateThread(FIFO_Writer, name, &writerData[i]);
650 }
651
652 /* Wait for the writers */
653 while (SDL_AtomicGet(&writersRunning) > 0) {
655 }
656
657 /* Shut down the queue so readers exit */
658 SDL_AtomicSet(&queue.active, 0);
659
660 /* Wait for the readers */
661 while (SDL_AtomicGet(&readersRunning) > 0) {
663 }
664
665 end = SDL_GetTicks();
666
669
670 if (!lock_free) {
671 SDL_DestroyMutex(queue.mutex);
672 }
673
674 SDL_Log("Finished in %f sec\n", (end - start) / 1000.f);
675
676 SDL_Log("\n");
677 for (i = 0; i < NUM_WRITERS; ++i) {
678 SDL_Log("Writer %d wrote %d events, had %d waits\n", i, EVENTS_PER_WRITER, writerData[i].waits);
679 }
680 SDL_Log("Writers wrote %d total events\n", NUM_WRITERS*EVENTS_PER_WRITER);
681
682 /* Print a breakdown of which readers read messages from which writer */
683 SDL_Log("\n");
684 grand_total = 0;
685 for (i = 0; i < NUM_READERS; ++i) {
686 int total = 0;
687 for (j = 0; j < NUM_WRITERS; ++j) {
688 total += readerData[i].counters[j];
689 }
690 grand_total += total;
691 SDL_Log("Reader %d read %d events, had %d waits\n", i, total, readerData[i].waits);
692 SDL_snprintf(textBuffer, sizeof(textBuffer), " { ");
693 for (j = 0; j < NUM_WRITERS; ++j) {
694 if (j > 0) {
695 len = SDL_strlen(textBuffer);
696 SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, ", ");
697 }
698 len = SDL_strlen(textBuffer);
699 SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, "%d", readerData[i].counters[j]);
700 }
701 len = SDL_strlen(textBuffer);
702 SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, " }\n");
703 SDL_Log("%s", textBuffer);
704 }
705 SDL_Log("Readers read %d total events\n", grand_total);
706}
#define SDL_memset
#define SDL_strlen
#define SDL_CreateMutex
#define SDL_DestroyMutex
#define SDL_snprintf
GLenum GLsizei len
GLuint const GLchar * name
GLint GLint GLsizei GLuint * counters
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
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
SDL_bool lock_free
Definition: testatomic.c:494
int counters[NUM_WRITERS]
Definition: testatomic.c:492
SDL_EventQueue * queue
Definition: testatomic.c:491
SDL_EventQueue * queue
Definition: testatomic.c:481
SDL_bool lock_free
Definition: testatomic.c:485
static int FIFO_Watcher(void *_data)
Definition: testatomic.c:573
#define NUM_WRITERS
Definition: testatomic.c:255
static int FIFO_Reader(void *_data)
Definition: testatomic.c:533
#define NUM_READERS
Definition: testatomic.c:254
static int FIFO_Writer(void *_data)
Definition: testatomic.c:498
static void InitEventQueue(SDL_EventQueue *queue)
Definition: testatomic.c:297

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.

24{
25 static char *t = "TRUE";
26 static char *f = "FALSE";
27
28 if (tf)
29 {
30 return t;
31 }
32
33 return f;
34}
GLdouble GLdouble t
Definition: SDL_opengl.h:2071
GLfloat f

References tf().

Referenced by RunBasicTest(), and tf().

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().