mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-11 22:42:31 +02:00
Implemented using this script:
find . -type f -exec sed -i'' -e 's,/\* *\([^*]*\)\*/ *$,// \1,' -e 's, \+$,,' {} \;
git checkout \
core/linux/SDL_evdev_kbd_default_keymap.h \
events/imKStoUCS.* \
hidapi \
joystick/controller_type.c \
joystick/controller_type.h \
joystick/hidapi/steam/controller_constants.h \
joystick/hidapi/steam/controller_structs.h \
joystick/SDL_gamepad_db.h \
libm \
render/*/*Shader*.h \
render/vitagxm/SDL_render_vita_gxm_shaders.h \
render/metal/SDL_shaders_metal_*.h \
stdlib/SDL_malloc.c \
stdlib/SDL_qsort.c \
stdlib/SDL_strtokr.c \
test/ \
video/directx/SDL_d3d12_xbox_cmacros.h \
video/directx/d3d12.h \
video/directx/d3d12sdklayers.h \
video/khronos \
video/x11/edid-parse.c \
video/x11/xsettings-client.* \
video/yuv2rgb
sed -i'' -e 's,/\* *\([^*]*\)\*/ *$,// \1,' -e 's, \+$,,' hidapi/SDL_hidapi.c
195 lines
6.6 KiB
C
195 lines
6.6 KiB
C
/*
|
|
Simple DirectMedia Layer
|
|
Copyright (C) 1997-2024 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
|
|
|
|
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);
|
|
}
|
|
|
|
int 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 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)
|
|
|
|
static LONG NTAPI EmptyVectoredExceptionHandler(EXCEPTION_POINTERS *ExceptionInfo)
|
|
{
|
|
(void)ExceptionInfo;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
|
|
typedef HRESULT(WINAPI *pfnSetThreadDescription)(HANDLE, PCWSTR);
|
|
|
|
void SDL_SYS_SetupThread(const char *name)
|
|
{
|
|
if (name) {
|
|
PVOID exceptionHandlerHandle;
|
|
#ifndef SDL_PLATFORM_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 = 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);
|
|
}
|
|
}
|
|
#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. */
|
|
|
|
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(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR *)&inf);
|
|
RemoveVectoredExceptionHandler(exceptionHandlerHandle);
|
|
}
|
|
}
|
|
}
|
|
|
|
SDL_ThreadID SDL_GetCurrentThreadID(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
|