SDL_systhread.c (8062B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 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_thread.h" 28#include "../SDL_thread_c.h" 29#include "../SDL_systhread.h" 30#include "SDL_systhread_c.h" 31 32#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD 33/* We'll use the C library from this DLL */ 34#include <process.h> 35 36/* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */ 37#if (defined(__MINGW32__) && (__GNUC__ < 4)) 38typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, 39 unsigned (__stdcall *func)(void *), void *arg, 40 unsigned, unsigned *threadID); 41typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); 42 43#elif defined(__WATCOMC__) 44/* This is for Watcom targets except OS2 */ 45#if __WATCOMC__ < 1240 46#define __watcall 47#endif 48typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *, 49 unsigned, 50 unsigned 51 (__stdcall * 52 func) (void 53 *), 54 void *arg, 55 unsigned, 56 unsigned 57 *threadID); 58typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code); 59 60#else 61typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned, 62 unsigned (__stdcall * 63 func) (void 64 *), 65 void *arg, unsigned, 66 unsigned *threadID); 67typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code); 68#endif 69#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */ 70 71 72typedef struct ThreadStartParms 73{ 74 void *args; 75 pfnSDL_CurrentEndThread pfnCurrentEndThread; 76} tThreadStartParms, *pThreadStartParms; 77 78static DWORD 79RunThread(void *data) 80{ 81 pThreadStartParms pThreadParms = (pThreadStartParms) data; 82 pfnSDL_CurrentEndThread pfnEndThread = pThreadParms->pfnCurrentEndThread; 83 void *args = pThreadParms->args; 84 SDL_free(pThreadParms); 85 SDL_RunThread(args); 86 if (pfnEndThread != NULL) 87 pfnEndThread(0); 88 return (0); 89} 90 91static DWORD WINAPI 92RunThreadViaCreateThread(LPVOID data) 93{ 94 return RunThread(data); 95} 96 97static unsigned __stdcall 98RunThreadViaBeginThreadEx(void *data) 99{ 100 return (unsigned) RunThread(data); 101} 102 103#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD 104int 105SDL_SYS_CreateThread(SDL_Thread * thread, void *args, 106 pfnSDL_CurrentBeginThread pfnBeginThread, 107 pfnSDL_CurrentEndThread pfnEndThread) 108{ 109#elif defined(__CYGWIN__) 110int 111SDL_SYS_CreateThread(SDL_Thread * thread, void *args) 112{ 113 pfnSDL_CurrentBeginThread pfnBeginThread = NULL; 114 pfnSDL_CurrentEndThread pfnEndThread = NULL; 115#else 116int 117SDL_SYS_CreateThread(SDL_Thread * thread, void *args) 118{ 119 pfnSDL_CurrentBeginThread pfnBeginThread = (pfnSDL_CurrentBeginThread)_beginthreadex; 120 pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)_endthreadex; 121#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */ 122 pThreadStartParms pThreadParms = 123 (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms)); 124 if (!pThreadParms) { 125 return SDL_OutOfMemory(); 126 } 127 /* Save the function which we will have to call to clear the RTL of calling app! */ 128 pThreadParms->pfnCurrentEndThread = pfnEndThread; 129 /* Also save the real parameters we have to pass to thread function */ 130 pThreadParms->args = args; 131 132 if (pfnBeginThread) { 133 unsigned threadid = 0; 134 thread->handle = (SYS_ThreadHandle) 135 ((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx, 136 pThreadParms, 0, &threadid)); 137 } else { 138 DWORD threadid = 0; 139 thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread, 140 pThreadParms, 0, &threadid); 141 } 142 if (thread->handle == NULL) { 143 return SDL_SetError("Not enough resources to create thread"); 144 } 145 return 0; 146} 147 148#if 0 /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */ 149#ifdef _MSC_VER 150#pragma warning(disable : 4733) 151#pragma pack(push,8) 152typedef struct tagTHREADNAME_INFO 153{ 154 DWORD dwType; /* must be 0x1000 */ 155 LPCSTR szName; /* pointer to name (in user addr space) */ 156 DWORD dwThreadID; /* thread ID (-1=caller thread) */ 157 DWORD dwFlags; /* reserved for future use, must be zero */ 158} THREADNAME_INFO; 159#pragma pack(pop) 160 161static EXCEPTION_DISPOSITION 162ignore_exception(void *a, void *b, void *c, void *d) 163{ 164 return ExceptionContinueExecution; 165} 166#endif 167#endif 168 169void 170SDL_SYS_SetupThread(const char *name) 171{ 172 if (name != NULL) { 173 #if 0 /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */ 174 #if (defined(_MSC_VER) && defined(_M_IX86)) 175 /* This magic tells the debugger to name a thread if it's listening. 176 The inline asm sets up SEH (__try/__except) without C runtime 177 support. See Microsoft Systems Journal, January 1997: 178 http://www.microsoft.com/msj/0197/exception/exception.aspx */ 179 INT_PTR handler = (INT_PTR) ignore_exception; 180 THREADNAME_INFO inf; 181 182 inf.dwType = 0x1000; 183 inf.szName = name; 184 inf.dwThreadID = (DWORD) -1; 185 inf.dwFlags = 0; 186 187 __asm { /* set up SEH */ 188 push handler 189 push fs:[0] 190 mov fs:[0],esp 191 } 192 193 /* The program itself should ignore this bogus exception. */ 194 RaiseException(0x406D1388, 0, sizeof(inf)/sizeof(DWORD), (DWORD*)&inf); 195 196 __asm { /* tear down SEH. */ 197 mov eax,[esp] 198 mov fs:[0], eax 199 add esp, 8 200 } 201 #endif 202 #endif 203 } 204} 205 206SDL_threadID 207SDL_ThreadID(void) 208{ 209 return ((SDL_threadID) GetCurrentThreadId()); 210} 211 212int 213SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) 214{ 215 int value; 216 217 if (priority == SDL_THREAD_PRIORITY_LOW) { 218 value = THREAD_PRIORITY_LOWEST; 219 } else if (priority == SDL_THREAD_PRIORITY_HIGH) { 220 value = THREAD_PRIORITY_HIGHEST; 221 } else { 222 value = THREAD_PRIORITY_NORMAL; 223 } 224 if (!SetThreadPriority(GetCurrentThread(), value)) { 225 return WIN_SetError("SetThreadPriority()"); 226 } 227 return 0; 228} 229 230void 231SDL_SYS_WaitThread(SDL_Thread * thread) 232{ 233 WaitForSingleObject(thread->handle, INFINITE); 234 CloseHandle(thread->handle); 235} 236 237void 238SDL_SYS_DetachThread(SDL_Thread * thread) 239{ 240 CloseHandle(thread->handle); 241} 242 243#endif /* SDL_THREAD_WINDOWS */ 244 245/* vi: set ts=4 sw=4 expandtab: */