1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2006 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 /* Win32 thread management routines for SDL */ 25 26 #define WIN32_LEAN_AND_MEAN 27 #include <windows.h> 28 29 #include "SDL_thread.h" 30 #include "../SDL_thread_c.h" 31 #include "../SDL_systhread.h" 32 33 #ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD 34 #ifndef _WIN32_WCE 35 /* We'll use the C library from this DLL */ 36 #include <process.h> 37 #endif 38 39 #if __GNUC__ 40 typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, 41 unsigned (__stdcall *func)(void *), void *arg, 42 unsigned, unsigned *threadID); 43 typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); 44 #elif defined(__WATCOMC__) 45 /* This is for Watcom targets except OS2 */ 46 #if __WATCOMC__ < 1240 47 #define __watcall 48 #endif 49 typedef unsigned long (__watcall *pfnSDL_CurrentBeginThread) (void *, unsigned, 50 unsigned (__stdcall *func)(void *), void *arg, 51 unsigned, unsigned *threadID); 52 typedef void (__watcall *pfnSDL_CurrentEndThread)(unsigned code); 53 #else 54 typedef uintptr_t (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, 55 unsigned (__stdcall *func)(void *), void *arg, 56 unsigned, unsigned *threadID); 57 typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); 58 #endif 59 #endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */ 60 61 62 typedef struct ThreadStartParms 63 { 64 void *args; 65 pfnSDL_CurrentEndThread pfnCurrentEndThread; 66 } tThreadStartParms, *pThreadStartParms; 67 68 static unsigned __stdcall RunThread(void *data) 69 { 70 pThreadStartParms pThreadParms = (pThreadStartParms)data; 71 pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL; 72 73 // Call the thread function! 74 SDL_RunThread(pThreadParms->args); 75 76 // Get the current endthread we have to use! 77 if (pThreadParms) 78 { 79 pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread; 80 SDL_free(pThreadParms); 81 } 82 // Call endthread! 83 if (pfnCurrentEndThread) 84 (*pfnCurrentEndThread)(0); 85 return(0); 86 } 87 88 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD 89 int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) 90 { 91 #else 92 int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) 93 { 94 #ifdef _WIN32_WCE 95 pfnSDL_CurrentBeginThread pfnBeginThread = NULL; 96 pfnSDL_CurrentEndThread pfnEndThread = NULL; 97 #else 98 pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex; 99 pfnSDL_CurrentEndThread pfnEndThread = _endthreadex; 100 #endif 101 #endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */ 102 unsigned threadid; 103 pThreadStartParms pThreadParms = (pThreadStartParms)SDL_malloc(sizeof(tThreadStartParms)); 104 if (!pThreadParms) { 105 SDL_OutOfMemory(); 106 return(-1); 107 } 108 109 // Save the function which we will have to call to clear the RTL of calling app! 110 pThreadParms->pfnCurrentEndThread = pfnEndThread; 111 // Also save the real parameters we have to pass to thread function 112 pThreadParms->args = args; 113 114 if (pfnBeginThread) { 115 thread->handle = (SYS_ThreadHandle) pfnBeginThread(NULL, 0, RunThread, 116 pThreadParms, 0, &threadid); 117 } else { 118 thread->handle = CreateThread(NULL, 0, RunThread, pThreadParms, 0, &threadid); 119 } 120 if (thread->handle == NULL) { 121 SDL_SetError("Not enough resources to create thread"); 122 return(-1); 123 } 124 return(0); 125 } 126 127 void SDL_SYS_SetupThread(void) 128 { 129 return; 130 } 131 132 Uint32 SDL_ThreadID(void) 133 { 134 return((Uint32)GetCurrentThreadId()); 135 } 136 137 void SDL_SYS_WaitThread(SDL_Thread *thread) 138 { 139 WaitForSingleObject(thread->handle, INFINITE); 140 CloseHandle(thread->handle); 141 } 142 143 /* WARNING: This function is really a last resort. 144 * Threads should be signaled and then exit by themselves. 145 * TerminateThread() doesn't perform stack and DLL cleanup. 146 */ 147 void SDL_SYS_KillThread(SDL_Thread *thread) 148 { 149 TerminateThread(thread->handle, FALSE); 150 } 151