SDL  2.0
testatomic.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 1997-2018 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 enum {
107  CountTo_GreaterThanZero = CountTo > 0,
108 };
109 SDL_COMPILE_TIME_ASSERT(size, CountTo_GreaterThanZero); /* check for rollover */
110 
111 static SDL_atomic_t good = { 42 };
112 
113 static atomicValue bad = 42;
114 
116 
117 static SDL_sem *threadDone;
118 
119 static
120 int SDLCALL adder(void* junk)
121 {
122  unsigned long N=NInter;
123  SDL_Log("Thread subtracting %d %lu times\n",CountInc,N);
124  while (N--) {
125  SDL_AtomicAdd(&good, -CountInc);
126  bad-=CountInc;
127  }
128  SDL_AtomicAdd(&threadsRunning, -1);
130  return 0;
131 }
132 
133 static
134 void runAdder(void)
135 {
136  Uint32 start, end;
137  int T=NThreads;
138 
139  start = SDL_GetTicks();
140 
142 
143  SDL_AtomicSet(&threadsRunning, NThreads);
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 }
157 
158 static
160 {
161  int b;
162  atomicValue v;
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");
170  v=SDL_AtomicGet(&good);
171  SDL_assert(v==42);
172 
173  SDL_assert(bad==42);
174 
175  SDL_Log("Test negative values\n");
176  SDL_AtomicSet(&good, -5);
177  v=SDL_AtomicGet(&good);
178  SDL_assert(v==-5);
179 
180  SDL_Log("Verify maximum value\n");
181  SDL_AtomicSet(&good, CountTo);
182  v=SDL_AtomicGet(&good);
183  SDL_assert(v==CountTo);
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 */
189  v=SDL_AtomicGet(&good);
190  SDL_assert(v==CountTo); /* ensure no swap */
191 
192  b=SDL_AtomicCAS(&good, CountTo, 44);
193  SDL_assert(!!b); /* will swap */
194  v=SDL_AtomicGet(&good);
195  SDL_assert(v==44);
196 
197  SDL_Log("Test Add\n");
198 
199  v=SDL_AtomicAdd(&good, 1);
200  SDL_assert(v==44);
201  v=SDL_AtomicGet(&good);
202  SDL_assert(v==45);
203 
204  v=SDL_AtomicAdd(&good, 10);
205  SDL_assert(v==45);
206  v=SDL_AtomicGet(&good);
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);
213  v=SDL_AtomicGet(&good);
214  SDL_assert(v==35);
215 
216  v=SDL_AtomicAdd(&good, -50); /* crossing zero down */
217  SDL_assert(v==35);
218  v=SDL_AtomicGet(&good);
219  SDL_assert(v==-15);
220 
221  v=SDL_AtomicAdd(&good, 30); /* crossing zero up */
222  SDL_assert(v==-15);
223  v=SDL_AtomicGet(&good);
224  SDL_assert(v==15);
225 
226  SDL_Log("Reset before count down test\n");
227  SDL_AtomicSet(&good, CountTo);
228  v=SDL_AtomicGet(&good);
229  SDL_assert(v==CountTo);
230 
231  bad=CountTo;
233 
234  SDL_Log("Counting down from %d, Expect %d remaining\n",CountTo,Expect);
235  runAdder();
236 
237  v=SDL_AtomicGet(&good);
238  SDL_Log("Atomic %d Non-Atomic %d\n",v,bad);
239  SDL_assert(v==Expect);
241 }
242 
243 /* End atomic operation test */
244 /**************************************************************************/
245 
246 /**************************************************************************/
247 /* Lock-free FIFO test */
248 
249 /* This is useful to test the impact of another thread locking the queue
250  entirely for heavy-weight manipulation.
251  */
252 #define TEST_SPINLOCK_FIFO
253 
254 #define NUM_READERS 4
255 #define NUM_WRITERS 4
256 #define EVENTS_PER_WRITER 1000000
257 
258 /* The number of entries must be a power of 2 */
259 #define MAX_ENTRIES 256
260 #define WRAP_MASK (MAX_ENTRIES-1)
261 
262 typedef struct
263 {
267 
268 typedef struct
269 {
271 
273 
275 
276  char cache_pad2[SDL_CACHELINE_SIZE-sizeof(SDL_atomic_t)];
277 
279 
280  char cache_pad3[SDL_CACHELINE_SIZE-sizeof(SDL_atomic_t)];
281 
282 #ifdef TEST_SPINLOCK_FIFO
286 
287  char cache_pad4[SDL_CACHELINE_SIZE-sizeof(SDL_SpinLock)-2*sizeof(SDL_atomic_t)];
288 #endif
289 
291 
292  /* Only needed for the mutex test */
294 
296 
297 static void InitEventQueue(SDL_EventQueue *queue)
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 }
313 
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 }
360 
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 }
407 
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 }
440 
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 }
473 
474 static SDL_sem *writersDone;
475 static SDL_sem *readersDone;
478 
479 typedef struct
480 {
482  int index;
483  char padding1[SDL_CACHELINE_SIZE-(sizeof(SDL_EventQueue*)+sizeof(int))%SDL_CACHELINE_SIZE];
484  int waits;
486  char padding2[SDL_CACHELINE_SIZE-sizeof(int)-sizeof(SDL_bool)];
487 } WriterData;
488 
489 typedef struct
490 {
493  int waits;
495  char padding[SDL_CACHELINE_SIZE-(sizeof(SDL_EventQueue*)+sizeof(int)*NUM_WRITERS+sizeof(int)+sizeof(SDL_bool))%SDL_CACHELINE_SIZE];
496 } ReaderData;
497 
498 static int SDLCALL FIFO_Writer(void* _data)
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  }
528  SDL_AtomicAdd(&writersRunning, -1);
530  return 0;
531 }
532 
533 static int SDLCALL FIFO_Reader(void* _data)
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  }
566  SDL_AtomicAdd(&readersRunning, -1);
568  return 0;
569 }
570 
571 #ifdef TEST_SPINLOCK_FIFO
572 /* This thread periodically locks the queue for no particular reason */
573 static int SDLCALL FIFO_Watcher(void* _data)
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 }
592 #endif /* TEST_SPINLOCK_FIFO */
593 
594 static void RunFIFOTest(SDL_bool lock_free)
595 {
596  SDL_EventQueue queue;
597  WriterData writerData[NUM_WRITERS];
598  ReaderData readerData[NUM_READERS];
599  Uint32 start, end;
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 
618  start = SDL_GetTicks();
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);
630  SDL_AtomicSet(&readersRunning, NUM_READERS);
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);
642  SDL_AtomicSet(&writersRunning, NUM_WRITERS);
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 }
707 
708 /* End FIFO test */
709 /**************************************************************************/
710 
711 int
712 main(int argc, char *argv[])
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 }
726 
727 /* vi: set ts=4 sw=4 expandtab: */
void * data1
Definition: SDL_events.h:501
static SDL_bool DequeueEvent_Mutex(SDL_EventQueue *queue, SDL_Event *event)
Definition: testatomic.c:441
#define SDL_LockMutex
SDL_EventQueue * queue
Definition: testatomic.c:491
static SDL_sem * readersDone
Definition: testatomic.c:475
SDL_bool lock_free
Definition: testatomic.c:485
SDL_atomic_t dequeue_pos
Definition: testatomic.c:278
const GLdouble * v
Definition: SDL_opengl.h:2064
#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:198
#define SDL_AtomicCAS
static void InitEventQueue(SDL_EventQueue *queue)
Definition: testatomic.c:297
#define SDL_CreateSemaphore
#define atomicValue
Definition: testatomic.c:101
SDL_SpinLock lock
Definition: testatomic.c:283
GLuint GLuint end
Definition: SDL_opengl.h:1571
#define SDL_CreateMutex
static SDL_bool EnqueueEvent_LockFree(SDL_EventQueue *queue, const SDL_Event *event)
Definition: testatomic.c:314
int main(int argc, char *argv[])
Definition: testatomic.c:712
GLfloat f
static int FIFO_Writer(void *_data)
Definition: testatomic.c:498
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLuint start
Definition: SDL_opengl.h:1571
static SDL_atomic_t writersRunning
Definition: testatomic.c:476
static char * tf(SDL_bool tf)
Definition: testatomic.c:23
uint32_t Uint32
Definition: SDL_stdinc.h:181
static int adder(void *junk)
Definition: testatomic.c:120
#define NInter
Definition: testatomic.c:103
#define CountTo
Definition: testatomic.c:102
#define NThreads
Definition: testatomic.c:97
GLenum GLsizei len
GLint GLint GLsizei GLuint * counters
GLuint const GLchar * name
static const double T[]
Definition: k_tan.c:53
SDL_bool lock_free
Definition: testatomic.c:494
#define SDL_SemPost
#define SDL_AtomicUnlock
#define SDL_Log
SDL_EventQueueEntry entries[MAX_ENTRIES]
Definition: testatomic.c:270
static void RunBasicTest()
Definition: testatomic.c:37
static SDL_bool DequeueEvent_LockFree(SDL_EventQueue *queue, SDL_Event *event)
Definition: testatomic.c:361
static SDL_atomic_t readersRunning
Definition: testatomic.c:477
SDL_mutex * mutex
Definition: testatomic.c:293
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define MAX_ENTRIES
Definition: testatomic.c:259
struct _cl_event * event
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
#define SDL_CACHELINE_SIZE
Definition: SDL_cpuinfo.h:92
GLsizei const GLfloat * value
SDL_EventQueue * queue
Definition: testatomic.c:481
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_Event event
Definition: testatomic.c:265
SDL_COMPILE_TIME_ASSERT(size, CountTo_GreaterThanZero)
SDL_atomic_t sequence
Definition: testatomic.c:264
static SDL_bool EnqueueEvent_Mutex(SDL_EventQueue *queue, const SDL_Event *event)
Definition: testatomic.c:408
#define SDL_AtomicIncRef(a)
Increment an atomic variable used as a reference count.
Definition: SDL_atomic.h:234
static SDL_atomic_t good
Definition: testatomic.c:111
GLsizeiptr size
#define SDL_CreateThread
#define SDL_Delay
SDL_atomic_t watcher
Definition: testatomic.c:285
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 NUM_WRITERS
Definition: testatomic.c:255
#define SDL_assert(condition)
Definition: SDL_assert.h:169
static SDL_sem * threadDone
Definition: testatomic.c:117
#define SDL_LogSetPriority
int counters[NUM_WRITERS]
Definition: testatomic.c:492
#define NULL
Definition: begin_code.h:164
#define SDL_AtomicAdd
SDL_bool
Definition: SDL_stdinc.h:139
static int FIFO_Watcher(void *_data)
Definition: testatomic.c:573
static void runAdder(void)
Definition: testatomic.c:134
#define SDL_DestroyMutex
#define EVENTS_PER_WRITER
Definition: testatomic.c:256
SDL_mutex * lock
Definition: SDL_events.c:78
#define SDL_strlen
static SDL_sem * writersDone
Definition: testatomic.c:474
#define SDL_SemWait
#define SDL_AtomicDecRef(a)
Decrement an atomic variable used as a reference count.
Definition: SDL_atomic.h:244
#define SDL_DestroySemaphore
#define SDL_AtomicSet
static SDL_atomic_t threadsRunning
Definition: testatomic.c:115
#define SDL_AtomicGet
#define CountInc
Definition: testatomic.c:98
#define SDL_snprintf
SDL_atomic_t rwcount
Definition: testatomic.c:284
#define SDL_UnlockMutex
General event structure.
Definition: SDL_events.h:525
SDL_UserEvent user
Definition: SDL_events.h:546
int SDL_SpinLock
Definition: SDL_atomic.h:89
static void RunEpicTest()
Definition: testatomic.c:159
static atomicValue bad
Definition: testatomic.c:113
static int FIFO_Reader(void *_data)
Definition: testatomic.c:533
#define Expect
Definition: testatomic.c:104
SDL_atomic_t active
Definition: testatomic.c:290
#define SDLCALL
Definition: SDL_internal.h:45
GLboolean GLboolean GLboolean b
#define WRAP_MASK
Definition: testatomic.c:260
SDL_atomic_t enqueue_pos
Definition: testatomic.c:274
static void RunFIFOTest(SDL_bool lock_free)
Definition: testatomic.c:594
GLdouble GLdouble t
Definition: SDL_opengl.h:2071
#define SDL_memset
#define NUM_READERS
Definition: testatomic.c:254
Definition: testatomic.c:262