initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
197
thirdparty/sdl/thread/windows/SDL_systhread.c
vendored
Normal file
197
thirdparty/sdl/thread/windows/SDL_systhread.c
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 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"
|
||||
|
||||
#ifdef SDL_THREAD_WINDOWS
|
||||
|
||||
// Win32 thread management routines for SDL
|
||||
|
||||
#include "../SDL_thread_c.h"
|
||||
#include "../SDL_systhread.h"
|
||||
#include "SDL_systhread_c.h"
|
||||
|
||||
#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
|
||||
#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
|
||||
#endif
|
||||
|
||||
#define SDL_DEBUGGER_NAME_EXCEPTION_CODE 0x406D1388
|
||||
|
||||
typedef void (__cdecl * SDL_EndThreadExCallback) (unsigned retval);
|
||||
typedef uintptr_t (__cdecl * SDL_BeginThreadExCallback)
|
||||
(void *security, unsigned stacksize, unsigned (__stdcall *startaddr)(void *),
|
||||
void * arglist, unsigned initflag, unsigned *threadaddr);
|
||||
|
||||
static DWORD RunThread(void *data)
|
||||
{
|
||||
SDL_Thread *thread = (SDL_Thread *)data;
|
||||
SDL_EndThreadExCallback pfnEndThread = (SDL_EndThreadExCallback)thread->endfunc;
|
||||
SDL_RunThread(thread);
|
||||
if (pfnEndThread) {
|
||||
pfnEndThread(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD WINAPI MINGW32_FORCEALIGN RunThreadViaCreateThread(LPVOID data)
|
||||
{
|
||||
return RunThread(data);
|
||||
}
|
||||
|
||||
static unsigned __stdcall MINGW32_FORCEALIGN RunThreadViaBeginThreadEx(void *data)
|
||||
{
|
||||
return (unsigned)RunThread(data);
|
||||
}
|
||||
|
||||
bool SDL_SYS_CreateThread(SDL_Thread *thread,
|
||||
SDL_FunctionPointer vpfnBeginThread,
|
||||
SDL_FunctionPointer vpfnEndThread)
|
||||
{
|
||||
SDL_BeginThreadExCallback pfnBeginThread = (SDL_BeginThreadExCallback) vpfnBeginThread;
|
||||
|
||||
const DWORD flags = thread->stacksize ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0;
|
||||
|
||||
// Save the function which we will have to call to clear the RTL of calling app!
|
||||
thread->endfunc = vpfnEndThread;
|
||||
|
||||
// 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,
|
||||
thread, flags, &threadid));
|
||||
} else {
|
||||
DWORD threadid = 0;
|
||||
thread->handle = CreateThread(NULL, thread->stacksize,
|
||||
RunThreadViaCreateThread,
|
||||
thread, flags, &threadid);
|
||||
}
|
||||
if (!thread->handle) {
|
||||
return SDL_SetError("Not enough resources to create thread");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#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)
|
||||
|
||||
static LONG NTAPI EmptyVectoredExceptionHandler(EXCEPTION_POINTERS *info)
|
||||
{
|
||||
if (info != NULL && info->ExceptionRecord != NULL && info->ExceptionRecord->ExceptionCode == SDL_DEBUGGER_NAME_EXCEPTION_CODE) {
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
} else {
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
}
|
||||
|
||||
typedef HRESULT(WINAPI *pfnSetThreadDescription)(HANDLE, PCWSTR);
|
||||
|
||||
void SDL_SYS_SetupThread(const char *name)
|
||||
{
|
||||
if (name) {
|
||||
PVOID exceptionHandlerHandle;
|
||||
static pfnSetThreadDescription pSetThreadDescription = NULL;
|
||||
static HMODULE kernel32 = NULL;
|
||||
|
||||
if (!kernel32) {
|
||||
kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
|
||||
if (kernel32) {
|
||||
pSetThreadDescription = (pfnSetThreadDescription)GetProcAddress(kernel32, "SetThreadDescription");
|
||||
}
|
||||
if (!kernel32 || !pSetThreadDescription) {
|
||||
HMODULE kernelBase = GetModuleHandle(TEXT("KernelBase.dll"));
|
||||
if (kernelBase) {
|
||||
pSetThreadDescription = (pfnSetThreadDescription)GetProcAddress(kernelBase, "SetThreadDescription");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pSetThreadDescription) {
|
||||
WCHAR *strw = WIN_UTF8ToStringW(name);
|
||||
if (strw) {
|
||||
pSetThreadDescription(GetCurrentThread(), strw);
|
||||
SDL_free(strw);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
exceptionHandlerHandle = AddVectoredExceptionHandler(1, EmptyVectoredExceptionHandler);
|
||||
if (exceptionHandlerHandle) {
|
||||
THREADNAME_INFO inf;
|
||||
// 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(SDL_DEBUGGER_NAME_EXCEPTION_CODE, 0, sizeof(inf) / sizeof(ULONG_PTR), (const ULONG_PTR *)&inf);
|
||||
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_ThreadID SDL_GetCurrentThreadID(void)
|
||||
{
|
||||
return (SDL_ThreadID)GetCurrentThreadId();
|
||||
}
|
||||
|
||||
bool 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 true;
|
||||
}
|
||||
|
||||
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
|
Reference in New Issue
Block a user