SDL  2.0
testatomic.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
3 
4  This software is provided 'as-is', without any express or implied
5  warranty. In no event will the authors be held liable for any damages
6  arising from the use of this software.
7 
8  Permission is granted to anyone to use this software for any purpose,
9  including commercial applications, and to alter it and redistribute it
10  freely.
11 */
12 #include <stdio.h>
13 
14 #include "SDL.h"
15 
16 /*
17  Absolutely basic tests just to see if we get the expected value
18  after calling each function.
19 */
20 
21 static
22 char *
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 }
35 
36 static
38 {
39  int value;
40  SDL_SpinLock lock = 0;
41 
43  SDL_bool tfret = SDL_FALSE;
44 
45  SDL_Log("\nspin lock---------------------------------------\n\n");
46 
47  SDL_AtomicLock(&lock);
48  SDL_Log("AtomicLock lock=%d\n", lock);
49  SDL_AtomicUnlock(&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);
61  SDL_AtomicIncRef(&v);
62  tfret = (SDL_AtomicGet(&v) == 1) ? SDL_TRUE : SDL_FALSE;
63  SDL_Log("AtomicIncRef() tfret=%s val=%d\n", tf(tfret), SDL_AtomicGet(&v));
64  SDL_AtomicIncRef(&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));
67  tfret = (SDL_AtomicDecRef(&v) == SDL_FALSE) ? SDL_TRUE : SDL_FALSE;
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));
75  value = 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 }
79 
80 /**************************************************************************/
81 /* Atomic operation test
82  * Adapted with permission from code by Michael Davidsaver at:
83  * http://bazaar.launchpad.net/~mdavidsaver/epics-base/atomic/revision/12105#src/libCom/test/epicsAtomicTest.c
84  * Original copyright 2010 Brookhaven Science Associates as operator of Brookhaven National Lab
85  * http://www.aps.anl.gov/epics/license/open.php
86  */
87 
88 /* Tests semantics of atomic operations. Also a stress test
89  * to see if they are really atomic.
90  *
91  * Several threads adding to the same variable.
92  * at the end the value is compared with the expected
93  * and with a non-atomic counter.
94  */
95 
96 /* Number of concurrent incrementers */
97 #define NThreads 2
98 #define CountInc 100
99 #define VALBITS (sizeof(atomicValue)*8)
100 
101 #define atomicValue int
102 #define CountTo ((atomicValue)((unsigned int)(1<<(VALBITS-1))-1))
103 #define NInter (CountTo/CountInc/NThreads)
104 #define Expect (CountTo-NInter*CountInc*NThreads)
105 
106 SDL_COMPILE_TIME_ASSERT(size, CountTo>0); /* check for rollover */
107 
108 static SDL_atomic_t good = { 42 };
109 
110 static atomicValue bad = 42;
111 
113 
114 static SDL_sem *threadDone;
115 
116 static
117 int adder(void* junk)
118 {
119  unsigned long N=NInter;
120  SDL_Log("Thread subtracting %d %lu times\n",CountInc,N);
121  while (N--) {
122  SDL_AtomicAdd(&good, -CountInc);
123  bad-=CountInc;
124  }
125  SDL_AtomicAdd(&threadsRunning, -1);
127  return 0;
128 }
129 
130 static
131 void runAdder(void)
132 {
133  Uint32 start, end;
134  int T=NThreads;
135 
136  start = SDL_GetTicks();
137 
139 
140  SDL_AtomicSet(&threadsRunning, NThreads);
141 
142  while (T--)
143  SDL_CreateThread(adder, "Adder", NULL);
144 
145  while (SDL_AtomicGet(&threadsRunning) > 0)
147 
149 
150  end = SDL_GetTicks();
151 
152  SDL_Log("Finished in %f sec\n", (end - start) / 1000.f);
153 }
154 
155 static
157 {
158  int b;
159  atomicValue v;
160 
161  SDL_Log("\nepic test---------------------------------------\n\n");
162 
163  SDL_Log("Size asserted to be >= 32-bit\n");
164  SDL_assert(sizeof(atomicValue)>=4);
165 
166  SDL_Log("Check static initializer\n");
167  v=SDL_AtomicGet(&good);
168  SDL_assert(v==42);
169 
170  SDL_assert(bad==42);
171 
172  SDL_Log("Test negative values\n");
173  SDL_AtomicSet(&good, -5);
174  v=SDL_AtomicGet(&good);
175  SDL_assert(v==-5);
176 
177  SDL_Log("Verify maximum value\n");
178  SDL_AtomicSet(&good, CountTo);
179  v=SDL_AtomicGet(&good);
180  SDL_assert(v==CountTo);
181 
182  SDL_Log("Test compare and exchange\n");
183 
184  b=SDL_AtomicCAS(&good, 500, 43);
185  SDL_assert(!b); /* no swap since CountTo!=500 */
186  v=SDL_AtomicGet(&good);
187  SDL_assert(v==CountTo); /* ensure no swap */
188 
189  b=SDL_AtomicCAS(&good, CountTo, 44);
190  SDL_assert(!!b); /* will swap */
191  v=SDL_AtomicGet(&good);
192  SDL_assert(v==44);
193 
194  SDL_Log("Test Add\n");
195 
196  v=SDL_AtomicAdd(&good, 1);
197  SDL_assert(v==44);
198  v=SDL_AtomicGet(&good);
199  SDL_assert(v==45);
200 
201  v=SDL_AtomicAdd(&good, 10);
202  SDL_assert(v==45);
203  v=SDL_AtomicGet(&good);
204  SDL_assert(v==55);
205 
206  SDL_Log("Test Add (Negative values)\n");
207 
208  v=SDL_AtomicAdd(&good, -20);
209  SDL_assert(v==55);
210  v=SDL_AtomicGet(&good);
211  SDL_assert(v==35);
212 
213  v=SDL_AtomicAdd(&good, -50); /* crossing zero down */
214  SDL_assert(v==35);
215  v=SDL_AtomicGet(&good);
216  SDL_assert(v==-15);
217 
218  v=SDL_AtomicAdd(&good, 30); /* crossing zero up */
219  SDL_assert(v==-15);
220  v=SDL_AtomicGet(&good);
221  SDL_assert(v==15);
222 
223  SDL_Log("Reset before count down test\n");
224  SDL_AtomicSet(&good, CountTo);
225  v=SDL_AtomicGet(&good);
226  SDL_assert(v==CountTo);
227 
228  bad=CountTo;
230 
231  SDL_Log("Counting down from %d, Expect %d remaining\n",CountTo,Expect);
232  runAdder();
233 
234  v=SDL_AtomicGet(&good);
235  SDL_Log("Atomic %d Non-Atomic %d\n",v,bad);
236  SDL_assert(v==Expect);
238 }
239 
240 /* End atomic operation test */
241 /**************************************************************************/
242 
243 /**************************************************************************/
244 /* Lock-free FIFO test */
245 
246 /* This is useful to test the impact of another thread locking the queue
247  entirely for heavy-weight manipulation.
248  */
249 #define TEST_SPINLOCK_FIFO
250 
251 #define NUM_READERS 4
252 #define NUM_WRITERS 4
253 #define EVENTS_PER_WRITER 1000000
254 
255 /* The number of entries must be a power of 2 */
256 #define MAX_ENTRIES 256
257 #define WRAP_MASK (MAX_ENTRIES-1)
258 
259 typedef struct
260 {
264 
265 typedef struct
266 {
268 
270 
272 
273  char cache_pad2[SDL_CACHELINE_SIZE-sizeof(SDL_atomic_t)];
274 
276 
277  char cache_pad3[SDL_CACHELINE_SIZE-sizeof(SDL_atomic_t)];
278 
279 #ifdef TEST_SPINLOCK_FIFO
283 
284  char cache_pad4[SDL_CACHELINE_SIZE-sizeof(SDL_SpinLock)-2*sizeof(SDL_atomic_t)];
285 #endif
286 
287  volatile SDL_bool active;
288 
289  /* Only needed for the mutex test */
291 
293 
294 static void InitEventQueue(SDL_EventQueue *queue)
295 {
296  int i;
297 
298  for (i = 0; i < MAX_ENTRIES; ++i) {
299  SDL_AtomicSet(&queue->entries[i].sequence, i);
300  }
301  SDL_AtomicSet(&queue->enqueue_pos, 0);
302  SDL_AtomicSet(&queue->dequeue_pos, 0);
303 #ifdef TEST_SPINLOCK_FIFO
304  queue->lock = 0;
305  SDL_AtomicSet(&queue->rwcount, 0);
306  SDL_AtomicSet(&queue->watcher, 0);
307 #endif
308  queue->active = SDL_TRUE;
309 }
310 
312 {
313  SDL_EventQueueEntry *entry;
314  unsigned queue_pos;
315  unsigned entry_seq;
316  int delta;
317  SDL_bool status;
318 
319 #ifdef TEST_SPINLOCK_FIFO
320  /* This is a gate so an external thread can lock the queue */
321  SDL_AtomicLock(&queue->lock);
322  SDL_assert(SDL_AtomicGet(&queue->watcher) == 0);
323  SDL_AtomicIncRef(&queue->rwcount);
324  SDL_AtomicUnlock(&queue->lock);
325 #endif
326 
327  queue_pos = (unsigned)SDL_AtomicGet(&queue->enqueue_pos);
328  for ( ; ; ) {
329  entry = &queue->entries[queue_pos & WRAP_MASK];
330  entry_seq = (unsigned)SDL_AtomicGet(&entry->sequence);
331 
332  delta = (int)(entry_seq - queue_pos);
333  if (delta == 0) {
334  /* The entry and the queue position match, try to increment the queue position */
335  if (SDL_AtomicCAS(&queue->enqueue_pos, (int)queue_pos, (int)(queue_pos+1))) {
336  /* We own the object, fill it! */
337  entry->event = *event;
338  SDL_AtomicSet(&entry->sequence, (int)(queue_pos + 1));
339  status = SDL_TRUE;
340  break;
341  }
342  } else if (delta < 0) {
343  /* We ran into an old queue entry, which means it still needs to be dequeued */
344  status = SDL_FALSE;
345  break;
346  } else {
347  /* We ran into a new queue entry, get the new queue position */
348  queue_pos = (unsigned)SDL_AtomicGet(&queue->enqueue_pos);
349  }
350  }
351 
352 #ifdef TEST_SPINLOCK_FIFO
353  SDL_AtomicDecRef(&queue->rwcount);
354 #endif
355  return status;
356 }
357 
359 {
360  SDL_EventQueueEntry *entry;
361  unsigned queue_pos;
362  unsigned entry_seq;
363  int delta;
364  SDL_bool status;
365 
366 #ifdef TEST_SPINLOCK_FIFO
367  /* This is a gate so an external thread can lock the queue */
368  SDL_AtomicLock(&queue->lock);
369  SDL_assert(SDL_AtomicGet(&queue->watcher) == 0);
370  SDL_AtomicIncRef(&queue->rwcount);
371  SDL_AtomicUnlock(&queue->lock);
372 #endif
373 
374  queue_pos = (unsigned)SDL_AtomicGet(&queue->dequeue_pos);
375  for ( ; ; ) {
376  entry = &queue->entries[queue_pos & WRAP_MASK];
377  entry_seq = (unsigned)SDL_AtomicGet(&entry->sequence);
378 
379  delta = (int)(entry_seq - (queue_pos + 1));
380  if (delta == 0) {
381  /* The entry and the queue position match, try to increment the queue position */
382  if (SDL_AtomicCAS(&queue->dequeue_pos, (int)queue_pos, (int)(queue_pos+1))) {
383  /* We own the object, fill it! */
384  *event = entry->event;
385  SDL_AtomicSet(&entry->sequence, (int)(queue_pos+MAX_ENTRIES));
386  status = SDL_TRUE;
387  break;
388  }
389  } else if (delta < 0) {
390  /* We ran into an old queue entry, which means we've hit empty */
391  status = SDL_FALSE;
392  break;
393  } else {
394  /* We ran into a new queue entry, get the new queue position */
395  queue_pos = (unsigned)SDL_AtomicGet(&queue->dequeue_pos);
396  }
397  }
398 
399 #ifdef TEST_SPINLOCK_FIFO
400  SDL_AtomicDecRef(&queue->rwcount);
401 #endif
402  return status;
403 }
404 
406 {
407  SDL_EventQueueEntry *entry;
408  unsigned queue_pos;
409  unsigned entry_seq;
410  int delta;
411  SDL_bool status = SDL_FALSE;
412 
413  SDL_LockMutex(queue->mutex);
414 
415  queue_pos = (unsigned)queue->enqueue_pos.value;
416  entry = &queue->entries[queue_pos & WRAP_MASK];
417  entry_seq = (unsigned)entry->sequence.value;
418 
419  delta = (int)(entry_seq - queue_pos);
420  if (delta == 0) {
421  ++queue->enqueue_pos.value;
422 
423  /* We own the object, fill it! */
424  entry->event = *event;
425  entry->sequence.value = (int)(queue_pos + 1);
426  status = SDL_TRUE;
427  } else if (delta < 0) {
428  /* We ran into an old queue entry, which means it still needs to be dequeued */
429  } else {
430  SDL_Log("ERROR: mutex failed!\n");
431  }
432 
433  SDL_UnlockMutex(queue->mutex);
434 
435  return status;
436 }
437 
439 {
440  SDL_EventQueueEntry *entry;
441  unsigned queue_pos;
442  unsigned entry_seq;
443  int delta;
444  SDL_bool status = SDL_FALSE;
445 
446  SDL_LockMutex(queue->mutex);
447 
448  queue_pos = (unsigned)queue->dequeue_pos.value;
449  entry = &queue->entries[queue_pos & WRAP_MASK];
450  entry_seq = (unsigned)entry->sequence.value;
451 
452  delta = (int)(entry_seq - (queue_pos + 1));
453  if (delta == 0) {
454  ++queue->dequeue_pos.value;
455 
456  /* We own the object, fill it! */
457  *event = entry->event;
458  entry->sequence.value = (int)(queue_pos + MAX_ENTRIES);
459  status = SDL_TRUE;
460  } else if (delta < 0) {
461  /* We ran into an old queue entry, which means we've hit empty */
462  } else {
463  SDL_Log("ERROR: mutex failed!\n");
464  }
465 
466  SDL_UnlockMutex(queue->mutex);
467 
468  return status;
469 }
470 
471 static SDL_sem *writersDone;
472 static SDL_sem *readersDone;
475 
476 typedef struct
477 {
479  int index;
480  char padding1[SDL_CACHELINE_SIZE-(sizeof(SDL_EventQueue*)+sizeof(int))%SDL_CACHELINE_SIZE];
481  int waits;
483  char padding2[SDL_CACHELINE_SIZE-sizeof(int)-sizeof(SDL_bool)];
484 } WriterData;
485 
486 typedef struct
487 {
490  int waits;
492  char padding[SDL_CACHELINE_SIZE-(sizeof(SDL_EventQueue*)+sizeof(int)*NUM_WRITERS+sizeof(int)+sizeof(SDL_bool))%SDL_CACHELINE_SIZE];
493 } ReaderData;
494 
495 static int FIFO_Writer(void* _data)
496 {
497  WriterData *data = (WriterData *)_data;
498  SDL_EventQueue *queue = data->queue;
499  int i;
501 
502  event.type = SDL_USEREVENT;
503  event.user.windowID = 0;
504  event.user.code = 0;
505  event.user.data1 = data;
506  event.user.data2 = NULL;
507 
508  if (data->lock_free) {
509  for (i = 0; i < EVENTS_PER_WRITER; ++i) {
510  event.user.code = i;
511  while (!EnqueueEvent_LockFree(queue, &event)) {
512  ++data->waits;
513  SDL_Delay(0);
514  }
515  }
516  } else {
517  for (i = 0; i < EVENTS_PER_WRITER; ++i) {
518  event.user.code = i;
519  while (!EnqueueEvent_Mutex(queue, &event)) {
520  ++data->waits;
521  SDL_Delay(0);
522  }
523  }
524  }
525  SDL_AtomicAdd(&writersRunning, -1);
527  return 0;
528 }
529 
530 static int FIFO_Reader(void* _data)
531 {
532  ReaderData *data = (ReaderData *)_data;
533  SDL_EventQueue *queue = data->queue;
535 
536  if (data->lock_free) {
537  for ( ; ; ) {
538  if (DequeueEvent_LockFree(queue, &event)) {
539  WriterData *writer = (WriterData*)event.user.data1;
540  ++data->counters[writer->index];
541  } else if (queue->active) {
542  ++data->waits;
543  SDL_Delay(0);
544  } else {
545  /* We drained the queue, we're done! */
546  break;
547  }
548  }
549  } else {
550  for ( ; ; ) {
551  if (DequeueEvent_Mutex(queue, &event)) {
552  WriterData *writer = (WriterData*)event.user.data1;
553  ++data->counters[writer->index];
554  } else if (queue->active) {
555  ++data->waits;
556  SDL_Delay(0);
557  } else {
558  /* We drained the queue, we're done! */
559  break;
560  }
561  }
562  }
563  SDL_AtomicAdd(&readersRunning, -1);
565  return 0;
566 }
567 
568 #ifdef TEST_SPINLOCK_FIFO
569 /* This thread periodically locks the queue for no particular reason */
570 static int FIFO_Watcher(void* _data)
571 {
572  SDL_EventQueue *queue = (SDL_EventQueue *)_data;
573 
574  while (queue->active) {
575  SDL_AtomicLock(&queue->lock);
576  SDL_AtomicIncRef(&queue->watcher);
577  while (SDL_AtomicGet(&queue->rwcount) > 0) {
578  SDL_Delay(0);
579  }
580  /* Do queue manipulation here... */
581  SDL_AtomicDecRef(&queue->watcher);
582  SDL_AtomicUnlock(&queue->lock);
583 
584  /* Wait a bit... */
585  SDL_Delay(1);
586  }
587  return 0;
588 }
589 #endif /* TEST_SPINLOCK_FIFO */
590 
591 static void RunFIFOTest(SDL_bool lock_free)
592 {
593  SDL_EventQueue queue;
594  WriterData writerData[NUM_WRITERS];
595  ReaderData readerData[NUM_READERS];
596  Uint32 start, end;
597  int i, j;
598  int grand_total;
599  char textBuffer[1024];
600  int len;
601 
602  SDL_Log("\nFIFO test---------------------------------------\n\n");
603  SDL_Log("Mode: %s\n", lock_free ? "LockFree" : "Mutex");
604 
607 
608  SDL_memset(&queue, 0xff, sizeof(queue));
609 
610  InitEventQueue(&queue);
611  if (!lock_free) {
612  queue.mutex = SDL_CreateMutex();
613  }
614 
615  start = SDL_GetTicks();
616 
617 #ifdef TEST_SPINLOCK_FIFO
618  /* Start a monitoring thread */
619  if (lock_free) {
620  SDL_CreateThread(FIFO_Watcher, "FIFOWatcher", &queue);
621  }
622 #endif
623 
624  /* Start the readers first */
625  SDL_Log("Starting %d readers\n", NUM_READERS);
626  SDL_zero(readerData);
627  SDL_AtomicSet(&readersRunning, NUM_READERS);
628  for (i = 0; i < NUM_READERS; ++i) {
629  char name[64];
630  SDL_snprintf(name, sizeof (name), "FIFOReader%d", i);
631  readerData[i].queue = &queue;
632  readerData[i].lock_free = lock_free;
633  SDL_CreateThread(FIFO_Reader, name, &readerData[i]);
634  }
635 
636  /* Start up the writers */
637  SDL_Log("Starting %d writers\n", NUM_WRITERS);
638  SDL_zero(writerData);
639  SDL_AtomicSet(&writersRunning, NUM_WRITERS);
640  for (i = 0; i < NUM_WRITERS; ++i) {
641  char name[64];
642  SDL_snprintf(name, sizeof (name), "FIFOWriter%d", i);
643  writerData[i].queue = &queue;
644  writerData[i].index = i;
645  writerData[i].lock_free = lock_free;
646  SDL_CreateThread(FIFO_Writer, name, &writerData[i]);
647  }
648 
649  /* Wait for the writers */
650  while (SDL_AtomicGet(&writersRunning) > 0) {
652  }
653 
654  /* Shut down the queue so readers exit */
655  queue.active = SDL_FALSE;
656 
657  /* Wait for the readers */
658  while (SDL_AtomicGet(&readersRunning) > 0) {
660  }
661 
662  end = SDL_GetTicks();
663 
666 
667  if (!lock_free) {
668  SDL_DestroyMutex(queue.mutex);
669  }
670 
671  SDL_Log("Finished in %f sec\n", (end - start) / 1000.f);
672 
673  SDL_Log("\n");
674  for (i = 0; i < NUM_WRITERS; ++i) {
675  SDL_Log("Writer %d wrote %d events, had %d waits\n", i, EVENTS_PER_WRITER, writerData[i].waits);
676  }
677  SDL_Log("Writers wrote %d total events\n", NUM_WRITERS*EVENTS_PER_WRITER);
678 
679  /* Print a breakdown of which readers read messages from which writer */
680  SDL_Log("\n");
681  grand_total = 0;
682  for (i = 0; i < NUM_READERS; ++i) {
683  int total = 0;
684  for (j = 0; j < NUM_WRITERS; ++j) {
685  total += readerData[i].counters[j];
686  }
687  grand_total += total;
688  SDL_Log("Reader %d read %d events, had %d waits\n", i, total, readerData[i].waits);
689  SDL_snprintf(textBuffer, sizeof(textBuffer), " { ");
690  for (j = 0; j < NUM_WRITERS; ++j) {
691  if (j > 0) {
692  len = SDL_strlen(textBuffer);
693  SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, ", ");
694  }
695  len = SDL_strlen(textBuffer);
696  SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, "%d", readerData[i].counters[j]);
697  }
698  len = SDL_strlen(textBuffer);
699  SDL_snprintf(textBuffer + len, sizeof(textBuffer) - len, " }\n");
700  SDL_Log("%s", textBuffer);
701  }
702  SDL_Log("Readers read %d total events\n", grand_total);
703 }
704 
705 /* End FIFO test */
706 /**************************************************************************/
707 
708 int
709 main(int argc, char *argv[])
710 {
711  /* Enable standard application logging */
713 
714  RunBasicTest();
715  RunEpicTest();
716 /* This test is really slow, so don't run it by default */
717 #if 0
719 #endif
721  return 0;
722 }
723 
724 /* vi: set ts=4 sw=4 expandtab: */
void * data1
Definition: SDL_events.h:497
static SDL_bool DequeueEvent_Mutex(SDL_EventQueue *queue, SDL_Event *event)
Definition: testatomic.c:438
#define SDL_LockMutex
SDL_EventQueue * queue
Definition: testatomic.c:488
static SDL_sem * readersDone
Definition: testatomic.c:472
SDL_bool lock_free
Definition: testatomic.c:482
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:155
SDL_atomic_t dequeue_pos
Definition: testatomic.c:275
#define SDL_AtomicLock
A type representing an atomic integer value. It is a struct so people don&#39;t accidentally use numeric ...
Definition: SDL_atomic.h:189
#define SDL_AtomicCAS
static void InitEventQueue(SDL_EventQueue *queue)
Definition: testatomic.c:294
#define SDL_CreateSemaphore
#define atomicValue
Definition: testatomic.c:101
SDL_SpinLock lock
Definition: testatomic.c:280
GLuint GLuint end
Definition: SDL_opengl.h:1564
#define SDL_CreateMutex
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
static SDL_bool EnqueueEvent_LockFree(SDL_EventQueue *queue, const SDL_Event *event)
Definition: testatomic.c:311
int main(int argc, char *argv[])
Definition: testatomic.c:709
GLfloat f
static int FIFO_Writer(void *_data)
Definition: testatomic.c:495
GLuint start
Definition: SDL_opengl.h:1564
static SDL_atomic_t writersRunning
Definition: testatomic.c:473
static char * tf(SDL_bool tf)
Definition: testatomic.c:23
GLuint const GLchar * name
static int adder(void *junk)
Definition: testatomic.c:117
#define NInter
Definition: testatomic.c:103
#define CountTo
Definition: testatomic.c:102
#define NThreads
Definition: testatomic.c:97
GLsizeiptr size
GLenum GLsizei len
GLint GLint GLsizei GLuint * counters
static const double T[]
Definition: k_tan.c:53
SDL_bool lock_free
Definition: testatomic.c:491
volatile SDL_bool active
Definition: testatomic.c:287
#define SDL_SemPost
#define SDL_AtomicUnlock
SDL_bool
Definition: SDL_stdinc.h:126
const GLdouble * v
Definition: SDL_opengl.h:2057
#define SDL_Log
SDL_EventQueueEntry entries[MAX_ENTRIES]
Definition: testatomic.c:267
static void RunBasicTest()
Definition: testatomic.c:37
static SDL_bool DequeueEvent_LockFree(SDL_EventQueue *queue, SDL_Event *event)
Definition: testatomic.c:358
static SDL_atomic_t readersRunning
Definition: testatomic.c:474
SDL_mutex * mutex
Definition: testatomic.c:290
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define MAX_ENTRIES
Definition: testatomic.c:256
GLsizei const GLfloat * value
struct _cl_event * event
#define SDL_CACHELINE_SIZE
Definition: SDL_cpuinfo.h:77
SDL_EventQueue * queue
Definition: testatomic.c:478
#define SDL_zero(x)
Definition: SDL_stdinc.h:355
SDL_Event event
Definition: testatomic.c:262
SDL_atomic_t sequence
Definition: testatomic.c:261
static SDL_bool EnqueueEvent_Mutex(SDL_EventQueue *queue, const SDL_Event *event)
Definition: testatomic.c:405
#define SDL_AtomicIncRef(a)
Increment an atomic variable used as a reference count.
Definition: SDL_atomic.h:225
static SDL_atomic_t good
Definition: testatomic.c:108
#define SDL_CreateThread
#define SDL_Delay
SDL_atomic_t watcher
Definition: testatomic.c:282
#define NUM_WRITERS
Definition: testatomic.c:252
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:42
#define SDL_assert(condition)
Definition: SDL_assert.h:167
static SDL_sem * threadDone
Definition: testatomic.c:114
#define SDL_LogSetPriority
int counters[NUM_WRITERS]
Definition: testatomic.c:489
#define NULL
Definition: begin_code.h:143
#define SDL_AtomicAdd
static int FIFO_Watcher(void *_data)
Definition: testatomic.c:570
static void runAdder(void)
Definition: testatomic.c:131
#define SDL_DestroyMutex
#define EVENTS_PER_WRITER
Definition: testatomic.c:253
SDL_mutex * lock
Definition: SDL_events.c:75
#define SDL_strlen
SDL_COMPILE_TIME_ASSERT(size, CountTo >0)
static SDL_sem * writersDone
Definition: testatomic.c:471
#define SDL_SemWait
#define SDL_AtomicDecRef(a)
Decrement an atomic variable used as a reference count.
Definition: SDL_atomic.h:235
#define SDL_DestroySemaphore
#define SDL_AtomicSet
static SDL_atomic_t threadsRunning
Definition: testatomic.c:112
#define SDL_AtomicGet
#define CountInc
Definition: testatomic.c:98
#define SDL_snprintf
SDL_atomic_t rwcount
Definition: testatomic.c:281
#define SDL_UnlockMutex
General event structure.
Definition: SDL_events.h:521
SDL_UserEvent user
Definition: SDL_events.h:542
int SDL_SpinLock
Definition: SDL_atomic.h:89
static void RunEpicTest()
Definition: testatomic.c:156
static atomicValue bad
Definition: testatomic.c:110
static int FIFO_Reader(void *_data)
Definition: testatomic.c:530
#define Expect
Definition: testatomic.c:104
GLboolean GLboolean GLboolean b
#define WRAP_MASK
Definition: testatomic.c:257
SDL_atomic_t enqueue_pos
Definition: testatomic.c:271
static void RunFIFOTest(SDL_bool lock_free)
Definition: testatomic.c:591
GLdouble GLdouble t
Definition: SDL_opengl.h:2064
#define SDL_memset
#define NUM_READERS
Definition: testatomic.c:251
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:42
Definition: testatomic.c:259