diff options
Diffstat (limited to 'source/3rd-party/SDL2/src/thread/windows/SDL_systhread.c')
-rw-r--r-- | source/3rd-party/SDL2/src/thread/windows/SDL_systhread.c | 260 |
1 files changed, 260 insertions, 0 deletions
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: */ |