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.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@0
    22
slouken@6044
    23
#if SDL_THREAD_WINDOWS
slouken@6044
    24
slouken@0
    25
/* Win32 thread management routines for SDL */
slouken@0
    26
slouken@0
    27
#include "SDL_thread.h"
slouken@1361
    28
#include "../SDL_thread_c.h"
slouken@1361
    29
#include "../SDL_systhread.h"
slouken@5086
    30
#include "SDL_systhread_c.h"
slouken@0
    31
slouken@1471
    32
#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
slouken@1471
    33
/* We'll use the C library from this DLL */
slouken@1471
    34
#include <process.h>
slouken@1471
    35
icculus@5904
    36
/* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */
icculus@5904
    37
#if (defined(__MINGW32__) && (__GNUC__ < 4))
icculus@5904
    38
typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
slouken@7191
    39
        unsigned (__stdcall *func)(void *), void *arg,
icculus@5904
    40
        unsigned, unsigned *threadID);
icculus@5904
    41
typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code);
icculus@5904
    42
slouken@1769
    43
#elif defined(__WATCOMC__)
slouken@1769
    44
/* This is for Watcom targets except OS2 */
slouken@1769
    45
#if __WATCOMC__ < 1240
slouken@1769
    46
#define __watcall
slouken@1769
    47
#endif
slouken@1895
    48
typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *,
slouken@1895
    49
                                                               unsigned,
slouken@1895
    50
                                                               unsigned
slouken@1895
    51
                                                               (__stdcall *
slouken@1895
    52
                                                                func) (void
slouken@1895
    53
                                                                       *),
slouken@1895
    54
                                                               void *arg,
slouken@1895
    55
                                                               unsigned,
slouken@1895
    56
                                                               unsigned
slouken@1895
    57
                                                               *threadID);
slouken@1895
    58
typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
icculus@5904
    59
slouken@1471
    60
#else
slouken@1895
    61
typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
slouken@1895
    62
                                                        unsigned (__stdcall *
slouken@1895
    63
                                                                  func) (void
slouken@1895
    64
                                                                         *),
slouken@1895
    65
                                                        void *arg, unsigned,
slouken@1895
    66
                                                        unsigned *threadID);
slouken@1895
    67
typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
slouken@1471
    68
#endif
slouken@1471
    69
#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
slouken@1471
    70
slouken@1471
    71
slouken@1330
    72
typedef struct ThreadStartParms
slouken@1330
    73
{
slouken@1895
    74
    void *args;
slouken@1895
    75
    pfnSDL_CurrentEndThread pfnCurrentEndThread;
slouken@1330
    76
} tThreadStartParms, *pThreadStartParms;
slouken@0
    77
icculus@5904
    78
static DWORD
slouken@1895
    79
RunThread(void *data)
slouken@0
    80
{
slouken@1895
    81
    pThreadStartParms pThreadParms = (pThreadStartParms) data;
icculus@5962
    82
    pfnSDL_CurrentEndThread pfnEndThread = pThreadParms->pfnCurrentEndThread;
icculus@5962
    83
    void *args = pThreadParms->args;
icculus@5962
    84
    SDL_free(pThreadParms);
icculus@5962
    85
    SDL_RunThread(args);
icculus@5962
    86
    if (pfnEndThread != NULL)
icculus@5962
    87
        pfnEndThread(0);
slouken@1895
    88
    return (0);
slouken@0
    89
}
slouken@0
    90
icculus@5904
    91
static DWORD WINAPI
icculus@5904
    92
RunThreadViaCreateThread(LPVOID data)
icculus@5904
    93
{
icculus@5904
    94
  return RunThread(data);
icculus@5904
    95
}
icculus@5904
    96
icculus@5904
    97
static unsigned __stdcall
icculus@5904
    98
RunThreadViaBeginThreadEx(void *data)
icculus@5904
    99
{
icculus@5904
   100
  return (unsigned) RunThread(data);
icculus@5904
   101
}
icculus@5904
   102
slouken@1471
   103
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
slouken@1895
   104
int
slouken@1895
   105
SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
slouken@1895
   106
                     pfnSDL_CurrentBeginThread pfnBeginThread,
slouken@1895
   107
                     pfnSDL_CurrentEndThread pfnEndThread)
slouken@0
   108
{
slouken@7498
   109
#elif defined(__CYGWIN__)
slouken@7498
   110
int
slouken@7498
   111
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
slouken@7498
   112
{
slouken@7498
   113
    pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
slouken@7498
   114
    pfnSDL_CurrentEndThread pfnEndThread = NULL;
slouken@1471
   115
#else
slouken@1895
   116
int
slouken@1895
   117
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
slouken@1471
   118
{
slouken@7828
   119
    pfnSDL_CurrentBeginThread pfnBeginThread = (pfnSDL_CurrentBeginThread)_beginthreadex;
slouken@7828
   120
    pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)_endthreadex;
slouken@1471
   121
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
slouken@1895
   122
    pThreadStartParms pThreadParms =
slouken@1895
   123
        (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
slouken@1895
   124
    if (!pThreadParms) {
icculus@7037
   125
        return SDL_OutOfMemory();
slouken@1895
   126
    }
slouken@7191
   127
    /* Save the function which we will have to call to clear the RTL of calling app! */
slouken@1895
   128
    pThreadParms->pfnCurrentEndThread = pfnEndThread;
slouken@7191
   129
    /* Also save the real parameters we have to pass to thread function */
slouken@1895
   130
    pThreadParms->args = args;
slouken@1330
   131
slouken@1895
   132
    if (pfnBeginThread) {
icculus@5904
   133
        unsigned threadid = 0;
icculus@5904
   134
        thread->handle = (SYS_ThreadHandle)
icculus@5904
   135
            ((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx,
icculus@5904
   136
                                     pThreadParms, 0, &threadid));
slouken@1895
   137
    } else {
icculus@5904
   138
        DWORD threadid = 0;
icculus@5904
   139
        thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread,
icculus@5904
   140
                                      pThreadParms, 0, &threadid);
slouken@1895
   141
    }
slouken@1895
   142
    if (thread->handle == NULL) {
icculus@7037
   143
        return SDL_SetError("Not enough resources to create thread");
slouken@1895
   144
    }
icculus@7037
   145
    return 0;
slouken@0
   146
}
slouken@0
   147
icculus@7854
   148
#if 0  /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */
icculus@5969
   149
#ifdef _MSC_VER
icculus@7724
   150
#pragma warning(disable : 4733)
icculus@5969
   151
#pragma pack(push,8)
icculus@5969
   152
typedef struct tagTHREADNAME_INFO
icculus@5969
   153
{
icculus@5969
   154
    DWORD dwType; /* must be 0x1000 */
icculus@5969
   155
    LPCSTR szName; /* pointer to name (in user addr space) */
icculus@5969
   156
    DWORD dwThreadID; /* thread ID (-1=caller thread) */
icculus@5969
   157
    DWORD dwFlags; /* reserved for future use, must be zero */
icculus@5969
   158
} THREADNAME_INFO;
icculus@5969
   159
#pragma pack(pop)
icculus@7724
   160
icculus@7724
   161
static EXCEPTION_DISPOSITION
icculus@7724
   162
ignore_exception(void *a, void *b, void *c, void *d)
icculus@7724
   163
{
icculus@7724
   164
    return ExceptionContinueExecution;
icculus@7724
   165
}
icculus@5969
   166
#endif
icculus@7854
   167
#endif
icculus@5969
   168
slouken@1895
   169
void
icculus@5969
   170
SDL_SYS_SetupThread(const char *name)
slouken@0
   171
{
icculus@6000
   172
    if (name != NULL) {
icculus@7854
   173
        #if 0 /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */
icculus@7735
   174
        #if (defined(_MSC_VER) && defined(_M_IX86))
icculus@7724
   175
        /* This magic tells the debugger to name a thread if it's listening.
icculus@7724
   176
            The inline asm sets up SEH (__try/__except) without C runtime
icculus@7724
   177
            support. See Microsoft Systems Journal, January 1997:
icculus@7724
   178
            http://www.microsoft.com/msj/0197/exception/exception.aspx */
icculus@7724
   179
        INT_PTR handler = (INT_PTR) ignore_exception;
icculus@6000
   180
        THREADNAME_INFO inf;
icculus@7724
   181
icculus@6000
   182
        inf.dwType = 0x1000;
icculus@6000
   183
        inf.szName = name;
icculus@6000
   184
        inf.dwThreadID = (DWORD) -1;
icculus@6000
   185
        inf.dwFlags = 0;
icculus@5969
   186
icculus@7724
   187
        __asm {   /* set up SEH */
icculus@7724
   188
            push handler
icculus@7724
   189
            push fs:[0]
icculus@7724
   190
            mov fs:[0],esp
icculus@6000
   191
        }
icculus@7724
   192
icculus@7724
   193
        /* The program itself should ignore this bogus exception. */
icculus@7724
   194
        RaiseException(0x406D1388, 0, sizeof(inf)/sizeof(DWORD), (DWORD*)&inf);
icculus@7724
   195
icculus@7724
   196
        __asm {  /* tear down SEH. */
icculus@7724
   197
            mov eax,[esp]
icculus@7724
   198
            mov fs:[0], eax
icculus@7724
   199
            add esp, 8
icculus@6000
   200
        }
icculus@6000
   201
        #endif
icculus@7854
   202
        #endif
icculus@5969
   203
    }
slouken@0
   204
}
slouken@0
   205
slouken@3578
   206
SDL_threadID
slouken@1895
   207
SDL_ThreadID(void)
slouken@0
   208
{
slouken@3578
   209
    return ((SDL_threadID) GetCurrentThreadId());
slouken@0
   210
}
slouken@0
   211
slouken@5506
   212
int
slouken@5509
   213
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
slouken@5506
   214
{
slouken@5509
   215
    int value;
slouken@5506
   216
slouken@5506
   217
    if (priority == SDL_THREAD_PRIORITY_LOW) {
slouken@5509
   218
        value = THREAD_PRIORITY_LOWEST;
slouken@5506
   219
    } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
slouken@5509
   220
        value = THREAD_PRIORITY_HIGHEST;
slouken@5506
   221
    } else {
slouken@5509
   222
        value = THREAD_PRIORITY_NORMAL;
slouken@5506
   223
    }
slouken@5509
   224
    if (!SetThreadPriority(GetCurrentThread(), value)) {
icculus@7037
   225
        return WIN_SetError("SetThreadPriority()");
slouken@5506
   226
    }
slouken@5506
   227
    return 0;
slouken@5506
   228
}
slouken@5506
   229
slouken@1895
   230
void
slouken@1895
   231
SDL_SYS_WaitThread(SDL_Thread * thread)
slouken@0
   232
{
slouken@1895
   233
    WaitForSingleObject(thread->handle, INFINITE);
slouken@1895
   234
    CloseHandle(thread->handle);
slouken@0
   235
}
slouken@0
   236
icculus@7978
   237
void
icculus@7978
   238
SDL_SYS_DetachThread(SDL_Thread * thread)
icculus@7978
   239
{
icculus@7978
   240
    CloseHandle(thread->handle);
icculus@7978
   241
}
icculus@7978
   242
slouken@6044
   243
#endif /* SDL_THREAD_WINDOWS */
slouken@6044
   244
slouken@1895
   245
/* vi: set ts=4 sw=4 expandtab: */