src/thread/windows/SDL_systhread.c
author Ryan C. Gordon
Sun, 02 Oct 2011 00:43:56 -0400
changeset 5971 ca2d4b8e9e40
parent 5970 34263edce4f4
child 5973 9392717808aa
permissions -rw-r--r--
Further patched to compile on Windows.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2011 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_config.h"
    22 
    23 /* Win32 thread management routines for SDL */
    24 
    25 #include "SDL_thread.h"
    26 #include "../SDL_thread_c.h"
    27 #include "../SDL_systhread.h"
    28 #include "SDL_systhread_c.h"
    29 
    30 #ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
    31 #ifndef _WIN32_WCE
    32 /* We'll use the C library from this DLL */
    33 #include <process.h>
    34 #endif
    35 
    36 /* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */
    37 #if (defined(__MINGW32__) && (__GNUC__ < 4))
    38 typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
    39         unsigned (__stdcall *func)(void *), void *arg, 
    40         unsigned, unsigned *threadID);
    41 typedef 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
    48 typedef 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);
    58 typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
    59 
    60 #else
    61 typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
    62                                                         unsigned (__stdcall *
    63                                                                   func) (void
    64                                                                          *),
    65                                                         void *arg, unsigned,
    66                                                         unsigned *threadID);
    67 typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
    68 #endif
    69 #endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
    70 
    71 
    72 typedef struct ThreadStartParms
    73 {
    74     void *args;
    75     pfnSDL_CurrentEndThread pfnCurrentEndThread;
    76 } tThreadStartParms, *pThreadStartParms;
    77 
    78 static DWORD
    79 RunThread(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 
    91 static DWORD WINAPI
    92 RunThreadViaCreateThread(LPVOID data)
    93 {
    94   return RunThread(data);
    95 }
    96 
    97 static unsigned __stdcall
    98 RunThreadViaBeginThreadEx(void *data)
    99 {
   100   return (unsigned) RunThread(data);
   101 }
   102 
   103 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
   104 int
   105 SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
   106                      pfnSDL_CurrentBeginThread pfnBeginThread,
   107                      pfnSDL_CurrentEndThread pfnEndThread)
   108 {
   109 #else
   110 int
   111 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
   112 {
   113 #ifdef _WIN32_WCE
   114     pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
   115     pfnSDL_CurrentEndThread pfnEndThread = NULL;
   116 #else
   117     pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex;
   118     pfnSDL_CurrentEndThread pfnEndThread = _endthreadex;
   119 #endif
   120 #endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
   121     pThreadStartParms pThreadParms =
   122         (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
   123     if (!pThreadParms) {
   124         SDL_OutOfMemory();
   125         return (-1);
   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         SDL_SetError("Not enough resources to create thread");
   144         return (-1);
   145     }
   146     return (0);
   147 }
   148 
   149 #ifdef _MSC_VER
   150 #pragma pack(push,8)
   151 typedef struct tagTHREADNAME_INFO
   152 {
   153     DWORD dwType; /* must be 0x1000 */
   154     LPCSTR szName; /* pointer to name (in user addr space) */
   155     DWORD dwThreadID; /* thread ID (-1=caller thread) */
   156     DWORD dwFlags; /* reserved for future use, must be zero */
   157 } THREADNAME_INFO;
   158 #pragma pack(pop)
   159 #endif
   160 
   161 void
   162 SDL_SYS_SetupThread(const char *name)
   163 {
   164 #ifdef _MSC_VER  /* !!! FIXME: can we do SEH on other compilers yet? */
   165     /* This magic tells the debugger to name a thread if it's listening. */
   166     THREADNAME_INFO inf;
   167     inf.dwType = 0x1000;
   168     inf.szName = name;
   169     inf.dwThreadID = (DWORD) -1;
   170     inf.dwFlags = 0;
   171 
   172     __try
   173     {
   174         RaiseException(0x406D1388, 0, sizeof(inf)/sizeof(DWORD), (DWORD*)&inf);
   175     }
   176     __except(EXCEPTION_CONTINUE_EXECUTION)
   177     {
   178         /* The program itself should ignore this bogus exception. */
   179     }
   180 #endif
   181 }
   182 
   183 SDL_threadID
   184 SDL_ThreadID(void)
   185 {
   186     return ((SDL_threadID) GetCurrentThreadId());
   187 }
   188 
   189 int
   190 SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
   191 {
   192     int value;
   193 
   194     if (priority == SDL_THREAD_PRIORITY_LOW) {
   195         value = THREAD_PRIORITY_LOWEST;
   196     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   197         value = THREAD_PRIORITY_HIGHEST;
   198     } else {
   199         value = THREAD_PRIORITY_NORMAL;
   200     }
   201     if (!SetThreadPriority(GetCurrentThread(), value)) {
   202         WIN_SetError("SetThreadPriority()");
   203         return -1;
   204     }
   205     return 0;
   206 }
   207 
   208 void
   209 SDL_SYS_WaitThread(SDL_Thread * thread)
   210 {
   211     WaitForSingleObject(thread->handle, INFINITE);
   212     CloseHandle(thread->handle);
   213 }
   214 
   215 /* vi: set ts=4 sw=4 expandtab: */