Home | History | Annotate | Download | only in win32
      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