Home | History | Annotate | Download | only in win32
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 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 1
     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 defined(__WATCOMC__)
     40 /* This is for Watcom targets except OS2 */
     41 #if __WATCOMC__ < 1240
     42 #define __watcall
     43 #endif
     44 typedef unsigned long (__watcall *pfnSDL_CurrentBeginThread) (void *, unsigned,
     45         unsigned (__stdcall *func)(void *), void *arg,
     46         unsigned, unsigned *threadID);
     47 typedef void (__watcall *pfnSDL_CurrentEndThread)(unsigned code);
     48 #elif (defined(__MINGW32__) && (__GNUC__ < 4))
     49 typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
     50         unsigned (__stdcall *func)(void *), void *arg,
     51         unsigned, unsigned *threadID);
     52 typedef void (__cdecl *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 DWORD 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 static DWORD WINAPI RunThreadViaCreateThread(LPVOID data)
     89 {
     90   return RunThread(data);
     91 }
     92 
     93 static unsigned __stdcall RunThreadViaBeginThreadEx(void *data)
     94 {
     95   return (unsigned) RunThread(data);
     96 }
     97 
     98 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
     99 int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread)
    100 {
    101 #else
    102 int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
    103 {
    104 #ifdef _WIN32_WCE
    105 	pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
    106 	pfnSDL_CurrentEndThread pfnEndThread = NULL;
    107 #else
    108 	pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex;
    109 	pfnSDL_CurrentEndThread pfnEndThread = _endthreadex;
    110 #endif
    111 #endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
    112 	pThreadStartParms pThreadParms = (pThreadStartParms)SDL_malloc(sizeof(tThreadStartParms));
    113 	if (!pThreadParms) {
    114 		SDL_OutOfMemory();
    115 		return(-1);
    116 	}
    117 
    118 	// Save the function which we will have to call to clear the RTL of calling app!
    119 	pThreadParms->pfnCurrentEndThread = pfnEndThread;
    120 	// Also save the real parameters we have to pass to thread function
    121 	pThreadParms->args = args;
    122 
    123 	if (pfnBeginThread) {
    124 		unsigned threadid = 0;
    125 		thread->handle = (SYS_ThreadHandle)
    126 				((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx,
    127 										 pThreadParms, 0, &threadid));
    128 	} else {
    129 		DWORD threadid = 0;
    130 		thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread, pThreadParms, 0, &threadid);
    131 	}
    132 	if (thread->handle == NULL) {
    133 		SDL_SetError("Not enough resources to create thread");
    134 		return(-1);
    135 	}
    136 	return(0);
    137 }
    138 
    139 void SDL_SYS_SetupThread(void)
    140 {
    141 	return;
    142 }
    143 
    144 Uint32 SDL_ThreadID(void)
    145 {
    146 	return((Uint32)GetCurrentThreadId());
    147 }
    148 
    149 void SDL_SYS_WaitThread(SDL_Thread *thread)
    150 {
    151 	WaitForSingleObject(thread->handle, INFINITE);
    152 	CloseHandle(thread->handle);
    153 }
    154 
    155 /* WARNING: This function is really a last resort.
    156  * Threads should be signaled and then exit by themselves.
    157  * TerminateThread() doesn't perform stack and DLL cleanup.
    158  */
    159 void SDL_SYS_KillThread(SDL_Thread *thread)
    160 {
    161 	TerminateThread(thread->handle, FALSE);
    162 }
    163