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@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__ 40typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, 41 unsigned (__stdcall *func)(void *), void *arg, 42 unsigned, unsigned *threadID); 43typedef 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 49typedef unsigned long (__watcall *pfnSDL_CurrentBeginThread) (void *, unsigned, 50 unsigned (__stdcall *func)(void *), void *arg, 51 unsigned, unsigned *threadID); 52typedef void (__watcall *pfnSDL_CurrentEndThread)(unsigned code); 53#else 54typedef uintptr_t (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, 55 unsigned (__stdcall *func)(void *), void *arg, 56 unsigned, unsigned *threadID); 57typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); 58#endif 59#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */ 60 61 62typedef struct ThreadStartParms 63{ 64 void *args; 65 pfnSDL_CurrentEndThread pfnCurrentEndThread; 66} tThreadStartParms, *pThreadStartParms; 67 68static 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 89int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) 90{ 91#else 92int 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 127void SDL_SYS_SetupThread(void) 128{ 129 return; 130} 131 132Uint32 SDL_ThreadID(void) 133{ 134 return((Uint32)GetCurrentThreadId()); 135} 136 137void 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 */ 147void SDL_SYS_KillThread(SDL_Thread *thread) 148{ 149 TerminateThread(thread->handle, FALSE); 150} 151