Path: blob/master/thirdparty/sdl/thread/windows/SDL_systhread.c
9905 views
/*1Simple DirectMedia Layer2Copyright (C) 1997-2025 Sam Lantinga <[email protected]>34This software is provided 'as-is', without any express or implied5warranty. In no event will the authors be held liable for any damages6arising from the use of this software.78Permission is granted to anyone to use this software for any purpose,9including commercial applications, and to alter it and redistribute it10freely, subject to the following restrictions:11121. The origin of this software must not be misrepresented; you must not13claim that you wrote the original software. If you use this software14in a product, an acknowledgment in the product documentation would be15appreciated but is not required.162. Altered source versions must be plainly marked as such, and must not be17misrepresented as being the original software.183. This notice may not be removed or altered from any source distribution.19*/20#include "SDL_internal.h"2122#ifdef SDL_THREAD_WINDOWS2324// Win32 thread management routines for SDL2526#include "../SDL_thread_c.h"27#include "../SDL_systhread.h"28#include "SDL_systhread_c.h"2930#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION31#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x0001000032#endif3334#define SDL_DEBUGGER_NAME_EXCEPTION_CODE 0x406D13883536typedef void (__cdecl * SDL_EndThreadExCallback) (unsigned retval);37typedef uintptr_t (__cdecl * SDL_BeginThreadExCallback)38(void *security, unsigned stacksize, unsigned (__stdcall *startaddr)(void *),39void * arglist, unsigned initflag, unsigned *threadaddr);4041static DWORD RunThread(void *data)42{43SDL_Thread *thread = (SDL_Thread *)data;44SDL_EndThreadExCallback pfnEndThread = (SDL_EndThreadExCallback)thread->endfunc;45SDL_RunThread(thread);46if (pfnEndThread) {47pfnEndThread(0);48}49return 0;50}5152static DWORD WINAPI MINGW32_FORCEALIGN RunThreadViaCreateThread(LPVOID data)53{54return RunThread(data);55}5657static unsigned __stdcall MINGW32_FORCEALIGN RunThreadViaBeginThreadEx(void *data)58{59return (unsigned)RunThread(data);60}6162bool SDL_SYS_CreateThread(SDL_Thread *thread,63SDL_FunctionPointer vpfnBeginThread,64SDL_FunctionPointer vpfnEndThread)65{66SDL_BeginThreadExCallback pfnBeginThread = (SDL_BeginThreadExCallback) vpfnBeginThread;6768const DWORD flags = thread->stacksize ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0;6970// Save the function which we will have to call to clear the RTL of calling app!71thread->endfunc = vpfnEndThread;7273// thread->stacksize == 0 means "system default", same as win32 expects74if (pfnBeginThread) {75unsigned threadid = 0;76thread->handle = (SYS_ThreadHandle)((size_t)pfnBeginThread(NULL, (unsigned int)thread->stacksize,77RunThreadViaBeginThreadEx,78thread, flags, &threadid));79} else {80DWORD threadid = 0;81thread->handle = CreateThread(NULL, thread->stacksize,82RunThreadViaCreateThread,83thread, flags, &threadid);84}85if (!thread->handle) {86return SDL_SetError("Not enough resources to create thread");87}88return true;89}9091#pragma pack(push, 8)92typedef struct tagTHREADNAME_INFO93{94DWORD dwType; // must be 0x100095LPCSTR szName; // pointer to name (in user addr space)96DWORD dwThreadID; // thread ID (-1=caller thread)97DWORD dwFlags; // reserved for future use, must be zero98} THREADNAME_INFO;99#pragma pack(pop)100101static LONG NTAPI EmptyVectoredExceptionHandler(EXCEPTION_POINTERS *info)102{103if (info != NULL && info->ExceptionRecord != NULL && info->ExceptionRecord->ExceptionCode == SDL_DEBUGGER_NAME_EXCEPTION_CODE) {104return EXCEPTION_CONTINUE_EXECUTION;105} else {106return EXCEPTION_CONTINUE_SEARCH;107}108}109110typedef HRESULT(WINAPI *pfnSetThreadDescription)(HANDLE, PCWSTR);111112void SDL_SYS_SetupThread(const char *name)113{114if (name) {115PVOID exceptionHandlerHandle;116static pfnSetThreadDescription pSetThreadDescription = NULL;117static HMODULE kernel32 = NULL;118119if (!kernel32) {120kernel32 = GetModuleHandle(TEXT("kernel32.dll"));121if (kernel32) {122pSetThreadDescription = (pfnSetThreadDescription)GetProcAddress(kernel32, "SetThreadDescription");123}124if (!kernel32 || !pSetThreadDescription) {125HMODULE kernelBase = GetModuleHandle(TEXT("KernelBase.dll"));126if (kernelBase) {127pSetThreadDescription = (pfnSetThreadDescription)GetProcAddress(kernelBase, "SetThreadDescription");128}129}130}131132if (pSetThreadDescription) {133WCHAR *strw = WIN_UTF8ToStringW(name);134if (strw) {135pSetThreadDescription(GetCurrentThread(), strw);136SDL_free(strw);137}138}139140/* Presumably some version of Visual Studio will understand SetThreadDescription(),141but we still need to deal with older OSes and debuggers. Set it with the arcane142exception magic, too. */143144exceptionHandlerHandle = AddVectoredExceptionHandler(1, EmptyVectoredExceptionHandler);145if (exceptionHandlerHandle) {146THREADNAME_INFO inf;147// This magic tells the debugger to name a thread if it's listening.148SDL_zero(inf);149inf.dwType = 0x1000;150inf.szName = name;151inf.dwThreadID = (DWORD)-1;152inf.dwFlags = 0;153154// The debugger catches this, renames the thread, continues on.155RaiseException(SDL_DEBUGGER_NAME_EXCEPTION_CODE, 0, sizeof(inf) / sizeof(ULONG_PTR), (const ULONG_PTR *)&inf);156RemoveVectoredExceptionHandler(exceptionHandlerHandle);157}158}159}160161SDL_ThreadID SDL_GetCurrentThreadID(void)162{163return (SDL_ThreadID)GetCurrentThreadId();164}165166bool SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)167{168int value;169170if (priority == SDL_THREAD_PRIORITY_LOW) {171value = THREAD_PRIORITY_LOWEST;172} else if (priority == SDL_THREAD_PRIORITY_HIGH) {173value = THREAD_PRIORITY_HIGHEST;174} else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) {175value = THREAD_PRIORITY_TIME_CRITICAL;176} else {177value = THREAD_PRIORITY_NORMAL;178}179if (!SetThreadPriority(GetCurrentThread(), value)) {180return WIN_SetError("SetThreadPriority()");181}182return true;183}184185void SDL_SYS_WaitThread(SDL_Thread *thread)186{187WaitForSingleObjectEx(thread->handle, INFINITE, FALSE);188CloseHandle(thread->handle);189}190191void SDL_SYS_DetachThread(SDL_Thread *thread)192{193CloseHandle(thread->handle);194}195196#endif // SDL_THREAD_WINDOWS197198199