src/thread/windows/SDL_systhread.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Sun, 08 Jun 2014 12:51:02 +0200
changeset 8844 d35c1b1798c8
parent 8149 681eb46b8ac4
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Fixed typo in source comment.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 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_internal.h"
    22 
    23 #if SDL_THREAD_WINDOWS
    24 
    25 /* Win32 thread management routines for SDL */
    26 
    27 #include "SDL_thread.h"
    28 #include "../SDL_thread_c.h"
    29 #include "../SDL_systhread.h"
    30 #include "SDL_systhread_c.h"
    31 
    32 #ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
    33 /* We'll use the C library from this DLL */
    34 #include <process.h>
    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 #elif defined(__CYGWIN__)
   110 int
   111 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
   112 {
   113     pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
   114     pfnSDL_CurrentEndThread pfnEndThread = NULL;
   115 #else
   116 int
   117 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
   118 {
   119     pfnSDL_CurrentBeginThread pfnBeginThread = (pfnSDL_CurrentBeginThread)_beginthreadex;
   120     pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)_endthreadex;
   121 #endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
   122     pThreadStartParms pThreadParms =
   123         (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
   124     if (!pThreadParms) {
   125         return SDL_OutOfMemory();
   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         return SDL_SetError("Not enough resources to create thread");
   144     }
   145     return 0;
   146 }
   147 
   148 #if 0  /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */
   149 #ifdef _MSC_VER
   150 #pragma warning(disable : 4733)
   151 #pragma pack(push,8)
   152 typedef struct tagTHREADNAME_INFO
   153 {
   154     DWORD dwType; /* must be 0x1000 */
   155     LPCSTR szName; /* pointer to name (in user addr space) */
   156     DWORD dwThreadID; /* thread ID (-1=caller thread) */
   157     DWORD dwFlags; /* reserved for future use, must be zero */
   158 } THREADNAME_INFO;
   159 #pragma pack(pop)
   160 
   161 static EXCEPTION_DISPOSITION
   162 ignore_exception(void *a, void *b, void *c, void *d)
   163 {
   164     return ExceptionContinueExecution;
   165 }
   166 #endif
   167 #endif
   168 
   169 void
   170 SDL_SYS_SetupThread(const char *name)
   171 {
   172     if (name != NULL) {
   173         #if 0 /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */
   174         #if (defined(_MSC_VER) && defined(_M_IX86))
   175         /* This magic tells the debugger to name a thread if it's listening.
   176             The inline asm sets up SEH (__try/__except) without C runtime
   177             support. See Microsoft Systems Journal, January 1997:
   178             http://www.microsoft.com/msj/0197/exception/exception.aspx */
   179         INT_PTR handler = (INT_PTR) ignore_exception;
   180         THREADNAME_INFO inf;
   181 
   182         inf.dwType = 0x1000;
   183         inf.szName = name;
   184         inf.dwThreadID = (DWORD) -1;
   185         inf.dwFlags = 0;
   186 
   187         __asm {   /* set up SEH */
   188             push handler
   189             push fs:[0]
   190             mov fs:[0],esp
   191         }
   192 
   193         /* The program itself should ignore this bogus exception. */
   194         RaiseException(0x406D1388, 0, sizeof(inf)/sizeof(DWORD), (DWORD*)&inf);
   195 
   196         __asm {  /* tear down SEH. */
   197             mov eax,[esp]
   198             mov fs:[0], eax
   199             add esp, 8
   200         }
   201         #endif
   202         #endif
   203     }
   204 }
   205 
   206 SDL_threadID
   207 SDL_ThreadID(void)
   208 {
   209     return ((SDL_threadID) GetCurrentThreadId());
   210 }
   211 
   212 int
   213 SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
   214 {
   215     int value;
   216 
   217     if (priority == SDL_THREAD_PRIORITY_LOW) {
   218         value = THREAD_PRIORITY_LOWEST;
   219     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   220         value = THREAD_PRIORITY_HIGHEST;
   221     } else {
   222         value = THREAD_PRIORITY_NORMAL;
   223     }
   224     if (!SetThreadPriority(GetCurrentThread(), value)) {
   225         return WIN_SetError("SetThreadPriority()");
   226     }
   227     return 0;
   228 }
   229 
   230 void
   231 SDL_SYS_WaitThread(SDL_Thread * thread)
   232 {
   233     WaitForSingleObject(thread->handle, INFINITE);
   234     CloseHandle(thread->handle);
   235 }
   236 
   237 void
   238 SDL_SYS_DetachThread(SDL_Thread * thread)
   239 {
   240     CloseHandle(thread->handle);
   241 }
   242 
   243 #endif /* SDL_THREAD_WINDOWS */
   244 
   245 /* vi: set ts=4 sw=4 expandtab: */