summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/SDL2/src/thread/SDL_thread.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/SDL2/src/thread/SDL_thread.c')
-rw-r--r--3rdparty/SDL2/src/thread/SDL_thread.c503
1 files changed, 0 insertions, 503 deletions
diff --git a/3rdparty/SDL2/src/thread/SDL_thread.c b/3rdparty/SDL2/src/thread/SDL_thread.c
deleted file mode 100644
index ae865790a7d..00000000000
--- a/3rdparty/SDL2/src/thread/SDL_thread.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- Simple DirectMedia Layer
- Copyright (C) 1997-2016 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 (*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()
-{
- 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
-#endif
-#if SDL_DYNAMIC_API
-#define SDL_CreateThread SDL_CreateThread_REAL
-#endif
-
-#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
-static SDL_Thread *
-SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
- const char *name, const size_t stacksize, void *data,
- pfnSDL_CurrentBeginThread pfnBeginThread,
- pfnSDL_CurrentEndThread pfnEndThread)
-#else
-static 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: */