src/thread/windows/SDL_systhread.c
author Philipp Wiesemann
Thu, 30 May 2013 12:23:36 +0200
changeset 7242 96f4133dfafa
parent 7191 75360622e65f
child 7498 bda3639deecc
permissions -rw-r--r--
Added deactivated loading of SDL2_net to Java file.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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 #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 #else
   110 int
   111 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
   112 {
   113     pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex;
   114     pfnSDL_CurrentEndThread pfnEndThread = _endthreadex;
   115 #endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
   116     pThreadStartParms pThreadParms =
   117         (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
   118     if (!pThreadParms) {
   119         return SDL_OutOfMemory();
   120     }
   121     /* Save the function which we will have to call to clear the RTL of calling app! */
   122     pThreadParms->pfnCurrentEndThread = pfnEndThread;
   123     /* Also save the real parameters we have to pass to thread function */
   124     pThreadParms->args = args;
   125 
   126     if (pfnBeginThread) {
   127         unsigned threadid = 0;
   128         thread->handle = (SYS_ThreadHandle)
   129             ((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx,
   130                                      pThreadParms, 0, &threadid));
   131     } else {
   132         DWORD threadid = 0;
   133         thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread,
   134                                       pThreadParms, 0, &threadid);
   135     }
   136     if (thread->handle == NULL) {
   137         return SDL_SetError("Not enough resources to create thread");
   138     }
   139     return 0;
   140 }
   141 
   142 #ifdef _MSC_VER
   143 #pragma pack(push,8)
   144 typedef struct tagTHREADNAME_INFO
   145 {
   146     DWORD dwType; /* must be 0x1000 */
   147     LPCSTR szName; /* pointer to name (in user addr space) */
   148     DWORD dwThreadID; /* thread ID (-1=caller thread) */
   149     DWORD dwFlags; /* reserved for future use, must be zero */
   150 } THREADNAME_INFO;
   151 #pragma pack(pop)
   152 #endif
   153 
   154 void
   155 SDL_SYS_SetupThread(const char *name)
   156 {
   157     if (name != NULL) {
   158         #if 0  /* !!! FIXME: __except needs C runtime, which we don't link against. */
   159         #ifdef _MSC_VER  /* !!! FIXME: can we do SEH on other compilers yet? */
   160         /* This magic tells the debugger to name a thread if it's listening. */
   161         THREADNAME_INFO inf;
   162         inf.dwType = 0x1000;
   163         inf.szName = name;
   164         inf.dwThreadID = (DWORD) -1;
   165         inf.dwFlags = 0;
   166 
   167         __try
   168         {
   169             RaiseException(0x406D1388, 0, sizeof(inf)/sizeof(DWORD), (DWORD*)&inf);
   170         }
   171         __except(EXCEPTION_CONTINUE_EXECUTION)
   172         {
   173             /* The program itself should ignore this bogus exception. */
   174         }
   175         #endif
   176         #endif
   177     }
   178 }
   179 
   180 SDL_threadID
   181 SDL_ThreadID(void)
   182 {
   183     return ((SDL_threadID) GetCurrentThreadId());
   184 }
   185 
   186 int
   187 SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
   188 {
   189     int value;
   190 
   191     if (priority == SDL_THREAD_PRIORITY_LOW) {
   192         value = THREAD_PRIORITY_LOWEST;
   193     } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
   194         value = THREAD_PRIORITY_HIGHEST;
   195     } else {
   196         value = THREAD_PRIORITY_NORMAL;
   197     }
   198     if (!SetThreadPriority(GetCurrentThread(), value)) {
   199         return WIN_SetError("SetThreadPriority()");
   200     }
   201     return 0;
   202 }
   203 
   204 void
   205 SDL_SYS_WaitThread(SDL_Thread * thread)
   206 {
   207     WaitForSingleObject(thread->handle, INFINITE);
   208     CloseHandle(thread->handle);
   209 }
   210 
   211 #endif /* SDL_THREAD_WINDOWS */
   212 
   213 /* vi: set ts=4 sw=4 expandtab: */