summaryrefslogtreecommitdiff
path: root/source/3rd-party/SDL2/src/thread
diff options
context:
space:
mode:
Diffstat (limited to 'source/3rd-party/SDL2/src/thread')
-rw-r--r--source/3rd-party/SDL2/src/thread/SDL_systhread.h70
-rw-r--r--source/3rd-party/SDL2/src/thread/SDL_thread.c505
-rw-r--r--source/3rd-party/SDL2/src/thread/SDL_thread_c.h95
-rw-r--r--source/3rd-party/SDL2/src/thread/generic/SDL_syscond.c220
-rw-r--r--source/3rd-party/SDL2/src/thread/generic/SDL_sysmutex.c165
-rw-r--r--source/3rd-party/SDL2/src/thread/generic/SDL_sysmutex_c.h22
-rw-r--r--source/3rd-party/SDL2/src/thread/generic/SDL_syssem.c217
-rw-r--r--source/3rd-party/SDL2/src/thread/generic/SDL_systhread.c71
-rw-r--r--source/3rd-party/SDL2/src/thread/generic/SDL_systhread_c.h26
-rw-r--r--source/3rd-party/SDL2/src/thread/generic/SDL_systls.c38
-rw-r--r--source/3rd-party/SDL2/src/thread/psp/SDL_syscond.c224
-rw-r--r--source/3rd-party/SDL2/src/thread/psp/SDL_sysmutex.c136
-rw-r--r--source/3rd-party/SDL2/src/thread/psp/SDL_sysmutex_c.h22
-rw-r--r--source/3rd-party/SDL2/src/thread/psp/SDL_syssem.c161
-rw-r--r--source/3rd-party/SDL2/src/thread/psp/SDL_systhread.c114
-rw-r--r--source/3rd-party/SDL2/src/thread/psp/SDL_systhread_c.h24
-rw-r--r--source/3rd-party/SDL2/src/thread/pthread/SDL_syscond.c158
-rw-r--r--source/3rd-party/SDL2/src/thread/pthread/SDL_sysmutex.c195
-rw-r--r--source/3rd-party/SDL2/src/thread/pthread/SDL_sysmutex_c.h32
-rw-r--r--source/3rd-party/SDL2/src/thread/pthread/SDL_syssem.c209
-rw-r--r--source/3rd-party/SDL2/src/thread/pthread/SDL_systhread.c324
-rw-r--r--source/3rd-party/SDL2/src/thread/pthread/SDL_systhread_c.h27
-rw-r--r--source/3rd-party/SDL2/src/thread/pthread/SDL_systls.c70
-rw-r--r--source/3rd-party/SDL2/src/thread/stdcpp/SDL_syscond.cpp164
-rw-r--r--source/3rd-party/SDL2/src/thread/stdcpp/SDL_sysmutex.cpp111
-rw-r--r--source/3rd-party/SDL2/src/thread/stdcpp/SDL_sysmutex_c.h30
-rw-r--r--source/3rd-party/SDL2/src/thread/stdcpp/SDL_systhread.cpp168
-rw-r--r--source/3rd-party/SDL2/src/thread/stdcpp/SDL_systhread_c.h26
-rw-r--r--source/3rd-party/SDL2/src/thread/windows/SDL_sysmutex.c110
-rw-r--r--source/3rd-party/SDL2/src/thread/windows/SDL_syssem.c152
-rw-r--r--source/3rd-party/SDL2/src/thread/windows/SDL_systhread.c260
-rw-r--r--source/3rd-party/SDL2/src/thread/windows/SDL_systhread_c.h32
-rw-r--r--source/3rd-party/SDL2/src/thread/windows/SDL_systls.c72
33 files changed, 4250 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/thread/SDL_systhread.h b/source/3rd-party/SDL2/src/thread/SDL_systhread.h
new file mode 100644
index 0000000..1862b23
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/SDL_systhread.h
@@ -0,0 +1,70 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../SDL_internal.h"
+
+/* These are functions that need to be implemented by a port of SDL */
+
+#ifndef SDL_systhread_h_
+#define SDL_systhread_h_
+
+#include "SDL_thread.h"
+#include "SDL_thread_c.h"
+
+/* This function creates a thread, passing args to SDL_RunThread(),
+ saves a system-dependent thread id in thread->id, and returns 0
+ on success.
+*/
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+extern int SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread);
+#else
+extern int SDL_SYS_CreateThread(SDL_Thread * thread, void *args);
+#endif
+
+/* This function does any necessary setup in the child thread */
+extern void SDL_SYS_SetupThread(const char *name);
+
+/* This function sets the current thread priority */
+extern int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority);
+
+/* This function waits for the thread to finish and frees any data
+ allocated by SDL_SYS_CreateThread()
+ */
+extern void SDL_SYS_WaitThread(SDL_Thread * thread);
+
+/* Mark thread as cleaned up as soon as it exits, without joining. */
+extern void SDL_SYS_DetachThread(SDL_Thread * thread);
+
+/* Get the thread local storage for this thread */
+extern SDL_TLSData *SDL_SYS_GetTLSData(void);
+
+/* Set the thread local storage for this thread */
+extern int SDL_SYS_SetTLSData(SDL_TLSData *data);
+
+/* This is for internal SDL use, so we don't need #ifdefs everywhere. */
+extern SDL_Thread *
+SDL_CreateThreadInternal(int (SDLCALL * fn) (void *), const char *name,
+ const size_t stacksize, void *data);
+
+#endif /* SDL_systhread_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/SDL_thread.c b/source/3rd-party/SDL2/src/thread/SDL_thread.c
new file mode 100644
index 0000000..5570adb
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/SDL_thread.c
@@ -0,0 +1,505 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../SDL_internal.h"
+
+/* System independent thread management routines for SDL */
+
+#include "SDL_assert.h"
+#include "SDL_thread.h"
+#include "SDL_thread_c.h"
+#include "SDL_systhread.h"
+#include "SDL_hints.h"
+#include "../SDL_error_c.h"
+
+
+SDL_TLSID
+SDL_TLSCreate()
+{
+ static SDL_atomic_t SDL_tls_id;
+ return SDL_AtomicIncRef(&SDL_tls_id)+1;
+}
+
+void *
+SDL_TLSGet(SDL_TLSID id)
+{
+ SDL_TLSData *storage;
+
+ storage = SDL_SYS_GetTLSData();
+ if (!storage || id == 0 || id > storage->limit) {
+ return NULL;
+ }
+ return storage->array[id-1].data;
+}
+
+int
+SDL_TLSSet(SDL_TLSID id, const void *value, void (SDLCALL *destructor)(void *))
+{
+ SDL_TLSData *storage;
+
+ if (id == 0) {
+ return SDL_InvalidParamError("id");
+ }
+
+ storage = SDL_SYS_GetTLSData();
+ if (!storage || (id > storage->limit)) {
+ unsigned int i, oldlimit, newlimit;
+
+ oldlimit = storage ? storage->limit : 0;
+ newlimit = (id + TLS_ALLOC_CHUNKSIZE);
+ storage = (SDL_TLSData *)SDL_realloc(storage, sizeof(*storage)+(newlimit-1)*sizeof(storage->array[0]));
+ if (!storage) {
+ return SDL_OutOfMemory();
+ }
+ storage->limit = newlimit;
+ for (i = oldlimit; i < newlimit; ++i) {
+ storage->array[i].data = NULL;
+ storage->array[i].destructor = NULL;
+ }
+ if (SDL_SYS_SetTLSData(storage) != 0) {
+ return -1;
+ }
+ }
+
+ storage->array[id-1].data = SDL_const_cast(void*, value);
+ storage->array[id-1].destructor = destructor;
+ return 0;
+}
+
+static void
+SDL_TLSCleanup()
+{
+ SDL_TLSData *storage;
+
+ storage = SDL_SYS_GetTLSData();
+ if (storage) {
+ unsigned int i;
+ for (i = 0; i < storage->limit; ++i) {
+ if (storage->array[i].destructor) {
+ storage->array[i].destructor(storage->array[i].data);
+ }
+ }
+ SDL_SYS_SetTLSData(NULL);
+ SDL_free(storage);
+ }
+}
+
+
+/* This is a generic implementation of thread-local storage which doesn't
+ require additional OS support.
+
+ It is not especially efficient and doesn't clean up thread-local storage
+ as threads exit. If there is a real OS that doesn't support thread-local
+ storage this implementation should be improved to be production quality.
+*/
+
+typedef struct SDL_TLSEntry {
+ SDL_threadID thread;
+ SDL_TLSData *storage;
+ struct SDL_TLSEntry *next;
+} SDL_TLSEntry;
+
+static SDL_mutex *SDL_generic_TLS_mutex;
+static SDL_TLSEntry *SDL_generic_TLS;
+
+
+SDL_TLSData *
+SDL_Generic_GetTLSData(void)
+{
+ SDL_threadID thread = SDL_ThreadID();
+ SDL_TLSEntry *entry;
+ SDL_TLSData *storage = NULL;
+
+#if !SDL_THREADS_DISABLED
+ if (!SDL_generic_TLS_mutex) {
+ static SDL_SpinLock tls_lock;
+ SDL_AtomicLock(&tls_lock);
+ if (!SDL_generic_TLS_mutex) {
+ SDL_mutex *mutex = SDL_CreateMutex();
+ SDL_MemoryBarrierRelease();
+ SDL_generic_TLS_mutex = mutex;
+ if (!SDL_generic_TLS_mutex) {
+ SDL_AtomicUnlock(&tls_lock);
+ return NULL;
+ }
+ }
+ SDL_AtomicUnlock(&tls_lock);
+ }
+#endif /* SDL_THREADS_DISABLED */
+
+ SDL_MemoryBarrierAcquire();
+ SDL_LockMutex(SDL_generic_TLS_mutex);
+ for (entry = SDL_generic_TLS; entry; entry = entry->next) {
+ if (entry->thread == thread) {
+ storage = entry->storage;
+ break;
+ }
+ }
+#if !SDL_THREADS_DISABLED
+ SDL_UnlockMutex(SDL_generic_TLS_mutex);
+#endif
+
+ return storage;
+}
+
+int
+SDL_Generic_SetTLSData(SDL_TLSData *storage)
+{
+ SDL_threadID thread = SDL_ThreadID();
+ SDL_TLSEntry *prev, *entry;
+
+ /* SDL_Generic_GetTLSData() is always called first, so we can assume SDL_generic_TLS_mutex */
+ SDL_LockMutex(SDL_generic_TLS_mutex);
+ prev = NULL;
+ for (entry = SDL_generic_TLS; entry; entry = entry->next) {
+ if (entry->thread == thread) {
+ if (storage) {
+ entry->storage = storage;
+ } else {
+ if (prev) {
+ prev->next = entry->next;
+ } else {
+ SDL_generic_TLS = entry->next;
+ }
+ SDL_free(entry);
+ }
+ break;
+ }
+ prev = entry;
+ }
+ if (!entry) {
+ entry = (SDL_TLSEntry *)SDL_malloc(sizeof(*entry));
+ if (entry) {
+ entry->thread = thread;
+ entry->storage = storage;
+ entry->next = SDL_generic_TLS;
+ SDL_generic_TLS = entry;
+ }
+ }
+ SDL_UnlockMutex(SDL_generic_TLS_mutex);
+
+ if (!entry) {
+ return SDL_OutOfMemory();
+ }
+ return 0;
+}
+
+/* Routine to get the thread-specific error variable */
+SDL_error *
+SDL_GetErrBuf(void)
+{
+ static SDL_SpinLock tls_lock;
+ static SDL_bool tls_being_created;
+ static SDL_TLSID tls_errbuf;
+ static SDL_error SDL_global_errbuf;
+ const SDL_error *ALLOCATION_IN_PROGRESS = (SDL_error *)-1;
+ SDL_error *errbuf;
+
+ /* tls_being_created is there simply to prevent recursion if SDL_TLSCreate() fails.
+ It also means it's possible for another thread to also use SDL_global_errbuf,
+ but that's very unlikely and hopefully won't cause issues.
+ */
+ if (!tls_errbuf && !tls_being_created) {
+ SDL_AtomicLock(&tls_lock);
+ if (!tls_errbuf) {
+ SDL_TLSID slot;
+ tls_being_created = SDL_TRUE;
+ slot = SDL_TLSCreate();
+ tls_being_created = SDL_FALSE;
+ SDL_MemoryBarrierRelease();
+ tls_errbuf = slot;
+ }
+ SDL_AtomicUnlock(&tls_lock);
+ }
+ if (!tls_errbuf) {
+ return &SDL_global_errbuf;
+ }
+
+ SDL_MemoryBarrierAcquire();
+ errbuf = (SDL_error *)SDL_TLSGet(tls_errbuf);
+ if (errbuf == ALLOCATION_IN_PROGRESS) {
+ return &SDL_global_errbuf;
+ }
+ if (!errbuf) {
+ /* Mark that we're in the middle of allocating our buffer */
+ SDL_TLSSet(tls_errbuf, ALLOCATION_IN_PROGRESS, NULL);
+ errbuf = (SDL_error *)SDL_malloc(sizeof(*errbuf));
+ if (!errbuf) {
+ SDL_TLSSet(tls_errbuf, NULL, NULL);
+ return &SDL_global_errbuf;
+ }
+ SDL_zerop(errbuf);
+ SDL_TLSSet(tls_errbuf, errbuf, SDL_free);
+ }
+ return errbuf;
+}
+
+
+/* Arguments and callback to setup and run the user thread function */
+typedef struct
+{
+ int (SDLCALL * func) (void *);
+ void *data;
+ SDL_Thread *info;
+ SDL_sem *wait;
+} thread_args;
+
+void
+SDL_RunThread(void *data)
+{
+ thread_args *args = (thread_args *) data;
+ int (SDLCALL * userfunc) (void *) = args->func;
+ void *userdata = args->data;
+ SDL_Thread *thread = args->info;
+ int *statusloc = &thread->status;
+
+ /* Perform any system-dependent setup - this function may not fail */
+ SDL_SYS_SetupThread(thread->name);
+
+ /* Get the thread id */
+ thread->threadid = SDL_ThreadID();
+
+ /* Wake up the parent thread */
+ SDL_SemPost(args->wait);
+
+ /* Run the function */
+ *statusloc = userfunc(userdata);
+
+ /* Clean up thread-local storage */
+ SDL_TLSCleanup();
+
+ /* Mark us as ready to be joined (or detached) */
+ if (!SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_ZOMBIE)) {
+ /* Clean up if something already detached us. */
+ if (SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_CLEANED)) {
+ if (thread->name) {
+ SDL_free(thread->name);
+ }
+ SDL_free(thread);
+ }
+ }
+}
+
+#ifdef SDL_CreateThread
+#undef SDL_CreateThread
+#undef SDL_CreateThreadWithStackSize
+#endif
+#if SDL_DYNAMIC_API
+#define SDL_CreateThread SDL_CreateThread_REAL
+#define SDL_CreateThreadWithStackSize SDL_CreateThreadWithStackSize_REAL
+#endif
+
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+SDL_Thread *
+SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
+ const char *name, const size_t stacksize, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread)
+#else
+SDL_Thread *
+SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
+ const char *name, const size_t stacksize, void *data)
+#endif
+{
+ SDL_Thread *thread;
+ thread_args *args;
+ int ret;
+
+ /* Allocate memory for the thread info structure */
+ thread = (SDL_Thread *) SDL_malloc(sizeof(*thread));
+ if (thread == NULL) {
+ SDL_OutOfMemory();
+ return (NULL);
+ }
+ SDL_zerop(thread);
+ thread->status = -1;
+ SDL_AtomicSet(&thread->state, SDL_THREAD_STATE_ALIVE);
+
+ /* Set up the arguments for the thread */
+ if (name != NULL) {
+ thread->name = SDL_strdup(name);
+ if (thread->name == NULL) {
+ SDL_OutOfMemory();
+ SDL_free(thread);
+ return (NULL);
+ }
+ }
+
+ /* Set up the arguments for the thread */
+ args = (thread_args *) SDL_malloc(sizeof(*args));
+ if (args == NULL) {
+ SDL_OutOfMemory();
+ if (thread->name) {
+ SDL_free(thread->name);
+ }
+ SDL_free(thread);
+ return (NULL);
+ }
+ args->func = fn;
+ args->data = data;
+ args->info = thread;
+ args->wait = SDL_CreateSemaphore(0);
+ if (args->wait == NULL) {
+ if (thread->name) {
+ SDL_free(thread->name);
+ }
+ SDL_free(thread);
+ SDL_free(args);
+ return (NULL);
+ }
+
+ thread->stacksize = stacksize;
+
+ /* Create the thread and go! */
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+ ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
+#else
+ ret = SDL_SYS_CreateThread(thread, args);
+#endif
+ if (ret >= 0) {
+ /* Wait for the thread function to use arguments */
+ SDL_SemWait(args->wait);
+ } else {
+ /* Oops, failed. Gotta free everything */
+ if (thread->name) {
+ SDL_free(thread->name);
+ }
+ SDL_free(thread);
+ thread = NULL;
+ }
+ SDL_DestroySemaphore(args->wait);
+ SDL_free(args);
+
+ /* Everything is running now */
+ return (thread);
+}
+
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(int (SDLCALL * fn) (void *),
+ const char *name, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread)
+#else
+DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(int (SDLCALL * fn) (void *),
+ const char *name, void *data)
+#endif
+{
+ /* !!! FIXME: in 2.1, just make stackhint part of the usual API. */
+ const char *stackhint = SDL_GetHint(SDL_HINT_THREAD_STACK_SIZE);
+ size_t stacksize = 0;
+
+ /* If the SDL_HINT_THREAD_STACK_SIZE exists, use it */
+ if (stackhint != NULL) {
+ char *endp = NULL;
+ const Sint64 hintval = SDL_strtoll(stackhint, &endp, 10);
+ if ((*stackhint != '\0') && (*endp == '\0')) { /* a valid number? */
+ if (hintval > 0) { /* reject bogus values. */
+ stacksize = (size_t) hintval;
+ }
+ }
+ }
+
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+ return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, pfnBeginThread, pfnEndThread);
+#else
+ return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
+#endif
+}
+
+SDL_Thread *
+SDL_CreateThreadInternal(int (SDLCALL * fn) (void *), const char *name,
+ const size_t stacksize, void *data) {
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+ return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, NULL, NULL);
+#else
+ return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
+#endif
+}
+
+SDL_threadID
+SDL_GetThreadID(SDL_Thread * thread)
+{
+ SDL_threadID id;
+
+ if (thread) {
+ id = thread->threadid;
+ } else {
+ id = SDL_ThreadID();
+ }
+ return id;
+}
+
+const char *
+SDL_GetThreadName(SDL_Thread * thread)
+{
+ if (thread) {
+ return thread->name;
+ } else {
+ return NULL;
+ }
+}
+
+int
+SDL_SetThreadPriority(SDL_ThreadPriority priority)
+{
+ return SDL_SYS_SetThreadPriority(priority);
+}
+
+void
+SDL_WaitThread(SDL_Thread * thread, int *status)
+{
+ if (thread) {
+ SDL_SYS_WaitThread(thread);
+ if (status) {
+ *status = thread->status;
+ }
+ if (thread->name) {
+ SDL_free(thread->name);
+ }
+ SDL_free(thread);
+ }
+}
+
+void
+SDL_DetachThread(SDL_Thread * thread)
+{
+ if (!thread) {
+ return;
+ }
+
+ /* Grab dibs if the state is alive+joinable. */
+ if (SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_DETACHED)) {
+ SDL_SYS_DetachThread(thread);
+ } else {
+ /* all other states are pretty final, see where we landed. */
+ const int thread_state = SDL_AtomicGet(&thread->state);
+ if ((thread_state == SDL_THREAD_STATE_DETACHED) || (thread_state == SDL_THREAD_STATE_CLEANED)) {
+ return; /* already detached (you shouldn't call this twice!) */
+ } else if (thread_state == SDL_THREAD_STATE_ZOMBIE) {
+ SDL_WaitThread(thread, NULL); /* already done, clean it up. */
+ } else {
+ SDL_assert(0 && "Unexpected thread state");
+ }
+ }
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/SDL_thread_c.h b/source/3rd-party/SDL2/src/thread/SDL_thread_c.h
new file mode 100644
index 0000000..b68f90e
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/SDL_thread_c.h
@@ -0,0 +1,95 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../SDL_internal.h"
+
+#ifndef SDL_thread_c_h_
+#define SDL_thread_c_h_
+
+#include "SDL_thread.h"
+
+/* Need the definitions of SYS_ThreadHandle */
+#if SDL_THREADS_DISABLED
+#include "generic/SDL_systhread_c.h"
+#elif SDL_THREAD_PTHREAD
+#include "pthread/SDL_systhread_c.h"
+#elif SDL_THREAD_WINDOWS
+#include "windows/SDL_systhread_c.h"
+#elif SDL_THREAD_PSP
+#include "psp/SDL_systhread_c.h"
+#elif SDL_THREAD_STDCPP
+#include "stdcpp/SDL_systhread_c.h"
+#else
+#error Need thread implementation for this platform
+#include "generic/SDL_systhread_c.h"
+#endif
+#include "../SDL_error_c.h"
+
+typedef enum SDL_ThreadState
+{
+ SDL_THREAD_STATE_ALIVE,
+ SDL_THREAD_STATE_DETACHED,
+ SDL_THREAD_STATE_ZOMBIE,
+ SDL_THREAD_STATE_CLEANED,
+} SDL_ThreadState;
+
+/* This is the system-independent thread info structure */
+struct SDL_Thread
+{
+ SDL_threadID threadid;
+ SYS_ThreadHandle handle;
+ int status;
+ SDL_atomic_t state; /* SDL_THREAD_STATE_* */
+ SDL_error errbuf;
+ char *name;
+ size_t stacksize; /* 0 for default, >0 for user-specified stack size. */
+ void *data;
+};
+
+/* This is the function called to run a thread */
+extern void SDL_RunThread(void *data);
+
+/* This is the system-independent thread local storage structure */
+typedef struct {
+ unsigned int limit;
+ struct {
+ void *data;
+ void (SDLCALL *destructor)(void*);
+ } array[1];
+} SDL_TLSData;
+
+/* This is how many TLS entries we allocate at once */
+#define TLS_ALLOC_CHUNKSIZE 4
+
+/* Get cross-platform, slow, thread local storage for this thread.
+ This is only intended as a fallback if getting real thread-local
+ storage fails or isn't supported on this platform.
+ */
+extern SDL_TLSData *SDL_Generic_GetTLSData(void);
+
+/* Set cross-platform, slow, thread local storage for this thread.
+ This is only intended as a fallback if getting real thread-local
+ storage fails or isn't supported on this platform.
+ */
+extern int SDL_Generic_SetTLSData(SDL_TLSData *data);
+
+#endif /* SDL_thread_c_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/generic/SDL_syscond.c b/source/3rd-party/SDL2/src/thread/generic/SDL_syscond.c
new file mode 100644
index 0000000..34b9893
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/generic/SDL_syscond.c
@@ -0,0 +1,220 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+/* An implementation of condition variables using semaphores and mutexes */
+/*
+ This implementation borrows heavily from the BeOS condition variable
+ implementation, written by Christopher Tate and Owen Smith. Thanks!
+ */
+
+#include "SDL_thread.h"
+
+struct SDL_cond
+{
+ SDL_mutex *lock;
+ int waiting;
+ int signals;
+ SDL_sem *wait_sem;
+ SDL_sem *wait_done;
+};
+
+/* Create a condition variable */
+SDL_cond *
+SDL_CreateCond(void)
+{
+ SDL_cond *cond;
+
+ cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
+ if (cond) {
+ cond->lock = SDL_CreateMutex();
+ cond->wait_sem = SDL_CreateSemaphore(0);
+ cond->wait_done = SDL_CreateSemaphore(0);
+ cond->waiting = cond->signals = 0;
+ if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
+ SDL_DestroyCond(cond);
+ cond = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return (cond);
+}
+
+/* Destroy a condition variable */
+void
+SDL_DestroyCond(SDL_cond * cond)
+{
+ if (cond) {
+ if (cond->wait_sem) {
+ SDL_DestroySemaphore(cond->wait_sem);
+ }
+ if (cond->wait_done) {
+ SDL_DestroySemaphore(cond->wait_done);
+ }
+ if (cond->lock) {
+ SDL_DestroyMutex(cond->lock);
+ }
+ SDL_free(cond);
+ }
+}
+
+/* Restart one of the threads that are waiting on the condition variable */
+int
+SDL_CondSignal(SDL_cond * cond)
+{
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+ /* If there are waiting threads not already signalled, then
+ signal the condition and wait for the thread to respond.
+ */
+ SDL_LockMutex(cond->lock);
+ if (cond->waiting > cond->signals) {
+ ++cond->signals;
+ SDL_SemPost(cond->wait_sem);
+ SDL_UnlockMutex(cond->lock);
+ SDL_SemWait(cond->wait_done);
+ } else {
+ SDL_UnlockMutex(cond->lock);
+ }
+
+ return 0;
+}
+
+/* Restart all threads that are waiting on the condition variable */
+int
+SDL_CondBroadcast(SDL_cond * cond)
+{
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+ /* If there are waiting threads not already signalled, then
+ signal the condition and wait for the thread to respond.
+ */
+ SDL_LockMutex(cond->lock);
+ if (cond->waiting > cond->signals) {
+ int i, num_waiting;
+
+ num_waiting = (cond->waiting - cond->signals);
+ cond->signals = cond->waiting;
+ for (i = 0; i < num_waiting; ++i) {
+ SDL_SemPost(cond->wait_sem);
+ }
+ /* Now all released threads are blocked here, waiting for us.
+ Collect them all (and win fabulous prizes!) :-)
+ */
+ SDL_UnlockMutex(cond->lock);
+ for (i = 0; i < num_waiting; ++i) {
+ SDL_SemWait(cond->wait_done);
+ }
+ } else {
+ SDL_UnlockMutex(cond->lock);
+ }
+
+ return 0;
+}
+
+/* Wait on the condition variable for at most 'ms' milliseconds.
+ The mutex must be locked before entering this function!
+ The mutex is unlocked during the wait, and locked again after the wait.
+
+Typical use:
+
+Thread A:
+ SDL_LockMutex(lock);
+ while ( ! condition ) {
+ SDL_CondWait(cond, lock);
+ }
+ SDL_UnlockMutex(lock);
+
+Thread B:
+ SDL_LockMutex(lock);
+ ...
+ condition = true;
+ ...
+ SDL_CondSignal(cond);
+ SDL_UnlockMutex(lock);
+ */
+int
+SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
+{
+ int retval;
+
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+ /* Obtain the protection mutex, and increment the number of waiters.
+ This allows the signal mechanism to only perform a signal if there
+ are waiting threads.
+ */
+ SDL_LockMutex(cond->lock);
+ ++cond->waiting;
+ SDL_UnlockMutex(cond->lock);
+
+ /* Unlock the mutex, as is required by condition variable semantics */
+ SDL_UnlockMutex(mutex);
+
+ /* Wait for a signal */
+ if (ms == SDL_MUTEX_MAXWAIT) {
+ retval = SDL_SemWait(cond->wait_sem);
+ } else {
+ retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
+ }
+
+ /* Let the signaler know we have completed the wait, otherwise
+ the signaler can race ahead and get the condition semaphore
+ if we are stopped between the mutex unlock and semaphore wait,
+ giving a deadlock. See the following URL for details:
+ http://web.archive.org/web/20010914175514/http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html#Workshop
+ */
+ SDL_LockMutex(cond->lock);
+ if (cond->signals > 0) {
+ /* If we timed out, we need to eat a condition signal */
+ if (retval > 0) {
+ SDL_SemWait(cond->wait_sem);
+ }
+ /* We always notify the signal thread that we are done */
+ SDL_SemPost(cond->wait_done);
+
+ /* Signal handshake complete */
+ --cond->signals;
+ }
+ --cond->waiting;
+ SDL_UnlockMutex(cond->lock);
+
+ /* Lock the mutex, as is required by condition variable semantics */
+ SDL_LockMutex(mutex);
+
+ return retval;
+}
+
+/* Wait on the condition variable forever */
+int
+SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
+{
+ return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/generic/SDL_sysmutex.c b/source/3rd-party/SDL2/src/thread/generic/SDL_sysmutex.c
new file mode 100644
index 0000000..df78ca9
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/generic/SDL_sysmutex.c
@@ -0,0 +1,165 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+/* An implementation of mutexes using semaphores */
+
+#include "SDL_thread.h"
+#include "SDL_systhread_c.h"
+
+
+struct SDL_mutex
+{
+ int recursive;
+ SDL_threadID owner;
+ SDL_sem *sem;
+};
+
+/* Create a mutex */
+SDL_mutex *
+SDL_CreateMutex(void)
+{
+ SDL_mutex *mutex;
+
+ /* Allocate mutex memory */
+ mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
+ if (mutex) {
+ /* Create the mutex semaphore, with initial value 1 */
+ mutex->sem = SDL_CreateSemaphore(1);
+ mutex->recursive = 0;
+ mutex->owner = 0;
+ if (!mutex->sem) {
+ SDL_free(mutex);
+ mutex = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return mutex;
+}
+
+/* Free the mutex */
+void
+SDL_DestroyMutex(SDL_mutex * mutex)
+{
+ if (mutex) {
+ if (mutex->sem) {
+ SDL_DestroySemaphore(mutex->sem);
+ }
+ SDL_free(mutex);
+ }
+}
+
+/* Lock the mutex */
+int
+SDL_LockMutex(SDL_mutex * mutex)
+{
+#if SDL_THREADS_DISABLED
+ return 0;
+#else
+ SDL_threadID this_thread;
+
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ this_thread = SDL_ThreadID();
+ if (mutex->owner == this_thread) {
+ ++mutex->recursive;
+ } else {
+ /* The order of operations is important.
+ We set the locking thread id after we obtain the lock
+ so unlocks from other threads will fail.
+ */
+ SDL_SemWait(mutex->sem);
+ mutex->owner = this_thread;
+ mutex->recursive = 0;
+ }
+
+ return 0;
+#endif /* SDL_THREADS_DISABLED */
+}
+
+/* try Lock the mutex */
+int
+SDL_TryLockMutex(SDL_mutex * mutex)
+{
+#if SDL_THREADS_DISABLED
+ return 0;
+#else
+ int retval = 0;
+ SDL_threadID this_thread;
+
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ this_thread = SDL_ThreadID();
+ if (mutex->owner == this_thread) {
+ ++mutex->recursive;
+ } else {
+ /* The order of operations is important.
+ We set the locking thread id after we obtain the lock
+ so unlocks from other threads will fail.
+ */
+ retval = SDL_SemWait(mutex->sem);
+ if (retval == 0) {
+ mutex->owner = this_thread;
+ mutex->recursive = 0;
+ }
+ }
+
+ return retval;
+#endif /* SDL_THREADS_DISABLED */
+}
+
+/* Unlock the mutex */
+int
+SDL_mutexV(SDL_mutex * mutex)
+{
+#if SDL_THREADS_DISABLED
+ return 0;
+#else
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ /* If we don't own the mutex, we can't unlock it */
+ if (SDL_ThreadID() != mutex->owner) {
+ return SDL_SetError("mutex not owned by this thread");
+ }
+
+ if (mutex->recursive) {
+ --mutex->recursive;
+ } else {
+ /* The order of operations is important.
+ First reset the owner so another thread doesn't lock
+ the mutex and set the ownership before we reset it,
+ then release the lock semaphore.
+ */
+ mutex->owner = 0;
+ SDL_SemPost(mutex->sem);
+ }
+ return 0;
+#endif /* SDL_THREADS_DISABLED */
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/generic/SDL_sysmutex_c.h b/source/3rd-party/SDL2/src/thread/generic/SDL_sysmutex_c.h
new file mode 100644
index 0000000..2979437
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/generic/SDL_sysmutex_c.h
@@ -0,0 +1,22 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/generic/SDL_syssem.c b/source/3rd-party/SDL2/src/thread/generic/SDL_syssem.c
new file mode 100644
index 0000000..30ff824
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/generic/SDL_syssem.c
@@ -0,0 +1,217 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+/* An implementation of semaphores using mutexes and condition variables */
+
+#include "SDL_timer.h"
+#include "SDL_thread.h"
+#include "SDL_systhread_c.h"
+
+
+#if SDL_THREADS_DISABLED
+
+SDL_sem *
+SDL_CreateSemaphore(Uint32 initial_value)
+{
+ SDL_SetError("SDL not built with thread support");
+ return (SDL_sem *) 0;
+}
+
+void
+SDL_DestroySemaphore(SDL_sem * sem)
+{
+}
+
+int
+SDL_SemTryWait(SDL_sem * sem)
+{
+ return SDL_SetError("SDL not built with thread support");
+}
+
+int
+SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
+{
+ return SDL_SetError("SDL not built with thread support");
+}
+
+int
+SDL_SemWait(SDL_sem * sem)
+{
+ return SDL_SetError("SDL not built with thread support");
+}
+
+Uint32
+SDL_SemValue(SDL_sem * sem)
+{
+ return 0;
+}
+
+int
+SDL_SemPost(SDL_sem * sem)
+{
+ return SDL_SetError("SDL not built with thread support");
+}
+
+#else
+
+struct SDL_semaphore
+{
+ Uint32 count;
+ Uint32 waiters_count;
+ SDL_mutex *count_lock;
+ SDL_cond *count_nonzero;
+};
+
+SDL_sem *
+SDL_CreateSemaphore(Uint32 initial_value)
+{
+ SDL_sem *sem;
+
+ sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
+ if (!sem) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+ sem->count = initial_value;
+ sem->waiters_count = 0;
+
+ sem->count_lock = SDL_CreateMutex();
+ sem->count_nonzero = SDL_CreateCond();
+ if (!sem->count_lock || !sem->count_nonzero) {
+ SDL_DestroySemaphore(sem);
+ return NULL;
+ }
+
+ return sem;
+}
+
+/* WARNING:
+ You cannot call this function when another thread is using the semaphore.
+*/
+void
+SDL_DestroySemaphore(SDL_sem * sem)
+{
+ if (sem) {
+ sem->count = 0xFFFFFFFF;
+ while (sem->waiters_count > 0) {
+ SDL_CondSignal(sem->count_nonzero);
+ SDL_Delay(10);
+ }
+ SDL_DestroyCond(sem->count_nonzero);
+ if (sem->count_lock) {
+ SDL_LockMutex(sem->count_lock);
+ SDL_UnlockMutex(sem->count_lock);
+ SDL_DestroyMutex(sem->count_lock);
+ }
+ SDL_free(sem);
+ }
+}
+
+int
+SDL_SemTryWait(SDL_sem * sem)
+{
+ int retval;
+
+ if (!sem) {
+ return SDL_SetError("Passed a NULL semaphore");
+ }
+
+ retval = SDL_MUTEX_TIMEDOUT;
+ SDL_LockMutex(sem->count_lock);
+ if (sem->count > 0) {
+ --sem->count;
+ retval = 0;
+ }
+ SDL_UnlockMutex(sem->count_lock);
+
+ return retval;
+}
+
+int
+SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
+{
+ int retval;
+
+ if (!sem) {
+ return SDL_SetError("Passed a NULL semaphore");
+ }
+
+ /* A timeout of 0 is an easy case */
+ if (timeout == 0) {
+ return SDL_SemTryWait(sem);
+ }
+
+ SDL_LockMutex(sem->count_lock);
+ ++sem->waiters_count;
+ retval = 0;
+ while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) {
+ retval = SDL_CondWaitTimeout(sem->count_nonzero,
+ sem->count_lock, timeout);
+ }
+ --sem->waiters_count;
+ if (retval == 0) {
+ --sem->count;
+ }
+ SDL_UnlockMutex(sem->count_lock);
+
+ return retval;
+}
+
+int
+SDL_SemWait(SDL_sem * sem)
+{
+ return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
+}
+
+Uint32
+SDL_SemValue(SDL_sem * sem)
+{
+ Uint32 value;
+
+ value = 0;
+ if (sem) {
+ SDL_LockMutex(sem->count_lock);
+ value = sem->count;
+ SDL_UnlockMutex(sem->count_lock);
+ }
+ return value;
+}
+
+int
+SDL_SemPost(SDL_sem * sem)
+{
+ if (!sem) {
+ return SDL_SetError("Passed a NULL semaphore");
+ }
+
+ SDL_LockMutex(sem->count_lock);
+ if (sem->waiters_count > 0) {
+ SDL_CondSignal(sem->count_nonzero);
+ }
+ ++sem->count;
+ SDL_UnlockMutex(sem->count_lock);
+
+ return 0;
+}
+
+#endif /* SDL_THREADS_DISABLED */
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/generic/SDL_systhread.c b/source/3rd-party/SDL2/src/thread/generic/SDL_systhread.c
new file mode 100644
index 0000000..7a19b78
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/generic/SDL_systhread.c
@@ -0,0 +1,71 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+/* Thread management routines for SDL */
+
+#include "SDL_thread.h"
+#include "../SDL_systhread.h"
+
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+int
+SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread)
+#else
+int
+SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
+#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
+{
+ return SDL_SetError("Threads are not supported on this platform");
+}
+
+void
+SDL_SYS_SetupThread(const char *name)
+{
+ return;
+}
+
+SDL_threadID
+SDL_ThreadID(void)
+{
+ return (0);
+}
+
+int
+SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
+{
+ return (0);
+}
+
+void
+SDL_SYS_WaitThread(SDL_Thread * thread)
+{
+ return;
+}
+
+void
+SDL_SYS_DetachThread(SDL_Thread * thread)
+{
+ return;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/generic/SDL_systhread_c.h b/source/3rd-party/SDL2/src/thread/generic/SDL_systhread_c.h
new file mode 100644
index 0000000..13db579
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/generic/SDL_systhread_c.h
@@ -0,0 +1,26 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+/* Stub until we implement threads on this platform */
+typedef int SYS_ThreadHandle;
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/generic/SDL_systls.c b/source/3rd-party/SDL2/src/thread/generic/SDL_systls.c
new file mode 100644
index 0000000..241862e
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/generic/SDL_systls.c
@@ -0,0 +1,38 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+#include "../SDL_thread_c.h"
+
+
+SDL_TLSData *
+SDL_SYS_GetTLSData(void)
+{
+ return SDL_Generic_GetTLSData();
+}
+
+int
+SDL_SYS_SetTLSData(SDL_TLSData *data)
+{
+ return SDL_Generic_SetTLSData(data);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/psp/SDL_syscond.c b/source/3rd-party/SDL2/src/thread/psp/SDL_syscond.c
new file mode 100644
index 0000000..4ed73e0
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/psp/SDL_syscond.c
@@ -0,0 +1,224 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_THREAD_PSP
+
+/* An implementation of condition variables using semaphores and mutexes */
+/*
+ This implementation borrows heavily from the BeOS condition variable
+ implementation, written by Christopher Tate and Owen Smith. Thanks!
+ */
+
+#include "SDL_thread.h"
+
+struct SDL_cond
+{
+ SDL_mutex *lock;
+ int waiting;
+ int signals;
+ SDL_sem *wait_sem;
+ SDL_sem *wait_done;
+};
+
+/* Create a condition variable */
+SDL_cond *
+SDL_CreateCond(void)
+{
+ SDL_cond *cond;
+
+ cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
+ if (cond) {
+ cond->lock = SDL_CreateMutex();
+ cond->wait_sem = SDL_CreateSemaphore(0);
+ cond->wait_done = SDL_CreateSemaphore(0);
+ cond->waiting = cond->signals = 0;
+ if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
+ SDL_DestroyCond(cond);
+ cond = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return (cond);
+}
+
+/* Destroy a condition variable */
+void
+SDL_DestroyCond(SDL_cond * cond)
+{
+ if (cond) {
+ if (cond->wait_sem) {
+ SDL_DestroySemaphore(cond->wait_sem);
+ }
+ if (cond->wait_done) {
+ SDL_DestroySemaphore(cond->wait_done);
+ }
+ if (cond->lock) {
+ SDL_DestroyMutex(cond->lock);
+ }
+ SDL_free(cond);
+ }
+}
+
+/* Restart one of the threads that are waiting on the condition variable */
+int
+SDL_CondSignal(SDL_cond * cond)
+{
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+ /* If there are waiting threads not already signalled, then
+ signal the condition and wait for the thread to respond.
+ */
+ SDL_LockMutex(cond->lock);
+ if (cond->waiting > cond->signals) {
+ ++cond->signals;
+ SDL_SemPost(cond->wait_sem);
+ SDL_UnlockMutex(cond->lock);
+ SDL_SemWait(cond->wait_done);
+ } else {
+ SDL_UnlockMutex(cond->lock);
+ }
+
+ return 0;
+}
+
+/* Restart all threads that are waiting on the condition variable */
+int
+SDL_CondBroadcast(SDL_cond * cond)
+{
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+ /* If there are waiting threads not already signalled, then
+ signal the condition and wait for the thread to respond.
+ */
+ SDL_LockMutex(cond->lock);
+ if (cond->waiting > cond->signals) {
+ int i, num_waiting;
+
+ num_waiting = (cond->waiting - cond->signals);
+ cond->signals = cond->waiting;
+ for (i = 0; i < num_waiting; ++i) {
+ SDL_SemPost(cond->wait_sem);
+ }
+ /* Now all released threads are blocked here, waiting for us.
+ Collect them all (and win fabulous prizes!) :-)
+ */
+ SDL_UnlockMutex(cond->lock);
+ for (i = 0; i < num_waiting; ++i) {
+ SDL_SemWait(cond->wait_done);
+ }
+ } else {
+ SDL_UnlockMutex(cond->lock);
+ }
+
+ return 0;
+}
+
+/* Wait on the condition variable for at most 'ms' milliseconds.
+ The mutex must be locked before entering this function!
+ The mutex is unlocked during the wait, and locked again after the wait.
+
+Typical use:
+
+Thread A:
+ SDL_LockMutex(lock);
+ while ( ! condition ) {
+ SDL_CondWait(cond, lock);
+ }
+ SDL_UnlockMutex(lock);
+
+Thread B:
+ SDL_LockMutex(lock);
+ ...
+ condition = true;
+ ...
+ SDL_CondSignal(cond);
+ SDL_UnlockMutex(lock);
+ */
+int
+SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
+{
+ int retval;
+
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+ /* Obtain the protection mutex, and increment the number of waiters.
+ This allows the signal mechanism to only perform a signal if there
+ are waiting threads.
+ */
+ SDL_LockMutex(cond->lock);
+ ++cond->waiting;
+ SDL_UnlockMutex(cond->lock);
+
+ /* Unlock the mutex, as is required by condition variable semantics */
+ SDL_UnlockMutex(mutex);
+
+ /* Wait for a signal */
+ if (ms == SDL_MUTEX_MAXWAIT) {
+ retval = SDL_SemWait(cond->wait_sem);
+ } else {
+ retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
+ }
+
+ /* Let the signaler know we have completed the wait, otherwise
+ the signaler can race ahead and get the condition semaphore
+ if we are stopped between the mutex unlock and semaphore wait,
+ giving a deadlock. See the following URL for details:
+ http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
+ */
+ SDL_LockMutex(cond->lock);
+ if (cond->signals > 0) {
+ /* If we timed out, we need to eat a condition signal */
+ if (retval > 0) {
+ SDL_SemWait(cond->wait_sem);
+ }
+ /* We always notify the signal thread that we are done */
+ SDL_SemPost(cond->wait_done);
+
+ /* Signal handshake complete */
+ --cond->signals;
+ }
+ --cond->waiting;
+ SDL_UnlockMutex(cond->lock);
+
+ /* Lock the mutex, as is required by condition variable semantics */
+ SDL_LockMutex(mutex);
+
+ return retval;
+}
+
+/* Wait on the condition variable forever */
+int
+SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
+{
+ return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
+}
+
+#endif /* SDL_THREAD_PSP */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/psp/SDL_sysmutex.c b/source/3rd-party/SDL2/src/thread/psp/SDL_sysmutex.c
new file mode 100644
index 0000000..e2db5eb
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/psp/SDL_sysmutex.c
@@ -0,0 +1,136 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_THREAD_PSP
+
+/* An implementation of mutexes using semaphores */
+
+#include "SDL_thread.h"
+#include "SDL_systhread_c.h"
+
+
+struct SDL_mutex
+{
+ int recursive;
+ SDL_threadID owner;
+ SDL_sem *sem;
+};
+
+/* Create a mutex */
+SDL_mutex *
+SDL_CreateMutex(void)
+{
+ SDL_mutex *mutex;
+
+ /* Allocate mutex memory */
+ mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
+ if (mutex) {
+ /* Create the mutex semaphore, with initial value 1 */
+ mutex->sem = SDL_CreateSemaphore(1);
+ mutex->recursive = 0;
+ mutex->owner = 0;
+ if (!mutex->sem) {
+ SDL_free(mutex);
+ mutex = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return mutex;
+}
+
+/* Free the mutex */
+void
+SDL_DestroyMutex(SDL_mutex * mutex)
+{
+ if (mutex) {
+ if (mutex->sem) {
+ SDL_DestroySemaphore(mutex->sem);
+ }
+ SDL_free(mutex);
+ }
+}
+
+/* Lock the semaphore */
+int
+SDL_mutexP(SDL_mutex * mutex)
+{
+#if SDL_THREADS_DISABLED
+ return 0;
+#else
+ SDL_threadID this_thread;
+
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ this_thread = SDL_ThreadID();
+ if (mutex->owner == this_thread) {
+ ++mutex->recursive;
+ } else {
+ /* The order of operations is important.
+ We set the locking thread id after we obtain the lock
+ so unlocks from other threads will fail.
+ */
+ SDL_SemWait(mutex->sem);
+ mutex->owner = this_thread;
+ mutex->recursive = 0;
+ }
+
+ return 0;
+#endif /* SDL_THREADS_DISABLED */
+}
+
+/* Unlock the mutex */
+int
+SDL_mutexV(SDL_mutex * mutex)
+{
+#if SDL_THREADS_DISABLED
+ return 0;
+#else
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ /* If we don't own the mutex, we can't unlock it */
+ if (SDL_ThreadID() != mutex->owner) {
+ return SDL_SetError("mutex not owned by this thread");
+ }
+
+ if (mutex->recursive) {
+ --mutex->recursive;
+ } else {
+ /* The order of operations is important.
+ First reset the owner so another thread doesn't lock
+ the mutex and set the ownership before we reset it,
+ then release the lock semaphore.
+ */
+ mutex->owner = 0;
+ SDL_SemPost(mutex->sem);
+ }
+ return 0;
+#endif /* SDL_THREADS_DISABLED */
+}
+
+#endif /* SDL_THREAD_PSP */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/psp/SDL_sysmutex_c.h b/source/3rd-party/SDL2/src/thread/psp/SDL_sysmutex_c.h
new file mode 100644
index 0000000..2979437
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/psp/SDL_sysmutex_c.h
@@ -0,0 +1,22 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/psp/SDL_syssem.c b/source/3rd-party/SDL2/src/thread/psp/SDL_syssem.c
new file mode 100644
index 0000000..0c36434
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/psp/SDL_syssem.c
@@ -0,0 +1,161 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_THREAD_PSP
+
+/* Semaphore functions for the PSP. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "SDL_error.h"
+#include "SDL_thread.h"
+
+#include <pspthreadman.h>
+#include <pspkerror.h>
+
+struct SDL_semaphore {
+ SceUID semid;
+};
+
+
+/* Create a semaphore */
+SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
+{
+ SDL_sem *sem;
+
+ sem = (SDL_sem *) malloc(sizeof(*sem));
+ if (sem != NULL) {
+ /* TODO: Figure out the limit on the maximum value. */
+ sem->semid = sceKernelCreateSema("SDL sema", 0, initial_value, 255, NULL);
+ if (sem->semid < 0) {
+ SDL_SetError("Couldn't create semaphore");
+ free(sem);
+ sem = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+
+ return sem;
+}
+
+/* Free the semaphore */
+void SDL_DestroySemaphore(SDL_sem *sem)
+{
+ if (sem != NULL) {
+ if (sem->semid > 0) {
+ sceKernelDeleteSema(sem->semid);
+ sem->semid = 0;
+ }
+
+ free(sem);
+ }
+}
+
+/* TODO: This routine is a bit overloaded.
+ * If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass
+ * NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout
+ * is specified, convert it to microseconds. */
+int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
+{
+ Uint32 *pTimeout;
+ int res;
+
+ if (sem == NULL) {
+ SDL_SetError("Passed a NULL sem");
+ return 0;
+ }
+
+ if (timeout == 0) {
+ res = sceKernelPollSema(sem->semid, 1);
+ if (res < 0) {
+ return SDL_MUTEX_TIMEDOUT;
+ }
+ return 0;
+ }
+
+ if (timeout == SDL_MUTEX_MAXWAIT) {
+ pTimeout = NULL;
+ } else {
+ timeout *= 1000; /* Convert to microseconds. */
+ pTimeout = &timeout;
+ }
+
+ res = sceKernelWaitSema(sem->semid, 1, pTimeout);
+ switch (res) {
+ case SCE_KERNEL_ERROR_OK:
+ return 0;
+ case SCE_KERNEL_ERROR_WAIT_TIMEOUT:
+ return SDL_MUTEX_TIMEDOUT;
+ default:
+ return SDL_SetError("sceKernelWaitSema() failed");
+ }
+}
+
+int SDL_SemTryWait(SDL_sem *sem)
+{
+ return SDL_SemWaitTimeout(sem, 0);
+}
+
+int SDL_SemWait(SDL_sem *sem)
+{
+ return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
+}
+
+/* Returns the current count of the semaphore */
+Uint32 SDL_SemValue(SDL_sem *sem)
+{
+ SceKernelSemaInfo info;
+
+ if (sem == NULL) {
+ SDL_SetError("Passed a NULL sem");
+ return 0;
+ }
+
+ if (sceKernelReferSemaStatus(sem->semid, &info) >= 0) {
+ return info.currentCount;
+ }
+
+ return 0;
+}
+
+int SDL_SemPost(SDL_sem *sem)
+{
+ int res;
+
+ if (sem == NULL) {
+ return SDL_SetError("Passed a NULL sem");
+ }
+
+ res = sceKernelSignalSema(sem->semid, 1);
+ if (res < 0) {
+ return SDL_SetError("sceKernelSignalSema() failed");
+ }
+
+ return 0;
+}
+
+#endif /* SDL_THREAD_PSP */
+
+/* vim: ts=4 sw=4
+ */
diff --git a/source/3rd-party/SDL2/src/thread/psp/SDL_systhread.c b/source/3rd-party/SDL2/src/thread/psp/SDL_systhread.c
new file mode 100644
index 0000000..284f182
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/psp/SDL_systhread.c
@@ -0,0 +1,114 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_THREAD_PSP
+
+/* PSP thread management routines for SDL */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "SDL_error.h"
+#include "SDL_thread.h"
+#include "../SDL_systhread.h"
+#include "../SDL_thread_c.h"
+#include <pspkerneltypes.h>
+#include <pspthreadman.h>
+
+
+static int ThreadEntry(SceSize args, void *argp)
+{
+ SDL_RunThread(*(void **) argp);
+ return 0;
+}
+
+int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
+{
+ SceKernelThreadInfo status;
+ int priority = 32;
+
+ /* Set priority of new thread to the same as the current thread */
+ status.size = sizeof(SceKernelThreadInfo);
+ if (sceKernelReferThreadStatus(sceKernelGetThreadId(), &status) == 0) {
+ priority = status.currentPriority;
+ }
+
+ thread->handle = sceKernelCreateThread(thread->name, ThreadEntry,
+ priority, thread->stacksize ? ((int) thread->stacksize) : 0x8000,
+ PSP_THREAD_ATTR_VFPU, NULL);
+ if (thread->handle < 0) {
+ return SDL_SetError("sceKernelCreateThread() failed");
+ }
+
+ sceKernelStartThread(thread->handle, 4, &args);
+ return 0;
+}
+
+void SDL_SYS_SetupThread(const char *name)
+{
+ /* Do nothing. */
+}
+
+SDL_threadID SDL_ThreadID(void)
+{
+ return (SDL_threadID) sceKernelGetThreadId();
+}
+
+void SDL_SYS_WaitThread(SDL_Thread *thread)
+{
+ sceKernelWaitThreadEnd(thread->handle, NULL);
+ sceKernelDeleteThread(thread->handle);
+}
+
+void SDL_SYS_DetachThread(SDL_Thread *thread)
+{
+ /* !!! FIXME: is this correct? */
+ sceKernelDeleteThread(thread->handle);
+}
+
+void SDL_SYS_KillThread(SDL_Thread *thread)
+{
+ sceKernelTerminateDeleteThread(thread->handle);
+}
+
+int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
+{
+ int value;
+
+ if (priority == SDL_THREAD_PRIORITY_LOW) {
+ value = 19;
+ } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
+ value = -10;
+ } else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
+ value = -20;
+ } else {
+ value = 0;
+ }
+
+ return sceKernelChangeThreadPriority(sceKernelGetThreadId(),value);
+
+}
+
+#endif /* SDL_THREAD_PSP */
+
+/* vim: ts=4 sw=4
+ */
diff --git a/source/3rd-party/SDL2/src/thread/psp/SDL_systhread_c.h b/source/3rd-party/SDL2/src/thread/psp/SDL_systhread_c.h
new file mode 100644
index 0000000..ea26f81
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/psp/SDL_systhread_c.h
@@ -0,0 +1,24 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <pspkerneltypes.h>
+
+typedef SceUID SYS_ThreadHandle;
diff --git a/source/3rd-party/SDL2/src/thread/pthread/SDL_syscond.c b/source/3rd-party/SDL2/src/thread/pthread/SDL_syscond.c
new file mode 100644
index 0000000..d235780
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/pthread/SDL_syscond.c
@@ -0,0 +1,158 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "SDL_thread.h"
+#include "SDL_sysmutex_c.h"
+
+struct SDL_cond
+{
+ pthread_cond_t cond;
+};
+
+/* Create a condition variable */
+SDL_cond *
+SDL_CreateCond(void)
+{
+ SDL_cond *cond;
+
+ cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
+ if (cond) {
+ if (pthread_cond_init(&cond->cond, NULL) != 0) {
+ SDL_SetError("pthread_cond_init() failed");
+ SDL_free(cond);
+ cond = NULL;
+ }
+ }
+ return (cond);
+}
+
+/* Destroy a condition variable */
+void
+SDL_DestroyCond(SDL_cond * cond)
+{
+ if (cond) {
+ pthread_cond_destroy(&cond->cond);
+ SDL_free(cond);
+ }
+}
+
+/* Restart one of the threads that are waiting on the condition variable */
+int
+SDL_CondSignal(SDL_cond * cond)
+{
+ int retval;
+
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+ retval = 0;
+ if (pthread_cond_signal(&cond->cond) != 0) {
+ return SDL_SetError("pthread_cond_signal() failed");
+ }
+ return retval;
+}
+
+/* Restart all threads that are waiting on the condition variable */
+int
+SDL_CondBroadcast(SDL_cond * cond)
+{
+ int retval;
+
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+ retval = 0;
+ if (pthread_cond_broadcast(&cond->cond) != 0) {
+ return SDL_SetError("pthread_cond_broadcast() failed");
+ }
+ return retval;
+}
+
+int
+SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
+{
+ int retval;
+#ifndef HAVE_CLOCK_GETTIME
+ struct timeval delta;
+#endif
+ struct timespec abstime;
+
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ }
+
+#ifdef HAVE_CLOCK_GETTIME
+ clock_gettime(CLOCK_REALTIME, &abstime);
+
+ abstime.tv_nsec += (ms % 1000) * 1000000;
+ abstime.tv_sec += ms / 1000;
+#else
+ gettimeofday(&delta, NULL);
+
+ abstime.tv_sec = delta.tv_sec + (ms / 1000);
+ abstime.tv_nsec = (delta.tv_usec + (ms % 1000) * 1000) * 1000;
+#endif
+ if (abstime.tv_nsec > 1000000000) {
+ abstime.tv_sec += 1;
+ abstime.tv_nsec -= 1000000000;
+ }
+
+ tryagain:
+ retval = pthread_cond_timedwait(&cond->cond, &mutex->id, &abstime);
+ switch (retval) {
+ case EINTR:
+ goto tryagain;
+ /* break; -Wunreachable-code-break */
+ case ETIMEDOUT:
+ retval = SDL_MUTEX_TIMEDOUT;
+ break;
+ case 0:
+ break;
+ default:
+ retval = SDL_SetError("pthread_cond_timedwait() failed");
+ }
+ return retval;
+}
+
+/* Wait on the condition variable, unlocking the provided mutex.
+ The mutex must be locked before entering this function!
+ */
+int
+SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
+{
+ if (!cond) {
+ return SDL_SetError("Passed a NULL condition variable");
+ } else if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
+ return SDL_SetError("pthread_cond_wait() failed");
+ }
+ return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/pthread/SDL_sysmutex.c b/source/3rd-party/SDL2/src/thread/pthread/SDL_sysmutex.c
new file mode 100644
index 0000000..e514778
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/pthread/SDL_sysmutex.c
@@ -0,0 +1,195 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include <errno.h>
+#include <pthread.h>
+
+#include "SDL_thread.h"
+
+#if !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX && \
+ !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP
+#define FAKE_RECURSIVE_MUTEX 1
+#endif
+
+struct SDL_mutex
+{
+ pthread_mutex_t id;
+#if FAKE_RECURSIVE_MUTEX
+ int recursive;
+ pthread_t owner;
+#endif
+};
+
+SDL_mutex *
+SDL_CreateMutex(void)
+{
+ SDL_mutex *mutex;
+ pthread_mutexattr_t attr;
+
+ /* Allocate the structure */
+ mutex = (SDL_mutex *) SDL_calloc(1, sizeof(*mutex));
+ if (mutex) {
+ pthread_mutexattr_init(&attr);
+#if SDL_THREAD_PTHREAD_RECURSIVE_MUTEX
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+#elif SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP
+ pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
+#else
+ /* No extra attributes necessary */
+#endif
+ if (pthread_mutex_init(&mutex->id, &attr) != 0) {
+ SDL_SetError("pthread_mutex_init() failed");
+ SDL_free(mutex);
+ mutex = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return (mutex);
+}
+
+void
+SDL_DestroyMutex(SDL_mutex * mutex)
+{
+ if (mutex) {
+ pthread_mutex_destroy(&mutex->id);
+ SDL_free(mutex);
+ }
+}
+
+/* Lock the mutex */
+int
+SDL_LockMutex(SDL_mutex * mutex)
+{
+#if FAKE_RECURSIVE_MUTEX
+ pthread_t this_thread;
+#endif
+
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+#if FAKE_RECURSIVE_MUTEX
+ this_thread = pthread_self();
+ if (mutex->owner == this_thread) {
+ ++mutex->recursive;
+ } else {
+ /* The order of operations is important.
+ We set the locking thread id after we obtain the lock
+ so unlocks from other threads will fail.
+ */
+ if (pthread_mutex_lock(&mutex->id) == 0) {
+ mutex->owner = this_thread;
+ mutex->recursive = 0;
+ } else {
+ return SDL_SetError("pthread_mutex_lock() failed");
+ }
+ }
+#else
+ if (pthread_mutex_lock(&mutex->id) != 0) {
+ return SDL_SetError("pthread_mutex_lock() failed");
+ }
+#endif
+ return 0;
+}
+
+int
+SDL_TryLockMutex(SDL_mutex * mutex)
+{
+ int retval;
+ int result;
+#if FAKE_RECURSIVE_MUTEX
+ pthread_t this_thread;
+#endif
+
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ retval = 0;
+#if FAKE_RECURSIVE_MUTEX
+ this_thread = pthread_self();
+ if (mutex->owner == this_thread) {
+ ++mutex->recursive;
+ } else {
+ /* The order of operations is important.
+ We set the locking thread id after we obtain the lock
+ so unlocks from other threads will fail.
+ */
+ result = pthread_mutex_trylock(&mutex->id);
+ if (result == 0) {
+ mutex->owner = this_thread;
+ mutex->recursive = 0;
+ } else if (result == EBUSY) {
+ retval = SDL_MUTEX_TIMEDOUT;
+ } else {
+ retval = SDL_SetError("pthread_mutex_trylock() failed");
+ }
+ }
+#else
+ result = pthread_mutex_trylock(&mutex->id);
+ if (result != 0) {
+ if (result == EBUSY) {
+ retval = SDL_MUTEX_TIMEDOUT;
+ } else {
+ retval = SDL_SetError("pthread_mutex_trylock() failed");
+ }
+ }
+#endif
+ return retval;
+}
+
+int
+SDL_UnlockMutex(SDL_mutex * mutex)
+{
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+#if FAKE_RECURSIVE_MUTEX
+ /* We can only unlock the mutex if we own it */
+ if (pthread_self() == mutex->owner) {
+ if (mutex->recursive) {
+ --mutex->recursive;
+ } else {
+ /* The order of operations is important.
+ First reset the owner so another thread doesn't lock
+ the mutex and set the ownership before we reset it,
+ then release the lock semaphore.
+ */
+ mutex->owner = 0;
+ pthread_mutex_unlock(&mutex->id);
+ }
+ } else {
+ return SDL_SetError("mutex not owned by this thread");
+ }
+
+#else
+ if (pthread_mutex_unlock(&mutex->id) != 0) {
+ return SDL_SetError("pthread_mutex_unlock() failed");
+ }
+#endif /* FAKE_RECURSIVE_MUTEX */
+
+ return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/pthread/SDL_sysmutex_c.h b/source/3rd-party/SDL2/src/thread/pthread/SDL_sysmutex_c.h
new file mode 100644
index 0000000..27ac1da
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/pthread/SDL_sysmutex_c.h
@@ -0,0 +1,32 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_mutex_c_h_
+#define SDL_mutex_c_h_
+
+struct SDL_mutex
+{
+ pthread_mutex_t id;
+};
+
+#endif /* SDL_mutex_c_h_ */
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/pthread/SDL_syssem.c b/source/3rd-party/SDL2/src/thread/pthread/SDL_syssem.c
new file mode 100644
index 0000000..bdebf13
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/pthread/SDL_syssem.c
@@ -0,0 +1,209 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "SDL_thread.h"
+#include "SDL_timer.h"
+
+/* Wrapper around POSIX 1003.1b semaphores */
+
+#if defined(__MACOSX__) || defined(__IPHONEOS__)
+/* Mac OS X doesn't support sem_getvalue() as of version 10.4 */
+#include "../generic/SDL_syssem.c"
+#else
+
+struct SDL_semaphore
+{
+ sem_t sem;
+};
+
+/* Create a semaphore, initialized with value */
+SDL_sem *
+SDL_CreateSemaphore(Uint32 initial_value)
+{
+ SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem));
+ if (sem) {
+ if (sem_init(&sem->sem, 0, initial_value) < 0) {
+ SDL_SetError("sem_init() failed");
+ SDL_free(sem);
+ sem = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return sem;
+}
+
+void
+SDL_DestroySemaphore(SDL_sem * sem)
+{
+ if (sem) {
+ sem_destroy(&sem->sem);
+ SDL_free(sem);
+ }
+}
+
+int
+SDL_SemTryWait(SDL_sem * sem)
+{
+ int retval;
+
+ if (!sem) {
+ return SDL_SetError("Passed a NULL semaphore");
+ }
+ retval = SDL_MUTEX_TIMEDOUT;
+ if (sem_trywait(&sem->sem) == 0) {
+ retval = 0;
+ }
+ return retval;
+}
+
+int
+SDL_SemWait(SDL_sem * sem)
+{
+ int retval;
+
+ if (!sem) {
+ return SDL_SetError("Passed a NULL semaphore");
+ }
+
+ do {
+ retval = sem_wait(&sem->sem);
+ } while (retval < 0 && errno == EINTR);
+
+ if (retval < 0) {
+ retval = SDL_SetError("sem_wait() failed");
+ }
+ return retval;
+}
+
+int
+SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
+{
+ int retval;
+#ifdef HAVE_SEM_TIMEDWAIT
+#ifndef HAVE_CLOCK_GETTIME
+ struct timeval now;
+#endif
+ struct timespec ts_timeout;
+#else
+ Uint32 end;
+#endif
+
+ if (!sem) {
+ return SDL_SetError("Passed a NULL semaphore");
+ }
+
+ /* Try the easy cases first */
+ if (timeout == 0) {
+ return SDL_SemTryWait(sem);
+ }
+ if (timeout == SDL_MUTEX_MAXWAIT) {
+ return SDL_SemWait(sem);
+ }
+
+#ifdef HAVE_SEM_TIMEDWAIT
+ /* Setup the timeout. sem_timedwait doesn't wait for
+ * a lapse of time, but until we reach a certain time.
+ * This time is now plus the timeout.
+ */
+#ifdef HAVE_CLOCK_GETTIME
+ clock_gettime(CLOCK_REALTIME, &ts_timeout);
+
+ /* Add our timeout to current time */
+ ts_timeout.tv_nsec += (timeout % 1000) * 1000000;
+ ts_timeout.tv_sec += timeout / 1000;
+#else
+ gettimeofday(&now, NULL);
+
+ /* Add our timeout to current time */
+ ts_timeout.tv_sec = now.tv_sec + (timeout / 1000);
+ ts_timeout.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000;
+#endif
+
+ /* Wrap the second if needed */
+ if (ts_timeout.tv_nsec > 1000000000) {
+ ts_timeout.tv_sec += 1;
+ ts_timeout.tv_nsec -= 1000000000;
+ }
+
+ /* Wait. */
+ do {
+ retval = sem_timedwait(&sem->sem, &ts_timeout);
+ } while (retval < 0 && errno == EINTR);
+
+ if (retval < 0) {
+ if (errno == ETIMEDOUT) {
+ retval = SDL_MUTEX_TIMEDOUT;
+ } else {
+ SDL_SetError("sem_timedwait returned an error: %s", strerror(errno));
+ }
+ }
+#else
+ end = SDL_GetTicks() + timeout;
+ while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) {
+ if (SDL_TICKS_PASSED(SDL_GetTicks(), end)) {
+ break;
+ }
+ SDL_Delay(1);
+ }
+#endif /* HAVE_SEM_TIMEDWAIT */
+
+ return retval;
+}
+
+Uint32
+SDL_SemValue(SDL_sem * sem)
+{
+ int ret = 0;
+ if (sem) {
+ sem_getvalue(&sem->sem, &ret);
+ if (ret < 0) {
+ ret = 0;
+ }
+ }
+ return (Uint32) ret;
+}
+
+int
+SDL_SemPost(SDL_sem * sem)
+{
+ int retval;
+
+ if (!sem) {
+ return SDL_SetError("Passed a NULL semaphore");
+ }
+
+ retval = sem_post(&sem->sem);
+ if (retval < 0) {
+ SDL_SetError("sem_post() failed");
+ }
+ return retval;
+}
+
+#endif /* __MACOSX__ */
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/pthread/SDL_systhread.c b/source/3rd-party/SDL2/src/thread/pthread/SDL_systhread.c
new file mode 100644
index 0000000..ec32937
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/pthread/SDL_systhread.c
@@ -0,0 +1,324 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+
+#include <pthread.h>
+
+#if HAVE_PTHREAD_NP_H
+#include <pthread_np.h>
+#endif
+
+#include <signal.h>
+
+#ifdef __LINUX__
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "../../core/linux/SDL_dbus.h"
+#endif /* __LINUX__ */
+
+#if defined(__LINUX__) || defined(__MACOSX__) || defined(__IPHONEOS__)
+#include <dlfcn.h>
+#ifndef RTLD_DEFAULT
+#define RTLD_DEFAULT NULL
+#endif
+#endif
+
+#include "SDL_log.h"
+#include "SDL_platform.h"
+#include "SDL_thread.h"
+#include "../SDL_thread_c.h"
+#include "../SDL_systhread.h"
+#ifdef __ANDROID__
+#include "../../core/android/SDL_android.h"
+#endif
+
+#ifdef __HAIKU__
+#include <kernel/OS.h>
+#endif
+
+#include "SDL_assert.h"
+
+#ifndef __NACL__
+/* List of signals to mask in the subthreads */
+static const int sig_list[] = {
+ SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
+ SIGVTALRM, SIGPROF, 0
+};
+#endif
+
+static void *
+RunThread(void *data)
+{
+#ifdef __ANDROID__
+ Android_JNI_SetupThread();
+#endif
+ SDL_RunThread(data);
+ return NULL;
+}
+
+#if defined(__MACOSX__) || defined(__IPHONEOS__)
+static SDL_bool checked_setname = SDL_FALSE;
+static int (*ppthread_setname_np)(const char*) = NULL;
+#elif defined(__LINUX__)
+static SDL_bool checked_setname = SDL_FALSE;
+static int (*ppthread_setname_np)(pthread_t, const char*) = NULL;
+#endif
+int
+SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
+{
+ pthread_attr_t type;
+
+ /* do this here before any threads exist, so there's no race condition. */
+ #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
+ if (!checked_setname) {
+ void *fn = dlsym(RTLD_DEFAULT, "pthread_setname_np");
+ #if defined(__MACOSX__) || defined(__IPHONEOS__)
+ ppthread_setname_np = (int(*)(const char*)) fn;
+ #elif defined(__LINUX__)
+ ppthread_setname_np = (int(*)(pthread_t, const char*)) fn;
+ #endif
+ checked_setname = SDL_TRUE;
+ }
+ #endif
+
+ /* Set the thread attributes */
+ if (pthread_attr_init(&type) != 0) {
+ return SDL_SetError("Couldn't initialize pthread attributes");
+ }
+ pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
+
+ /* Set caller-requested stack size. Otherwise: use the system default. */
+ if (thread->stacksize) {
+ pthread_attr_setstacksize(&type, (size_t) thread->stacksize);
+ }
+
+ /* Create the thread and go! */
+ if (pthread_create(&thread->handle, &type, RunThread, args) != 0) {
+ return SDL_SetError("Not enough resources to create thread");
+ }
+
+ return 0;
+}
+
+void
+SDL_SYS_SetupThread(const char *name)
+{
+#if !defined(__NACL__)
+ int i;
+ sigset_t mask;
+#endif /* !__NACL__ */
+
+ if (name != NULL) {
+ #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
+ SDL_assert(checked_setname);
+ if (ppthread_setname_np != NULL) {
+ #if defined(__MACOSX__) || defined(__IPHONEOS__)
+ ppthread_setname_np(name);
+ #elif defined(__LINUX__)
+ ppthread_setname_np(pthread_self(), name);
+ #endif
+ }
+ #elif HAVE_PTHREAD_SETNAME_NP
+ #if defined(__NETBSD__)
+ pthread_setname_np(pthread_self(), "%s", name);
+ #else
+ pthread_setname_np(pthread_self(), name);
+ #endif
+ #elif HAVE_PTHREAD_SET_NAME_NP
+ pthread_set_name_np(pthread_self(), name);
+ #elif defined(__HAIKU__)
+ /* The docs say the thread name can't be longer than B_OS_NAME_LENGTH. */
+ char namebuf[B_OS_NAME_LENGTH];
+ SDL_snprintf(namebuf, sizeof (namebuf), "%s", name);
+ namebuf[sizeof (namebuf) - 1] = '\0';
+ rename_thread(find_thread(NULL), namebuf);
+ #endif
+ }
+
+ /* NativeClient does not yet support signals.*/
+#if !defined(__NACL__)
+ /* Mask asynchronous signals for this thread */
+ sigemptyset(&mask);
+ for (i = 0; sig_list[i]; ++i) {
+ sigaddset(&mask, sig_list[i]);
+ }
+ pthread_sigmask(SIG_BLOCK, &mask, 0);
+#endif /* !__NACL__ */
+
+
+#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
+ /* Allow ourselves to be asynchronously cancelled */
+ {
+ int oldstate;
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
+ }
+#endif
+}
+
+SDL_threadID
+SDL_ThreadID(void)
+{
+ return ((SDL_threadID) pthread_self());
+}
+
+#if __LINUX__
+/* d-bus queries to org.freedesktop.RealtimeKit1. */
+#if SDL_USE_LIBDBUS
+
+#define RTKIT_DBUS_NODE "org.freedesktop.RealtimeKit1"
+#define RTKIT_DBUS_PATH "/org/freedesktop/RealtimeKit1"
+#define RTKIT_DBUS_INTERFACE "org.freedesktop.RealtimeKit1"
+
+static pthread_once_t rtkit_initialize_once = PTHREAD_ONCE_INIT;
+static Sint32 rtkit_min_nice_level = -20;
+
+static void
+rtkit_initialize()
+{
+ SDL_DBusContext *dbus = SDL_DBus_GetContext();
+
+ /* Try getting minimum nice level: this is often greater than PRIO_MIN (-20). */
+ if (!dbus || !SDL_DBus_QueryPropertyOnConnection(dbus->system_conn, RTKIT_DBUS_NODE, RTKIT_DBUS_PATH, RTKIT_DBUS_INTERFACE, "MinNiceLevel",
+ DBUS_TYPE_INT32, &rtkit_min_nice_level)) {
+ rtkit_min_nice_level = -20;
+ }
+}
+
+static SDL_bool
+rtkit_setpriority(pid_t thread, int nice_level)
+{
+ Uint64 ui64 = (Uint64)thread;
+ Sint32 si32 = (Sint32)nice_level;
+ SDL_DBusContext *dbus = SDL_DBus_GetContext();
+
+ pthread_once(&rtkit_initialize_once, rtkit_initialize);
+
+ if (si32 < rtkit_min_nice_level)
+ si32 = rtkit_min_nice_level;
+
+ if (!dbus || !SDL_DBus_CallMethodOnConnection(dbus->system_conn,
+ RTKIT_DBUS_NODE, RTKIT_DBUS_PATH, RTKIT_DBUS_INTERFACE, "MakeThreadHighPriority",
+ DBUS_TYPE_UINT64, &ui64, DBUS_TYPE_INT32, &si32, DBUS_TYPE_INVALID,
+ DBUS_TYPE_INVALID)) {
+ return SDL_FALSE;
+ }
+ return SDL_TRUE;
+}
+
+#else
+
+static SDL_bool
+rtkit_setpriority(pid_t thread, int nice_level)
+{
+ return SDL_FALSE;
+}
+
+#endif /* !SDL_USE_LIBDBUS */
+
+int
+SDL_LinuxSetThreadPriority(Sint64 threadID, int priority)
+{
+ if (setpriority(PRIO_PROCESS, (id_t)threadID, priority) < 0) {
+ /* Note that this fails if you're trying to set high priority
+ and you don't have root permission. BUT DON'T RUN AS ROOT!
+
+ You can grant the ability to increase thread priority by
+ running the following command on your application binary:
+ sudo setcap 'cap_sys_nice=eip' <application>
+
+ Let's try setting priority with RealtimeKit...
+
+ README and sample code at:
+ http://git.0pointer.net/rtkit.git
+ */
+ if (rtkit_setpriority((pid_t)threadID, priority) == SDL_FALSE) {
+ return SDL_SetError("setpriority() failed");
+ }
+ }
+ return 0;
+}
+#endif /* __LINUX__ */
+
+int
+SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
+{
+#if __NACL__
+ /* FIXME: Setting thread priority does not seem to be supported in NACL */
+ return 0;
+#elif __LINUX__
+ int value;
+ pid_t thread = syscall(SYS_gettid);
+
+ if (priority == SDL_THREAD_PRIORITY_LOW) {
+ value = 19;
+ } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
+ value = -10;
+ } else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
+ value = -20;
+ } else {
+ value = 0;
+ }
+ return SDL_LinuxSetThreadPriority(thread, value);
+#else
+ struct sched_param sched;
+ int policy;
+ pthread_t thread = pthread_self();
+
+ if (pthread_getschedparam(thread, &policy, &sched) != 0) {
+ return SDL_SetError("pthread_getschedparam() failed");
+ }
+ if (priority == SDL_THREAD_PRIORITY_LOW) {
+ sched.sched_priority = sched_get_priority_min(policy);
+ } else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
+ sched.sched_priority = sched_get_priority_max(policy);
+ } else {
+ int min_priority = sched_get_priority_min(policy);
+ int max_priority = sched_get_priority_max(policy);
+ sched.sched_priority = (min_priority + (max_priority - min_priority) / 2);
+ if (priority == SDL_THREAD_PRIORITY_HIGH) {
+ sched.sched_priority += ((max_priority - min_priority) / 4);
+ }
+ }
+ if (pthread_setschedparam(thread, policy, &sched) != 0) {
+ return SDL_SetError("pthread_setschedparam() failed");
+ }
+ return 0;
+#endif /* linux */
+}
+
+void
+SDL_SYS_WaitThread(SDL_Thread * thread)
+{
+ pthread_join(thread->handle, 0);
+}
+
+void
+SDL_SYS_DetachThread(SDL_Thread * thread)
+{
+ pthread_detach(thread->handle);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/pthread/SDL_systhread_c.h b/source/3rd-party/SDL2/src/thread/pthread/SDL_systhread_c.h
new file mode 100644
index 0000000..898c219
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/pthread/SDL_systhread_c.h
@@ -0,0 +1,27 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#include <pthread.h>
+
+typedef pthread_t SYS_ThreadHandle;
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/pthread/SDL_systls.c b/source/3rd-party/SDL2/src/thread/pthread/SDL_systls.c
new file mode 100644
index 0000000..c580595
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/pthread/SDL_systls.c
@@ -0,0 +1,70 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+#include "SDL_thread.h"
+#include "../SDL_systhread.h"
+#include "../SDL_thread_c.h"
+
+#include <pthread.h>
+
+
+#define INVALID_PTHREAD_KEY ((pthread_key_t)-1)
+
+static pthread_key_t thread_local_storage = INVALID_PTHREAD_KEY;
+static SDL_bool generic_local_storage = SDL_FALSE;
+
+SDL_TLSData *
+SDL_SYS_GetTLSData(void)
+{
+ if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
+ static SDL_SpinLock lock;
+ SDL_AtomicLock(&lock);
+ if (thread_local_storage == INVALID_PTHREAD_KEY && !generic_local_storage) {
+ pthread_key_t storage;
+ if (pthread_key_create(&storage, NULL) == 0) {
+ SDL_MemoryBarrierRelease();
+ thread_local_storage = storage;
+ } else {
+ generic_local_storage = SDL_TRUE;
+ }
+ }
+ SDL_AtomicUnlock(&lock);
+ }
+ if (generic_local_storage) {
+ return SDL_Generic_GetTLSData();
+ }
+ SDL_MemoryBarrierAcquire();
+ return (SDL_TLSData *)pthread_getspecific(thread_local_storage);
+}
+
+int
+SDL_SYS_SetTLSData(SDL_TLSData *data)
+{
+ if (generic_local_storage) {
+ return SDL_Generic_SetTLSData(data);
+ }
+ if (pthread_setspecific(thread_local_storage, data) != 0) {
+ return SDL_SetError("pthread_setspecific() failed");
+ }
+ return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/stdcpp/SDL_syscond.cpp b/source/3rd-party/SDL2/src/thread/stdcpp/SDL_syscond.cpp
new file mode 100644
index 0000000..32c7c4b
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/stdcpp/SDL_syscond.cpp
@@ -0,0 +1,164 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+extern "C" {
+#include "SDL_thread.h"
+}
+
+#include <chrono>
+#include <condition_variable>
+#include <ratio>
+#include <system_error>
+
+#include "SDL_sysmutex_c.h"
+
+struct SDL_cond
+{
+ std::condition_variable_any cpp_cond;
+};
+
+/* Create a condition variable */
+extern "C"
+SDL_cond *
+SDL_CreateCond(void)
+{
+ /* Allocate and initialize the condition variable */
+ try {
+ SDL_cond * cond = new SDL_cond;
+ return cond;
+ } catch (std::system_error & ex) {
+ SDL_SetError("unable to create a C++ condition variable: code=%d; %s", ex.code(), ex.what());
+ return NULL;
+ } catch (std::bad_alloc &) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+}
+
+/* Destroy a condition variable */
+extern "C"
+void
+SDL_DestroyCond(SDL_cond * cond)
+{
+ if (cond) {
+ delete cond;
+ }
+}
+
+/* Restart one of the threads that are waiting on the condition variable */
+extern "C"
+int
+SDL_CondSignal(SDL_cond * cond)
+{
+ if (!cond) {
+ SDL_SetError("Passed a NULL condition variable");
+ return -1;
+ }
+
+ cond->cpp_cond.notify_one();
+ return 0;
+}
+
+/* Restart all threads that are waiting on the condition variable */
+extern "C"
+int
+SDL_CondBroadcast(SDL_cond * cond)
+{
+ if (!cond) {
+ SDL_SetError("Passed a NULL condition variable");
+ return -1;
+ }
+
+ cond->cpp_cond.notify_all();
+ return 0;
+}
+
+/* Wait on the condition variable for at most 'ms' milliseconds.
+ The mutex must be locked before entering this function!
+ The mutex is unlocked during the wait, and locked again after the wait.
+
+Typical use:
+
+Thread A:
+ SDL_LockMutex(lock);
+ while ( ! condition ) {
+ SDL_CondWait(cond, lock);
+ }
+ SDL_UnlockMutex(lock);
+
+Thread B:
+ SDL_LockMutex(lock);
+ ...
+ condition = true;
+ ...
+ SDL_CondSignal(cond);
+ SDL_UnlockMutex(lock);
+ */
+extern "C"
+int
+SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
+{
+ if (!cond) {
+ SDL_SetError("Passed a NULL condition variable");
+ return -1;
+ }
+
+ if (!mutex) {
+ SDL_SetError("Passed a NULL mutex variable");
+ return -1;
+ }
+
+ try {
+ std::unique_lock<std::recursive_mutex> cpp_lock(mutex->cpp_mutex, std::adopt_lock_t());
+ if (ms == SDL_MUTEX_MAXWAIT) {
+ cond->cpp_cond.wait(
+ cpp_lock
+ );
+ cpp_lock.release();
+ return 0;
+ } else {
+ auto wait_result = cond->cpp_cond.wait_for(
+ cpp_lock,
+ std::chrono::duration<Uint32, std::milli>(ms)
+ );
+ cpp_lock.release();
+ if (wait_result == std::cv_status::timeout) {
+ return SDL_MUTEX_TIMEDOUT;
+ } else {
+ return 0;
+ }
+ }
+ } catch (std::system_error & ex) {
+ SDL_SetError("unable to wait on a C++ condition variable: code=%d; %s", ex.code(), ex.what());
+ return -1;
+ }
+}
+
+/* Wait on the condition variable forever */
+extern "C"
+int
+SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
+{
+ return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/stdcpp/SDL_sysmutex.cpp b/source/3rd-party/SDL2/src/thread/stdcpp/SDL_sysmutex.cpp
new file mode 100644
index 0000000..667d36b
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/stdcpp/SDL_sysmutex.cpp
@@ -0,0 +1,111 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+extern "C" {
+#include "SDL_thread.h"
+#include "SDL_systhread_c.h"
+#include "SDL_log.h"
+}
+
+#include <system_error>
+
+#include "SDL_sysmutex_c.h"
+#include <Windows.h>
+
+
+/* Create a mutex */
+extern "C"
+SDL_mutex *
+SDL_CreateMutex(void)
+{
+ /* Allocate and initialize the mutex */
+ try {
+ SDL_mutex * mutex = new SDL_mutex;
+ return mutex;
+ } catch (std::system_error & ex) {
+ SDL_SetError("unable to create a C++ mutex: code=%d; %s", ex.code(), ex.what());
+ return NULL;
+ } catch (std::bad_alloc &) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+}
+
+/* Free the mutex */
+extern "C"
+void
+SDL_DestroyMutex(SDL_mutex * mutex)
+{
+ if (mutex) {
+ delete mutex;
+ }
+}
+
+/* Lock the semaphore */
+extern "C"
+int
+SDL_mutexP(SDL_mutex * mutex)
+{
+ if (mutex == NULL) {
+ SDL_SetError("Passed a NULL mutex");
+ return -1;
+ }
+
+ try {
+ mutex->cpp_mutex.lock();
+ return 0;
+ } catch (std::system_error & ex) {
+ SDL_SetError("unable to lock a C++ mutex: code=%d; %s", ex.code(), ex.what());
+ return -1;
+ }
+}
+
+/* TryLock the mutex */
+int
+SDL_TryLockMutex(SDL_mutex * mutex)
+{
+ int retval = 0;
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ if (mutex->cpp_mutex.try_lock() == false) {
+ retval = SDL_MUTEX_TIMEDOUT;
+ }
+ return retval;
+}
+
+/* Unlock the mutex */
+extern "C"
+int
+SDL_mutexV(SDL_mutex * mutex)
+{
+ if (mutex == NULL) {
+ SDL_SetError("Passed a NULL mutex");
+ return -1;
+ }
+
+ mutex->cpp_mutex.unlock();
+ return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/stdcpp/SDL_sysmutex_c.h b/source/3rd-party/SDL2/src/thread/stdcpp/SDL_sysmutex_c.h
new file mode 100644
index 0000000..000288f
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/stdcpp/SDL_sysmutex_c.h
@@ -0,0 +1,30 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+#include <mutex>
+
+struct SDL_mutex
+{
+ std::recursive_mutex cpp_mutex;
+};
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/stdcpp/SDL_systhread.cpp b/source/3rd-party/SDL2/src/thread/stdcpp/SDL_systhread.cpp
new file mode 100644
index 0000000..3020f1c
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/stdcpp/SDL_systhread.cpp
@@ -0,0 +1,168 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+/* Thread management routines for SDL */
+
+extern "C" {
+#include "SDL_thread.h"
+#include "../SDL_thread_c.h"
+#include "../SDL_systhread.h"
+#include "SDL_log.h"
+}
+
+#include <mutex>
+#include <thread>
+#include <system_error>
+
+#ifdef __WINRT__
+#include <Windows.h>
+#endif
+
+static void
+RunThread(void *args)
+{
+ SDL_RunThread(args);
+}
+
+extern "C"
+int
+SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
+{
+ try {
+ // !!! FIXME: no way to set a thread stack size here.
+ std::thread cpp_thread(RunThread, args);
+ thread->handle = (void *) new std::thread(std::move(cpp_thread));
+ return 0;
+ } catch (std::system_error & ex) {
+ SDL_SetError("unable to start a C++ thread: code=%d; %s", ex.code(), ex.what());
+ return -1;
+ } catch (std::bad_alloc &) {
+ SDL_OutOfMemory();
+ return -1;
+ }
+}
+
+extern "C"
+void
+SDL_SYS_SetupThread(const char *name)
+{
+ // Make sure a thread ID gets assigned ASAP, for debugging purposes:
+ SDL_ThreadID();
+ return;
+}
+
+extern "C"
+SDL_threadID
+SDL_ThreadID(void)
+{
+#ifdef __WINRT__
+ return GetCurrentThreadId();
+#else
+ // HACK: Mimick a thread ID, if one isn't otherwise available.
+ static thread_local SDL_threadID current_thread_id = 0;
+ static SDL_threadID next_thread_id = 1;
+ static std::mutex next_thread_id_mutex;
+
+ if (current_thread_id == 0) {
+ std::lock_guard<std::mutex> lock(next_thread_id_mutex);
+ current_thread_id = next_thread_id;
+ ++next_thread_id;
+ }
+
+ return current_thread_id;
+#endif
+}
+
+extern "C"
+int
+SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
+{
+ // Thread priorities do not look to be settable via C++11's thread
+ // interface, at least as of this writing (Nov 2012). std::thread does
+ // provide access to the OS' native handle, however, and some form of
+ // priority-setting could, in theory, be done through this interface.
+ //
+ // WinRT: UPDATE (Aug 20, 2013): thread priorities cannot be changed
+ // on WinRT, at least not for any thread that's already been created.
+ // WinRT threads appear to be based off of the WinRT class,
+ // ThreadPool, more info on which can be found at:
+ // http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.threading.threadpool.aspx
+ //
+ // For compatibility sake, 0 will be returned here.
+ return (0);
+}
+
+extern "C"
+void
+SDL_SYS_WaitThread(SDL_Thread * thread)
+{
+ if ( ! thread) {
+ return;
+ }
+
+ try {
+ std::thread * cpp_thread = (std::thread *) thread->handle;
+ if (cpp_thread->joinable()) {
+ cpp_thread->join();
+ }
+ } catch (std::system_error &) {
+ // An error occurred when joining the thread. SDL_WaitThread does not,
+ // however, seem to provide a means to report errors to its callers
+ // though!
+ }
+}
+
+extern "C"
+void
+SDL_SYS_DetachThread(SDL_Thread * thread)
+{
+ if ( ! thread) {
+ return;
+ }
+
+ try {
+ std::thread * cpp_thread = (std::thread *) thread->handle;
+ if (cpp_thread->joinable()) {
+ cpp_thread->detach();
+ }
+ } catch (std::system_error &) {
+ // An error occurred when detaching the thread. SDL_DetachThread does not,
+ // however, seem to provide a means to report errors to its callers
+ // though!
+ }
+}
+
+extern "C"
+SDL_TLSData *
+SDL_SYS_GetTLSData(void)
+{
+ return SDL_Generic_GetTLSData();
+}
+
+extern "C"
+int
+SDL_SYS_SetTLSData(SDL_TLSData *data)
+{
+ return SDL_Generic_SetTLSData(data);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/stdcpp/SDL_systhread_c.h b/source/3rd-party/SDL2/src/thread/stdcpp/SDL_systhread_c.h
new file mode 100644
index 0000000..ee4764d
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/stdcpp/SDL_systhread_c.h
@@ -0,0 +1,26 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+/* For a thread handle, use a void pointer to a std::thread */
+typedef void * SYS_ThreadHandle;
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/windows/SDL_sysmutex.c b/source/3rd-party/SDL2/src/thread/windows/SDL_sysmutex.c
new file mode 100644
index 0000000..119e62b
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/windows/SDL_sysmutex.c
@@ -0,0 +1,110 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_THREAD_WINDOWS
+
+/* Mutex functions using the Win32 API */
+
+#include "../../core/windows/SDL_windows.h"
+
+#include "SDL_mutex.h"
+
+
+struct SDL_mutex
+{
+ CRITICAL_SECTION cs;
+};
+
+/* Create a mutex */
+SDL_mutex *
+SDL_CreateMutex(void)
+{
+ SDL_mutex *mutex;
+
+ /* Allocate mutex memory */
+ mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
+ if (mutex) {
+ /* Initialize */
+ /* On SMP systems, a non-zero spin count generally helps performance */
+#if __WINRT__
+ InitializeCriticalSectionEx(&mutex->cs, 2000, 0);
+#else
+ InitializeCriticalSectionAndSpinCount(&mutex->cs, 2000);
+#endif
+ } else {
+ SDL_OutOfMemory();
+ }
+ return (mutex);
+}
+
+/* Free the mutex */
+void
+SDL_DestroyMutex(SDL_mutex * mutex)
+{
+ if (mutex) {
+ DeleteCriticalSection(&mutex->cs);
+ SDL_free(mutex);
+ }
+}
+
+/* Lock the mutex */
+int
+SDL_LockMutex(SDL_mutex * mutex)
+{
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ EnterCriticalSection(&mutex->cs);
+ return (0);
+}
+
+/* TryLock the mutex */
+int
+SDL_TryLockMutex(SDL_mutex * mutex)
+{
+ int retval = 0;
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ if (TryEnterCriticalSection(&mutex->cs) == 0) {
+ retval = SDL_MUTEX_TIMEDOUT;
+ }
+ return retval;
+}
+
+/* Unlock the mutex */
+int
+SDL_UnlockMutex(SDL_mutex * mutex)
+{
+ if (mutex == NULL) {
+ return SDL_SetError("Passed a NULL mutex");
+ }
+
+ LeaveCriticalSection(&mutex->cs);
+ return (0);
+}
+
+#endif /* SDL_THREAD_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/windows/SDL_syssem.c b/source/3rd-party/SDL2/src/thread/windows/SDL_syssem.c
new file mode 100644
index 0000000..dcb36fa
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/windows/SDL_syssem.c
@@ -0,0 +1,152 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_THREAD_WINDOWS
+
+/* Semaphore functions using the Win32 API */
+
+#include "../../core/windows/SDL_windows.h"
+
+#include "SDL_thread.h"
+
+struct SDL_semaphore
+{
+ HANDLE id;
+ LONG count;
+};
+
+
+/* Create a semaphore */
+SDL_sem *
+SDL_CreateSemaphore(Uint32 initial_value)
+{
+ SDL_sem *sem;
+
+ /* Allocate sem memory */
+ sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
+ if (sem) {
+ /* Create the semaphore, with max value 32K */
+#if __WINRT__
+ sem->id = CreateSemaphoreEx(NULL, initial_value, 32 * 1024, NULL, 0, SEMAPHORE_ALL_ACCESS);
+#else
+ sem->id = CreateSemaphore(NULL, initial_value, 32 * 1024, NULL);
+#endif
+ sem->count = initial_value;
+ if (!sem->id) {
+ SDL_SetError("Couldn't create semaphore");
+ SDL_free(sem);
+ sem = NULL;
+ }
+ } else {
+ SDL_OutOfMemory();
+ }
+ return (sem);
+}
+
+/* Free the semaphore */
+void
+SDL_DestroySemaphore(SDL_sem * sem)
+{
+ if (sem) {
+ if (sem->id) {
+ CloseHandle(sem->id);
+ sem->id = 0;
+ }
+ SDL_free(sem);
+ }
+}
+
+int
+SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
+{
+ int retval;
+ DWORD dwMilliseconds;
+
+ if (!sem) {
+ return SDL_SetError("Passed a NULL sem");
+ }
+
+ if (timeout == SDL_MUTEX_MAXWAIT) {
+ dwMilliseconds = INFINITE;
+ } else {
+ dwMilliseconds = (DWORD) timeout;
+ }
+ switch (WaitForSingleObjectEx(sem->id, dwMilliseconds, FALSE)) {
+ case WAIT_OBJECT_0:
+ InterlockedDecrement(&sem->count);
+ retval = 0;
+ break;
+ case WAIT_TIMEOUT:
+ retval = SDL_MUTEX_TIMEDOUT;
+ break;
+ default:
+ retval = SDL_SetError("WaitForSingleObject() failed");
+ break;
+ }
+ return retval;
+}
+
+int
+SDL_SemTryWait(SDL_sem * sem)
+{
+ return SDL_SemWaitTimeout(sem, 0);
+}
+
+int
+SDL_SemWait(SDL_sem * sem)
+{
+ return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
+}
+
+/* Returns the current count of the semaphore */
+Uint32
+SDL_SemValue(SDL_sem * sem)
+{
+ if (!sem) {
+ SDL_SetError("Passed a NULL sem");
+ return 0;
+ }
+ return (Uint32)sem->count;
+}
+
+int
+SDL_SemPost(SDL_sem * sem)
+{
+ if (!sem) {
+ return SDL_SetError("Passed a NULL sem");
+ }
+ /* Increase the counter in the first place, because
+ * after a successful release the semaphore may
+ * immediately get destroyed by another thread which
+ * is waiting for this semaphore.
+ */
+ InterlockedIncrement(&sem->count);
+ if (ReleaseSemaphore(sem->id, 1, NULL) == FALSE) {
+ InterlockedDecrement(&sem->count); /* restore */
+ return SDL_SetError("ReleaseSemaphore() failed");
+ }
+ return 0;
+}
+
+#endif /* SDL_THREAD_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/windows/SDL_systhread.c b/source/3rd-party/SDL2/src/thread/windows/SDL_systhread.c
new file mode 100644
index 0000000..251510d
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/windows/SDL_systhread.c
@@ -0,0 +1,260 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_THREAD_WINDOWS
+
+/* Win32 thread management routines for SDL */
+
+#include "SDL_hints.h"
+#include "SDL_thread.h"
+#include "../SDL_thread_c.h"
+#include "../SDL_systhread.h"
+#include "SDL_systhread_c.h"
+
+#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+/* We'll use the C library from this DLL */
+#include <process.h>
+
+#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
+#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
+#endif
+
+/* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */
+#if (defined(__MINGW32__) && (__GNUC__ < 4))
+typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
+ unsigned (__stdcall *func)(void *), void *arg,
+ unsigned, unsigned *threadID);
+typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code);
+
+#elif defined(__WATCOMC__)
+/* This is for Watcom targets except OS2 */
+#if __WATCOMC__ < 1240
+#define __watcall
+#endif
+typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *,
+ unsigned,
+ unsigned
+ (__stdcall *
+ func) (void
+ *),
+ void *arg,
+ unsigned,
+ unsigned
+ *threadID);
+typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
+
+#else
+typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
+ unsigned (__stdcall *
+ func) (void
+ *),
+ void *arg, unsigned,
+ unsigned *threadID);
+typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
+#endif
+#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
+
+
+typedef struct ThreadStartParms
+{
+ void *args;
+ pfnSDL_CurrentEndThread pfnCurrentEndThread;
+} tThreadStartParms, *pThreadStartParms;
+
+static DWORD
+RunThread(void *data)
+{
+ pThreadStartParms pThreadParms = (pThreadStartParms) data;
+ pfnSDL_CurrentEndThread pfnEndThread = pThreadParms->pfnCurrentEndThread;
+ void *args = pThreadParms->args;
+ SDL_free(pThreadParms);
+ SDL_RunThread(args);
+ if (pfnEndThread != NULL)
+ pfnEndThread(0);
+ return (0);
+}
+
+static DWORD WINAPI
+RunThreadViaCreateThread(LPVOID data)
+{
+ return RunThread(data);
+}
+
+static unsigned __stdcall
+RunThreadViaBeginThreadEx(void *data)
+{
+ return (unsigned) RunThread(data);
+}
+
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+int
+SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread)
+{
+#elif defined(__CYGWIN__) || defined(__WINRT__)
+int
+SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
+{
+ pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
+ pfnSDL_CurrentEndThread pfnEndThread = NULL;
+#else
+int
+SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
+{
+ pfnSDL_CurrentBeginThread pfnBeginThread = (pfnSDL_CurrentBeginThread)_beginthreadex;
+ pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)_endthreadex;
+#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
+ pThreadStartParms pThreadParms =
+ (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
+ const DWORD flags = thread->stacksize ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0;
+ if (!pThreadParms) {
+ return SDL_OutOfMemory();
+ }
+ /* Save the function which we will have to call to clear the RTL of calling app! */
+ pThreadParms->pfnCurrentEndThread = pfnEndThread;
+ /* Also save the real parameters we have to pass to thread function */
+ pThreadParms->args = args;
+
+ /* thread->stacksize == 0 means "system default", same as win32 expects */
+ if (pfnBeginThread) {
+ unsigned threadid = 0;
+ thread->handle = (SYS_ThreadHandle)
+ ((size_t) pfnBeginThread(NULL, (unsigned int) thread->stacksize,
+ RunThreadViaBeginThreadEx,
+ pThreadParms, flags, &threadid));
+ } else {
+ DWORD threadid = 0;
+ thread->handle = CreateThread(NULL, thread->stacksize,
+ RunThreadViaCreateThread,
+ pThreadParms, flags, &threadid);
+ }
+ if (thread->handle == NULL) {
+ return SDL_SetError("Not enough resources to create thread");
+ }
+ return 0;
+}
+
+#pragma pack(push,8)
+typedef struct tagTHREADNAME_INFO
+{
+ DWORD dwType; /* must be 0x1000 */
+ LPCSTR szName; /* pointer to name (in user addr space) */
+ DWORD dwThreadID; /* thread ID (-1=caller thread) */
+ DWORD dwFlags; /* reserved for future use, must be zero */
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+
+typedef HRESULT (WINAPI *pfnSetThreadDescription)(HANDLE, PCWSTR);
+
+void
+SDL_SYS_SetupThread(const char *name)
+{
+ if (name != NULL) {
+ #ifndef __WINRT__ /* !!! FIXME: There's no LoadLibrary() in WinRT; don't know if SetThreadDescription is available there at all at the moment. */
+ static pfnSetThreadDescription pSetThreadDescription = NULL;
+ static HMODULE kernel32 = 0;
+
+ if (!kernel32) {
+ kernel32 = LoadLibraryW(L"kernel32.dll");
+ if (kernel32) {
+ pSetThreadDescription = (pfnSetThreadDescription) GetProcAddress(kernel32, "SetThreadDescription");
+ }
+ }
+
+ if (pSetThreadDescription != NULL) {
+ WCHAR *strw = WIN_UTF8ToString(name);
+ if (strw) {
+ pSetThreadDescription(GetCurrentThread(), strw);
+ SDL_free(strw);
+ }
+ }
+ #endif
+
+ /* Presumably some version of Visual Studio will understand SetThreadDescription(),
+ but we still need to deal with older OSes and debuggers. Set it with the arcane
+ exception magic, too. */
+
+ if (IsDebuggerPresent()) {
+ THREADNAME_INFO inf;
+
+ /* C# and friends will try to catch this Exception, let's avoid it. */
+ if (SDL_GetHintBoolean(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, SDL_TRUE)) {
+ return;
+ }
+
+ /* This magic tells the debugger to name a thread if it's listening. */
+ SDL_zero(inf);
+ inf.dwType = 0x1000;
+ inf.szName = name;
+ inf.dwThreadID = (DWORD) -1;
+ inf.dwFlags = 0;
+
+ /* The debugger catches this, renames the thread, continues on. */
+ RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf);
+ }
+ }
+}
+
+SDL_threadID
+SDL_ThreadID(void)
+{
+ return ((SDL_threadID) GetCurrentThreadId());
+}
+
+int
+SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
+{
+ int value;
+
+ if (priority == SDL_THREAD_PRIORITY_LOW) {
+ value = THREAD_PRIORITY_LOWEST;
+ } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
+ value = THREAD_PRIORITY_HIGHEST;
+ } else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {
+ value = THREAD_PRIORITY_TIME_CRITICAL;
+ } else {
+ value = THREAD_PRIORITY_NORMAL;
+ }
+ if (!SetThreadPriority(GetCurrentThread(), value)) {
+ return WIN_SetError("SetThreadPriority()");
+ }
+ return 0;
+}
+
+void
+SDL_SYS_WaitThread(SDL_Thread * thread)
+{
+ WaitForSingleObjectEx(thread->handle, INFINITE, FALSE);
+ CloseHandle(thread->handle);
+}
+
+void
+SDL_SYS_DetachThread(SDL_Thread * thread)
+{
+ CloseHandle(thread->handle);
+}
+
+#endif /* SDL_THREAD_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/windows/SDL_systhread_c.h b/source/3rd-party/SDL2/src/thread/windows/SDL_systhread_c.h
new file mode 100644
index 0000000..65d5a1b
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/windows/SDL_systhread_c.h
@@ -0,0 +1,32 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_systhread_c_h_
+#define SDL_systhread_c_h_
+
+#include "../../core/windows/SDL_windows.h"
+
+typedef HANDLE SYS_ThreadHandle;
+
+#endif /* SDL_systhread_c_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/thread/windows/SDL_systls.c b/source/3rd-party/SDL2/src/thread/windows/SDL_systls.c
new file mode 100644
index 0000000..888fd74
--- /dev/null
+++ b/source/3rd-party/SDL2/src/thread/windows/SDL_systls.c
@@ -0,0 +1,72 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+
+#if SDL_THREAD_WINDOWS
+
+#include "../../core/windows/SDL_windows.h"
+
+#include "SDL_thread.h"
+#include "../SDL_thread_c.h"
+
+static DWORD thread_local_storage = TLS_OUT_OF_INDEXES;
+static SDL_bool generic_local_storage = SDL_FALSE;
+
+SDL_TLSData *
+SDL_SYS_GetTLSData(void)
+{
+ if (thread_local_storage == TLS_OUT_OF_INDEXES && !generic_local_storage) {
+ static SDL_SpinLock lock;
+ SDL_AtomicLock(&lock);
+ if (thread_local_storage == TLS_OUT_OF_INDEXES && !generic_local_storage) {
+ DWORD storage = TlsAlloc();
+ if (storage != TLS_OUT_OF_INDEXES) {
+ SDL_MemoryBarrierRelease();
+ thread_local_storage = storage;
+ } else {
+ generic_local_storage = SDL_TRUE;
+ }
+ }
+ SDL_AtomicUnlock(&lock);
+ }
+ if (generic_local_storage) {
+ return SDL_Generic_GetTLSData();
+ }
+ SDL_MemoryBarrierAcquire();
+ return (SDL_TLSData *)TlsGetValue(thread_local_storage);
+}
+
+int
+SDL_SYS_SetTLSData(SDL_TLSData *data)
+{
+ if (generic_local_storage) {
+ return SDL_Generic_SetTLSData(data);
+ }
+ if (!TlsSetValue(thread_local_storage, data)) {
+ return SDL_SetError("TlsSetValue() failed");
+ }
+ return 0;
+}
+
+#endif /* SDL_THREAD_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */