Atlas - SDL_systhread.c

Home / ext / SDL2 / src / thread / windows Lines: 1 | Size: 9027 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#if SDL_THREAD_WINDOWS 24 25/* Win32 thread management routines for SDL */ 26 27#include "SDL_hints.h" 28#include "SDL_thread.h" 29#include "../SDL_thread_c.h" 30#include "../SDL_systhread.h" 31#include "SDL_systhread_c.h" 32 33#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD 34/* We'll use the C library from this DLL */ 35#include <process.h> 36 37#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION 38#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000 39#endif 40 41/* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */ 42#if (defined(__MINGW32__) && (__GNUC__ < 4)) 43typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, 44 unsigned (__stdcall *func)(void *), void *arg, 45 unsigned, unsigned *threadID); 46typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); 47 48#elif defined(__WATCOMC__) 49/* This is for Watcom targets except OS2 */ 50#if __WATCOMC__ < 1240 51#define __watcall 52#endif 53typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *, 54 unsigned, 55 unsigned 56 (__stdcall * 57 func) (void 58 *), 59 void *arg, 60 unsigned, 61 unsigned 62 *threadID); 63typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code); 64 65#else 66typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned, 67 unsigned (__stdcall * 68 func) (void 69 *), 70 void *arg, unsigned, 71 unsigned *threadID); 72typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code); 73#endif 74#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */ 75 76 77typedef struct ThreadStartParms 78{ 79 void *args; 80 pfnSDL_CurrentEndThread pfnCurrentEndThread; 81} tThreadStartParms, *pThreadStartParms; 82 83static DWORD 84RunThread(void *data) 85{ 86 pThreadStartParms pThreadParms = (pThreadStartParms) data; 87 pfnSDL_CurrentEndThread pfnEndThread = pThreadParms->pfnCurrentEndThread; 88 void *args = pThreadParms->args; 89 SDL_free(pThreadParms); 90 SDL_RunThread(args); 91 if (pfnEndThread != NULL) 92 pfnEndThread(0); 93 return (0); 94} 95 96static DWORD WINAPI 97RunThreadViaCreateThread(LPVOID data) 98{ 99 return RunThread(data); 100} 101 102static unsigned __stdcall 103RunThreadViaBeginThreadEx(void *data) 104{ 105 return (unsigned) RunThread(data); 106} 107 108#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD 109int 110SDL_SYS_CreateThread(SDL_Thread * thread, void *args, 111 pfnSDL_CurrentBeginThread pfnBeginThread, 112 pfnSDL_CurrentEndThread pfnEndThread) 113{ 114#elif defined(__CYGWIN__) || defined(__WINRT__) 115int 116SDL_SYS_CreateThread(SDL_Thread * thread, void *args) 117{ 118 pfnSDL_CurrentBeginThread pfnBeginThread = NULL; 119 pfnSDL_CurrentEndThread pfnEndThread = NULL; 120#else 121int 122SDL_SYS_CreateThread(SDL_Thread * thread, void *args) 123{ 124 pfnSDL_CurrentBeginThread pfnBeginThread = (pfnSDL_CurrentBeginThread)_beginthreadex; 125 pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)_endthreadex; 126#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */ 127 pThreadStartParms pThreadParms = 128 (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms)); 129 const DWORD flags = thread->stacksize ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0; 130 if (!pThreadParms) { 131 return SDL_OutOfMemory(); 132 } 133 /* Save the function which we will have to call to clear the RTL of calling app! */ 134 pThreadParms->pfnCurrentEndThread = pfnEndThread; 135 /* Also save the real parameters we have to pass to thread function */ 136 pThreadParms->args = args; 137 138 /* thread->stacksize == 0 means "system default", same as win32 expects */ 139 if (pfnBeginThread) { 140 unsigned threadid = 0; 141 thread->handle = (SYS_ThreadHandle) 142 ((size_t) pfnBeginThread(NULL, (unsigned int) thread->stacksize, 143 RunThreadViaBeginThreadEx, 144 pThreadParms, flags, &threadid)); 145 } else { 146 DWORD threadid = 0; 147 thread->handle = CreateThread(NULL, thread->stacksize, 148 RunThreadViaCreateThread, 149 pThreadParms, flags, &threadid); 150 } 151 if (thread->handle == NULL) { 152 return SDL_SetError("Not enough resources to create thread"); 153 } 154 return 0; 155} 156 157#pragma pack(push,8) 158typedef struct tagTHREADNAME_INFO 159{ 160 DWORD dwType; /* must be 0x1000 */ 161 LPCSTR szName; /* pointer to name (in user addr space) */ 162 DWORD dwThreadID; /* thread ID (-1=caller thread) */ 163 DWORD dwFlags; /* reserved for future use, must be zero */ 164} THREADNAME_INFO; 165#pragma pack(pop) 166 167 168typedef HRESULT (WINAPI *pfnSetThreadDescription)(HANDLE, PCWSTR); 169 170void 171SDL_SYS_SetupThread(const char *name) 172{ 173 if (name != NULL) { 174 #ifndef __WINRT__ /* !!! FIXME: There's no LoadLibrary() in WinRT; don't know if SetThreadDescription is available there at all at the moment. */ 175 static pfnSetThreadDescription pSetThreadDescription = NULL; 176 static HMODULE kernel32 = 0; 177 178 if (!kernel32) { 179 kernel32 = LoadLibraryW(L"kernel32.dll"); 180 if (kernel32) { 181 pSetThreadDescription = (pfnSetThreadDescription) GetProcAddress(kernel32, "SetThreadDescription"); 182 } 183 } 184 185 if (pSetThreadDescription != NULL) { 186 WCHAR *strw = WIN_UTF8ToString(name); 187 if (strw) { 188 pSetThreadDescription(GetCurrentThread(), strw); 189 SDL_free(strw); 190 } 191 } 192 #endif 193 194 /* Presumably some version of Visual Studio will understand SetThreadDescription(), 195 but we still need to deal with older OSes and debuggers. Set it with the arcane 196 exception magic, too. */ 197 198 if (IsDebuggerPresent()) { 199 THREADNAME_INFO inf; 200 201 /* C# and friends will try to catch this Exception, let's avoid it. */ 202 if (SDL_GetHintBoolean(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, SDL_TRUE)) { 203 return; 204 } 205 206 /* This magic tells the debugger to name a thread if it's listening. */ 207 SDL_zero(inf); 208 inf.dwType = 0x1000; 209 inf.szName = name; 210 inf.dwThreadID = (DWORD) -1; 211 inf.dwFlags = 0; 212 213 /* The debugger catches this, renames the thread, continues on. */ 214 RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf); 215 } 216 } 217} 218 219SDL_threadID 220SDL_ThreadID(void) 221{ 222 return ((SDL_threadID) GetCurrentThreadId()); 223} 224 225int 226SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) 227{ 228 int value; 229 230 if (priority == SDL_THREAD_PRIORITY_LOW) { 231 value = THREAD_PRIORITY_LOWEST; 232 } else if (priority == SDL_THREAD_PRIORITY_HIGH) { 233 value = THREAD_PRIORITY_HIGHEST; 234 } else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) { 235 value = THREAD_PRIORITY_TIME_CRITICAL; 236 } else { 237 value = THREAD_PRIORITY_NORMAL; 238 } 239 if (!SetThreadPriority(GetCurrentThread(), value)) { 240 return WIN_SetError("SetThreadPriority()"); 241 } 242 return 0; 243} 244 245void 246SDL_SYS_WaitThread(SDL_Thread * thread) 247{ 248 WaitForSingleObjectEx(thread->handle, INFINITE, FALSE); 249 CloseHandle(thread->handle); 250} 251 252void 253SDL_SYS_DetachThread(SDL_Thread * thread) 254{ 255 CloseHandle(thread->handle); 256} 257 258#endif /* SDL_THREAD_WINDOWS */ 259 260/* vi: set ts=4 sw=4 expandtab: */ 261
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.