mirror of
https://github.com/Relintai/sdl2_frt.git
synced 2025-02-04 11:15:57 +01:00
261 lines
8.8 KiB
C
261 lines
8.8 KiB
C
/*
|
|
Simple DirectMedia Layer
|
|
Copyright (C) 1997-2019 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: */
|