Remove almost all instances of "volatile" keyword.
authorRyan C. Gordon <icculus@icculus.org>
Sun, 03 Jan 2016 06:50:50 -0500
changeset 10003d91a2c45825e
parent 10002 c9cce8633f13
child 10004 8f2f519d1e61
Remove almost all instances of "volatile" keyword.

As Tiffany pointed out in Bugzilla, volatile is not useful for thread safety:

https://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/

Some of these volatiles didn't need to be, some were otherwise protected by
spinlocks or mutexes, and some got moved over to SDL_atomic_t data, etc.

Fixes Bugzilla #3220.
src/dynapi/SDL_dynapi.c
src/events/SDL_events.c
src/haptic/windows/SDL_windowshaptic.c
src/haptic/windows/SDL_windowshaptic_c.h
src/haptic/windows/SDL_xinputhaptic.c
src/timer/SDL_timer.c
src/video/android/SDL_androidtouch.c
test/testatomic.c
test/testlock.c
test/testmultiaudio.c
test/torturethread.c
     1.1 --- a/src/dynapi/SDL_dynapi.c	Sat Jan 02 12:17:33 2016 -0800
     1.2 +++ b/src/dynapi/SDL_dynapi.c	Sun Jan 03 06:50:50 2016 -0500
     1.3 @@ -293,7 +293,7 @@
     1.4       *  SDL_CreateThread() would also call this function before building the
     1.5       *  new thread).
     1.6       */
     1.7 -    static volatile SDL_bool already_initialized = SDL_FALSE;
     1.8 +    static SDL_bool already_initialized = SDL_FALSE;
     1.9  
    1.10      /* SDL_AtomicLock calls SDL mutex functions to emulate if
    1.11         SDL_ATOMIC_DISABLED, which we can't do here, so in such a
     2.1 --- a/src/events/SDL_events.c	Sat Jan 02 12:17:33 2016 -0800
     2.2 +++ b/src/events/SDL_events.c	Sun Jan 03 06:50:50 2016 -0500
     2.3 @@ -73,15 +73,15 @@
     2.4  static struct
     2.5  {
     2.6      SDL_mutex *lock;
     2.7 -    volatile SDL_bool active;
     2.8 -    volatile int count;
     2.9 -    volatile int max_events_seen;
    2.10 +    SDL_atomic_t active;
    2.11 +    SDL_atomic_t count;
    2.12 +    int max_events_seen;
    2.13      SDL_EventEntry *head;
    2.14      SDL_EventEntry *tail;
    2.15      SDL_EventEntry *free;
    2.16      SDL_SysWMEntry *wmmsg_used;
    2.17      SDL_SysWMEntry *wmmsg_free;
    2.18 -} SDL_EventQ = { NULL, SDL_TRUE, 0, 0, NULL, NULL, NULL, NULL, NULL };
    2.19 +} SDL_EventQ = { NULL, { 1 }, { 0 }, 0, NULL, NULL, NULL, NULL, NULL };
    2.20  
    2.21  
    2.22  /* Public functions */
    2.23 @@ -98,7 +98,7 @@
    2.24          SDL_LockMutex(SDL_EventQ.lock);
    2.25      }
    2.26  
    2.27 -    SDL_EventQ.active = SDL_FALSE;
    2.28 +    SDL_AtomicSet(&SDL_EventQ.active, 0);
    2.29  
    2.30      if (report && SDL_atoi(report)) {
    2.31          SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d\n",
    2.32 @@ -127,7 +127,7 @@
    2.33          wmmsg = next;
    2.34      }
    2.35  
    2.36 -    SDL_EventQ.count = 0;
    2.37 +    SDL_AtomicSet(&SDL_EventQ.count, 0);
    2.38      SDL_EventQ.max_events_seen = 0;
    2.39      SDL_EventQ.head = NULL;
    2.40      SDL_EventQ.tail = NULL;
    2.41 @@ -171,7 +171,7 @@
    2.42          SDL_EventQ.lock = SDL_CreateMutex();
    2.43      }
    2.44      if (SDL_EventQ.lock == NULL) {
    2.45 -        return (-1);
    2.46 +        return -1;
    2.47      }
    2.48  #endif /* !SDL_THREADS_DISABLED */
    2.49  
    2.50 @@ -180,9 +180,9 @@
    2.51      SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
    2.52      SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
    2.53  
    2.54 -    SDL_EventQ.active = SDL_TRUE;
    2.55 +    SDL_AtomicSet(&SDL_EventQ.active, 1);
    2.56  
    2.57 -    return (0);
    2.58 +    return 0;
    2.59  }
    2.60  
    2.61  
    2.62 @@ -191,9 +191,11 @@
    2.63  SDL_AddEvent(SDL_Event * event)
    2.64  {
    2.65      SDL_EventEntry *entry;
    2.66 +    const int initial_count = SDL_AtomicGet(&SDL_EventQ.count);
    2.67 +    int final_count;
    2.68  
    2.69 -    if (SDL_EventQ.count >= SDL_MAX_QUEUED_EVENTS) {
    2.70 -        SDL_SetError("Event queue is full (%d events)", SDL_EventQ.count);
    2.71 +    if (initial_count >= SDL_MAX_QUEUED_EVENTS) {
    2.72 +        SDL_SetError("Event queue is full (%d events)", initial_count);
    2.73          return 0;
    2.74      }
    2.75  
    2.76 @@ -225,10 +227,10 @@
    2.77          entry->prev = NULL;
    2.78          entry->next = NULL;
    2.79      }
    2.80 -    ++SDL_EventQ.count;
    2.81  
    2.82 -    if (SDL_EventQ.count > SDL_EventQ.max_events_seen) {
    2.83 -        SDL_EventQ.max_events_seen = SDL_EventQ.count;
    2.84 +    final_count = SDL_AtomicAdd(&SDL_EventQ.count, 1) + 1;
    2.85 +    if (final_count > SDL_EventQ.max_events_seen) {
    2.86 +        SDL_EventQ.max_events_seen = final_count;
    2.87      }
    2.88  
    2.89      return 1;
    2.90 @@ -256,8 +258,8 @@
    2.91  
    2.92      entry->next = SDL_EventQ.free;
    2.93      SDL_EventQ.free = entry;
    2.94 -    SDL_assert(SDL_EventQ.count > 0);
    2.95 -    --SDL_EventQ.count;
    2.96 +    SDL_assert(SDL_AtomicGet(&SDL_EventQ.count) > 0);
    2.97 +    SDL_AtomicAdd(&SDL_EventQ.count, -1);
    2.98  }
    2.99  
   2.100  /* Lock the event queue, take a peep at it, and unlock it */
   2.101 @@ -268,7 +270,7 @@
   2.102      int i, used;
   2.103  
   2.104      /* Don't look after we've quit */
   2.105 -    if (!SDL_EventQ.active) {
   2.106 +    if (!SDL_AtomicGet(&SDL_EventQ.active)) {
   2.107          /* We get a few spurious events at shutdown, so don't warn then */
   2.108          if (action != SDL_ADDEVENT) {
   2.109              SDL_SetError("The event system has been shut down");
   2.110 @@ -363,7 +365,7 @@
   2.111  SDL_FlushEvents(Uint32 minType, Uint32 maxType)
   2.112  {
   2.113      /* Don't look after we've quit */
   2.114 -    if (!SDL_EventQ.active) {
   2.115 +    if (!SDL_AtomicGet(&SDL_EventQ.active)) {
   2.116          return;
   2.117      }
   2.118  
     3.1 --- a/src/haptic/windows/SDL_windowshaptic.c	Sat Jan 02 12:17:33 2016 -0800
     3.2 +++ b/src/haptic/windows/SDL_windowshaptic.c	Sun Jan 03 06:50:50 2016 -0500
     3.3 @@ -255,7 +255,7 @@
     3.4      for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
     3.5          if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
     3.6              /* we _have_ to stop the thread before we free the XInput DLL! */
     3.7 -            hapticitem->hwdata->stopThread = 1;
     3.8 +            SDL_AtomicSet(&hapticitem->hwdata->stopThread, 1);
     3.9              SDL_WaitThread(hapticitem->hwdata->thread, NULL);
    3.10              hapticitem->hwdata->thread = NULL;
    3.11          }
     4.1 --- a/src/haptic/windows/SDL_windowshaptic_c.h	Sat Jan 02 12:17:33 2016 -0800
     4.2 +++ b/src/haptic/windows/SDL_windowshaptic_c.h	Sun Jan 03 06:50:50 2016 -0500
     4.3 @@ -42,8 +42,8 @@
     4.4      Uint8 userid; /* XInput userid index for this joystick */
     4.5      SDL_Thread *thread;
     4.6      SDL_mutex *mutex;
     4.7 -    volatile Uint32 stopTicks;
     4.8 -    volatile int stopThread;
     4.9 +    Uint32 stopTicks;
    4.10 +    SDL_atomic_t stopThread;
    4.11  };
    4.12  
    4.13  
     5.1 --- a/src/haptic/windows/SDL_xinputhaptic.c	Sat Jan 02 12:17:33 2016 -0800
     5.2 +++ b/src/haptic/windows/SDL_xinputhaptic.c	Sun Jan 03 06:50:50 2016 -0500
     5.3 @@ -146,7 +146,7 @@
     5.4  {
     5.5      struct haptic_hwdata *hwdata = (struct haptic_hwdata *) arg;
     5.6  
     5.7 -    while (!hwdata->stopThread) {
     5.8 +    while (!SDL_AtomicGet(&hwdata->stopThread)) {
     5.9          SDL_Delay(50);
    5.10          SDL_LockMutex(hwdata->mutex);
    5.11          /* If we're currently running and need to stop... */
    5.12 @@ -261,7 +261,7 @@
    5.13  void
    5.14  SDL_XINPUT_HapticClose(SDL_Haptic * haptic)
    5.15  {
    5.16 -    haptic->hwdata->stopThread = 1;
    5.17 +    SDL_AtomicSet(&haptic->hwdata->stopThread, 1);
    5.18      SDL_WaitThread(haptic->hwdata->thread, NULL);
    5.19      SDL_DestroyMutex(haptic->hwdata->mutex);
    5.20  }
     6.1 --- a/src/timer/SDL_timer.c	Sat Jan 02 12:17:33 2016 -0800
     6.2 +++ b/src/timer/SDL_timer.c	Sun Jan 03 06:50:50 2016 -0500
     6.3 @@ -35,7 +35,7 @@
     6.4      void *param;
     6.5      Uint32 interval;
     6.6      Uint32 scheduled;
     6.7 -    volatile SDL_bool canceled;
     6.8 +    SDL_atomic_t canceled;
     6.9      struct _SDL_Timer *next;
    6.10  } SDL_Timer;
    6.11  
    6.12 @@ -60,9 +60,9 @@
    6.13      /* Data used to communicate with the timer thread */
    6.14      SDL_SpinLock lock;
    6.15      SDL_sem *sem;
    6.16 -    SDL_Timer * volatile pending;
    6.17 -    SDL_Timer * volatile freelist;
    6.18 -    volatile SDL_bool active;
    6.19 +    SDL_Timer *pending;
    6.20 +    SDL_Timer *freelist;
    6.21 +    SDL_atomic_t active;
    6.22  
    6.23      /* List of timers - this is only touched by the timer thread */
    6.24      SDL_Timer *timers;
    6.25 @@ -138,7 +138,7 @@
    6.26          freelist_tail = NULL;
    6.27  
    6.28          /* Check to see if we're still running, after maintenance */
    6.29 -        if (!data->active) {
    6.30 +        if (!SDL_AtomicGet(&data->active)) {
    6.31              break;
    6.32          }
    6.33  
    6.34 @@ -160,7 +160,7 @@
    6.35              /* We're going to do something with this timer */
    6.36              data->timers = current->next;
    6.37  
    6.38 -            if (current->canceled) {
    6.39 +            if (SDL_AtomicGet(&current->canceled)) {
    6.40                  interval = 0;
    6.41              } else {
    6.42                  interval = current->callback(current->interval, current->param);
    6.43 @@ -179,7 +179,7 @@
    6.44                  }
    6.45                  freelist_tail = current;
    6.46  
    6.47 -                current->canceled = SDL_TRUE;
    6.48 +                SDL_AtomicSet(&current->canceled, 1);
    6.49              }
    6.50          }
    6.51  
    6.52 @@ -207,7 +207,7 @@
    6.53  {
    6.54      SDL_TimerData *data = &SDL_timer_data;
    6.55  
    6.56 -    if (!data->active) {
    6.57 +    if (!SDL_AtomicGet(&data->active)) {
    6.58          const char *name = "SDLTimer";
    6.59          data->timermap_lock = SDL_CreateMutex();
    6.60          if (!data->timermap_lock) {
    6.61 @@ -220,7 +220,7 @@
    6.62              return -1;
    6.63          }
    6.64  
    6.65 -        data->active = SDL_TRUE;
    6.66 +        SDL_AtomicSet(&data->active, 1);
    6.67          /* !!! FIXME: this is nasty. */
    6.68  #if defined(__WIN32__) && !defined(HAVE_LIBC)
    6.69  #undef SDL_CreateThread
    6.70 @@ -249,9 +249,7 @@
    6.71      SDL_Timer *timer;
    6.72      SDL_TimerMap *entry;
    6.73  
    6.74 -    if (data->active) {
    6.75 -        data->active = SDL_FALSE;
    6.76 -
    6.77 +    if (SDL_AtomicCAS(&data->active, 1, 0)) {  /* active? Move to inactive. */
    6.78          /* Shutdown the timer thread */
    6.79          if (data->thread) {
    6.80              SDL_SemPost(data->sem);
    6.81 @@ -291,21 +289,14 @@
    6.82      SDL_Timer *timer;
    6.83      SDL_TimerMap *entry;
    6.84  
    6.85 -    if (!data->active) {
    6.86 -        int status = 0;
    6.87 -
    6.88 -        SDL_AtomicLock(&data->lock);
    6.89 -        if (!data->active) {
    6.90 -            status = SDL_TimerInit();
    6.91 -        }
    6.92 -        SDL_AtomicUnlock(&data->lock);
    6.93 -
    6.94 -        if (status < 0) {
    6.95 +    SDL_AtomicLock(&data->lock);
    6.96 +    if (!SDL_AtomicGet(&data->active)) {
    6.97 +        if (SDL_TimerInit() < 0) {
    6.98 +            SDL_AtomicUnlock(&data->lock);
    6.99              return 0;
   6.100          }
   6.101      }
   6.102  
   6.103 -    SDL_AtomicLock(&data->lock);
   6.104      timer = data->freelist;
   6.105      if (timer) {
   6.106          data->freelist = timer->next;
   6.107 @@ -326,7 +317,7 @@
   6.108      timer->param = param;
   6.109      timer->interval = interval;
   6.110      timer->scheduled = SDL_GetTicks() + interval;
   6.111 -    timer->canceled = SDL_FALSE;
   6.112 +    SDL_AtomicSet(&timer->canceled, 0);
   6.113  
   6.114      entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry));
   6.115      if (!entry) {
   6.116 @@ -377,8 +368,8 @@
   6.117      SDL_UnlockMutex(data->timermap_lock);
   6.118  
   6.119      if (entry) {
   6.120 -        if (!entry->timer->canceled) {
   6.121 -            entry->timer->canceled = SDL_TRUE;
   6.122 +        if (!SDL_AtomicGet(&entry->timer->canceled)) {
   6.123 +            SDL_AtomicSet(&entry->timer->canceled, 1);
   6.124              canceled = SDL_TRUE;
   6.125          }
   6.126          SDL_free(entry);
     7.1 --- a/src/video/android/SDL_androidtouch.c	Sat Jan 02 12:17:33 2016 -0800
     7.2 +++ b/src/video/android/SDL_androidtouch.c	Sun Jan 03 06:50:50 2016 -0500
     7.3 @@ -50,7 +50,7 @@
     7.4      *window_y = (int)(y * window_h);
     7.5  }
     7.6  
     7.7 -static volatile SDL_bool separate_mouse_and_touch = SDL_FALSE;
     7.8 +static SDL_bool separate_mouse_and_touch = SDL_FALSE;
     7.9  
    7.10  static void
    7.11  SeparateEventsHintWatcher(void *userdata, const char *name,
     8.1 --- a/test/testatomic.c	Sat Jan 02 12:17:33 2016 -0800
     8.2 +++ b/test/testatomic.c	Sun Jan 03 06:50:50 2016 -0500
     8.3 @@ -284,7 +284,7 @@
     8.4      char cache_pad4[SDL_CACHELINE_SIZE-sizeof(SDL_SpinLock)-2*sizeof(SDL_atomic_t)];
     8.5  #endif
     8.6  
     8.7 -    volatile SDL_bool active;
     8.8 +    SDL_atomic_t active;
     8.9  
    8.10      /* Only needed for the mutex test */
    8.11      SDL_mutex *mutex;
    8.12 @@ -305,7 +305,7 @@
    8.13      SDL_AtomicSet(&queue->rwcount, 0);
    8.14      SDL_AtomicSet(&queue->watcher, 0);
    8.15  #endif
    8.16 -    queue->active = SDL_TRUE;
    8.17 +    SDL_AtomicSet(&queue->active, 1);
    8.18  }
    8.19  
    8.20  static SDL_bool EnqueueEvent_LockFree(SDL_EventQueue *queue, const SDL_Event *event)
    8.21 @@ -538,7 +538,7 @@
    8.22              if (DequeueEvent_LockFree(queue, &event)) {
    8.23                  WriterData *writer = (WriterData*)event.user.data1;
    8.24                  ++data->counters[writer->index];
    8.25 -            } else if (queue->active) {
    8.26 +            } else if (SDL_AtomicGet(&queue->active)) {
    8.27                  ++data->waits;
    8.28                  SDL_Delay(0);
    8.29              } else {
    8.30 @@ -551,7 +551,7 @@
    8.31              if (DequeueEvent_Mutex(queue, &event)) {
    8.32                  WriterData *writer = (WriterData*)event.user.data1;
    8.33                  ++data->counters[writer->index];
    8.34 -            } else if (queue->active) {
    8.35 +            } else if (SDL_AtomicGet(&queue->active)) {
    8.36                  ++data->waits;
    8.37                  SDL_Delay(0);
    8.38              } else {
    8.39 @@ -571,7 +571,7 @@
    8.40  {
    8.41      SDL_EventQueue *queue = (SDL_EventQueue *)_data;
    8.42  
    8.43 -    while (queue->active) {
    8.44 +    while (SDL_AtomicGet(&queue->active)) {
    8.45          SDL_AtomicLock(&queue->lock);
    8.46          SDL_AtomicIncRef(&queue->watcher);
    8.47          while (SDL_AtomicGet(&queue->rwcount) > 0) {
    8.48 @@ -652,7 +652,7 @@
    8.49      }
    8.50  
    8.51      /* Shut down the queue so readers exit */
    8.52 -    queue.active = SDL_FALSE;
    8.53 +    SDL_AtomicSet(&queue.active, 0);
    8.54  
    8.55      /* Wait for the readers */
    8.56      while (SDL_AtomicGet(&readersRunning) > 0) {
     9.1 --- a/test/testlock.c	Sat Jan 02 12:17:33 2016 -0800
     9.2 +++ b/test/testlock.c	Sun Jan 03 06:50:50 2016 -0500
     9.3 @@ -23,7 +23,7 @@
     9.4  static SDL_mutex *mutex = NULL;
     9.5  static SDL_threadID mainthread;
     9.6  static SDL_Thread *threads[6];
     9.7 -static volatile int doterminate = 0;
     9.8 +static SDL_atomic_t doterminate;
     9.9  
    9.10  /*
    9.11   * SDL_Quit() shouldn't be used with atexit() directly because
    9.12 @@ -45,7 +45,7 @@
    9.13  terminate(int sig)
    9.14  {
    9.15      signal(SIGINT, terminate);
    9.16 -    doterminate = 1;
    9.17 +    SDL_AtomicSet(&doterminate, 1);
    9.18  }
    9.19  
    9.20  void
    9.21 @@ -54,7 +54,7 @@
    9.22      SDL_threadID id = SDL_ThreadID();
    9.23      int i;
    9.24      SDL_Log("Process %lu:  Cleaning up...\n", id == mainthread ? 0 : id);
    9.25 -    doterminate = 1;
    9.26 +    SDL_AtomicSet(&doterminate, 1);
    9.27      for (i = 0; i < 6; ++i)
    9.28          SDL_WaitThread(threads[i], NULL);
    9.29      SDL_DestroyMutex(mutex);
    9.30 @@ -66,7 +66,7 @@
    9.31  {
    9.32      if (SDL_ThreadID() == mainthread)
    9.33          signal(SIGTERM, closemutex);
    9.34 -    while (!doterminate) {
    9.35 +    while (!SDL_AtomicGet(&doterminate)) {
    9.36          SDL_Log("Process %lu ready to work\n", SDL_ThreadID());
    9.37          if (SDL_LockMutex(mutex) < 0) {
    9.38              SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock mutex: %s", SDL_GetError());
    9.39 @@ -82,7 +82,7 @@
    9.40          /* If this sleep isn't done, then threads may starve */
    9.41          SDL_Delay(10);
    9.42      }
    9.43 -    if (SDL_ThreadID() == mainthread && doterminate) {
    9.44 +    if (SDL_ThreadID() == mainthread && SDL_AtomicGet(&doterminate)) {
    9.45          SDL_Log("Process %lu:  raising SIGTERM\n", SDL_ThreadID());
    9.46          raise(SIGTERM);
    9.47      }
    9.48 @@ -105,6 +105,8 @@
    9.49      }
    9.50      atexit(SDL_Quit_Wrapper);
    9.51  
    9.52 +    SDL_AtomicSet(&doterminate, 0);
    9.53 +
    9.54      if ((mutex = SDL_CreateMutex()) == NULL) {
    9.55          SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create mutex: %s\n", SDL_GetError());
    9.56          exit(1);
    10.1 --- a/test/testmultiaudio.c	Sat Jan 02 12:17:33 2016 -0800
    10.2 +++ b/test/testmultiaudio.c	Sun Jan 03 06:50:50 2016 -0500
    10.3 @@ -25,7 +25,7 @@
    10.4  {
    10.5      SDL_AudioDeviceID dev;
    10.6      int soundpos;
    10.7 -    volatile int done;
    10.8 +    SDL_atomic_t done;
    10.9  } callback_data;
   10.10  
   10.11  callback_data cbd[64];
   10.12 @@ -46,14 +46,14 @@
   10.13      if (len > 0) {
   10.14          stream += cpy;
   10.15          SDL_memset(stream, spec.silence, len);
   10.16 -        cbd->done++;
   10.17 +        SDL_AtomicSet(&cbd->done, 1);
   10.18      }
   10.19  }
   10.20  
   10.21  void
   10.22  loop()
   10.23  {
   10.24 -    if(cbd[0].done) {
   10.25 +    if (SDL_AtomicGet(&cbd[0].done)) {
   10.26  #ifdef __EMSCRIPTEN__
   10.27          emscripten_cancel_main_loop();
   10.28  #endif
   10.29 @@ -100,8 +100,7 @@
   10.30  #ifdef __EMSCRIPTEN__
   10.31              emscripten_set_main_loop(loop, 0, 1);
   10.32  #else
   10.33 -            while (!cbd[0].done)
   10.34 -            {
   10.35 +            while (!SDL_AtomicGet(&cbd[0].done)) {
   10.36                  #ifdef __ANDROID__                
   10.37                  /* Empty queue, some application events would prevent pause. */
   10.38                  while (SDL_PollEvent(&event)){}
   10.39 @@ -136,7 +135,7 @@
   10.40      while (keep_going) {
   10.41          keep_going = 0;
   10.42          for (i = 0; i < devcount; i++) {
   10.43 -            if ((cbd[i].dev) && (!cbd[i].done)) {
   10.44 +            if ((cbd[i].dev) && (!SDL_AtomicGet(&cbd[i].done))) {
   10.45                  keep_going = 1;
   10.46              }
   10.47          }
    11.1 --- a/test/torturethread.c	Sat Jan 02 12:17:33 2016 -0800
    11.2 +++ b/test/torturethread.c	Sun Jan 03 06:50:50 2016 -0500
    11.3 @@ -21,7 +21,7 @@
    11.4  
    11.5  #define NUMTHREADS 10
    11.6  
    11.7 -static char volatile time_for_threads_to_die[NUMTHREADS];
    11.8 +static SDL_atomic_t time_for_threads_to_die[NUMTHREADS];
    11.9  
   11.10  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   11.11  static void
   11.12 @@ -58,7 +58,7 @@
   11.13      }
   11.14  
   11.15      SDL_Log("Thread '%d' waiting for signal\n", tid);
   11.16 -    while (time_for_threads_to_die[tid] != 1) {
   11.17 +    while (SDL_AtomicGet(&time_for_threads_to_die[tid]) != 1) {
   11.18          ;                       /* do nothing */
   11.19      }
   11.20  
   11.21 @@ -92,7 +92,7 @@
   11.22      for (i = 0; i < NUMTHREADS; i++) {
   11.23          char name[64];
   11.24          SDL_snprintf(name, sizeof (name), "Parent%d", i);
   11.25 -        time_for_threads_to_die[i] = 0;
   11.26 +        SDL_AtomicSet(&time_for_threads_to_die[i], 0);
   11.27          threads[i] = SDL_CreateThread(ThreadFunc, name, (void*) (uintptr_t) i);
   11.28  
   11.29          if (threads[i] == NULL) {
   11.30 @@ -102,7 +102,7 @@
   11.31      }
   11.32  
   11.33      for (i = 0; i < NUMTHREADS; i++) {
   11.34 -        time_for_threads_to_die[i] = 1;
   11.35 +        SDL_AtomicSet(&time_for_threads_to_die[i], 1);
   11.36      }
   11.37  
   11.38      for (i = 0; i < NUMTHREADS; i++) {