diff options
Diffstat (limited to 'source/3rd-party/SDL2/src/thread/windows')
5 files changed, 626 insertions, 0 deletions
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: */ |