src/thread/win32/SDL_systhread.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 16 Dec 2009 04:48:11 +0000
changeset 3578 0d1b16ee0bca
parent 2859 99210400e8b9
child 3697 f7b03b6838cb
permissions -rw-r--r--
Fixed bug #741

The thread ID is an unsigned long so it can hold pthread_t so people can do naughty things with it.

I'm going to be adding additional useful thread API functions, but this should prevent crashes in people's existing code on 64-bit architectures.
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
/* Win32 thread management routines for SDL */
slouken@0
    25
slouken@1433
    26
#define WIN32_LEAN_AND_MEAN
slouken@1433
    27
#include <windows.h>
slouken@0
    28
slouken@0
    29
#include "SDL_thread.h"
slouken@1361
    30
#include "../SDL_thread_c.h"
slouken@1361
    31
#include "../SDL_systhread.h"
slouken@0
    32
slouken@1471
    33
#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
slouken@1471
    34
#ifndef _WIN32_WCE
slouken@1471
    35
/* We'll use the C library from this DLL */
slouken@1471
    36
#include <process.h>
slouken@1471
    37
#endif
slouken@1471
    38
slouken@1471
    39
#if __GNUC__
slouken@1895
    40
typedef unsigned long (__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
slouken@1895
    41
                                                             unsigned
slouken@1895
    42
                                                             (__stdcall *
slouken@1895
    43
                                                              func) (void *),
slouken@1895
    44
                                                             void *arg,
slouken@1895
    45
                                                             unsigned,
slouken@1895
    46
                                                             unsigned
slouken@1895
    47
                                                             *threadID);
slouken@1895
    48
typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
slouken@1769
    49
#elif defined(__WATCOMC__)
slouken@1769
    50
/* This is for Watcom targets except OS2 */
slouken@1769
    51
#if __WATCOMC__ < 1240
slouken@1769
    52
#define __watcall
slouken@1769
    53
#endif
slouken@1895
    54
typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *,
slouken@1895
    55
                                                               unsigned,
slouken@1895
    56
                                                               unsigned
slouken@1895
    57
                                                               (__stdcall *
slouken@1895
    58
                                                                func) (void
slouken@1895
    59
                                                                       *),
slouken@1895
    60
                                                               void *arg,
slouken@1895
    61
                                                               unsigned,
slouken@1895
    62
                                                               unsigned
slouken@1895
    63
                                                               *threadID);
slouken@1895
    64
typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
slouken@1471
    65
#else
slouken@1895
    66
typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
slouken@1895
    67
                                                        unsigned (__stdcall *
slouken@1895
    68
                                                                  func) (void
slouken@1895
    69
                                                                         *),
slouken@1895
    70
                                                        void *arg, unsigned,
slouken@1895
    71
                                                        unsigned *threadID);
slouken@1895
    72
typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
slouken@1471
    73
#endif
slouken@1471
    74
#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
slouken@1471
    75
slouken@1471
    76
slouken@1330
    77
typedef struct ThreadStartParms
slouken@1330
    78
{
slouken@1895
    79
    void *args;
slouken@1895
    80
    pfnSDL_CurrentEndThread pfnCurrentEndThread;
slouken@1330
    81
} tThreadStartParms, *pThreadStartParms;
slouken@0
    82
slouken@1895
    83
static unsigned __stdcall
slouken@1895
    84
RunThread(void *data)
slouken@0
    85
{
slouken@1895
    86
    pThreadStartParms pThreadParms = (pThreadStartParms) data;
slouken@1895
    87
    pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL;
slouken@1330
    88
slouken@1895
    89
    // Call the thread function!
slouken@1895
    90
    SDL_RunThread(pThreadParms->args);
slouken@1330
    91
slouken@1895
    92
    // Get the current endthread we have to use!
slouken@1895
    93
    if (pThreadParms) {
slouken@1895
    94
        pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread;
slouken@1895
    95
        SDL_free(pThreadParms);
slouken@1895
    96
    }
slouken@1895
    97
    // Call endthread!
slouken@1895
    98
    if (pfnCurrentEndThread)
slouken@1895
    99
        (*pfnCurrentEndThread) (0);
slouken@1895
   100
    return (0);
slouken@0
   101
}
slouken@0
   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@1471
   109
#else
slouken@1895
   110
int
slouken@1895
   111
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
slouken@1471
   112
{
slouken@1471
   113
#ifdef _WIN32_WCE
slouken@1895
   114
    pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
slouken@1895
   115
    pfnSDL_CurrentEndThread pfnEndThread = NULL;
slouken@1471
   116
#else
slouken@1895
   117
    pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex;
slouken@1895
   118
    pfnSDL_CurrentEndThread pfnEndThread = _endthreadex;
slouken@1471
   119
#endif
slouken@1471
   120
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
slouken@1895
   121
    unsigned threadid;
slouken@1895
   122
    pThreadStartParms pThreadParms =
slouken@1895
   123
        (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
slouken@1895
   124
    if (!pThreadParms) {
slouken@1895
   125
        SDL_OutOfMemory();
slouken@1895
   126
        return (-1);
slouken@1895
   127
    }
slouken@1895
   128
    // Save the function which we will have to call to clear the RTL of calling app!
slouken@1895
   129
    pThreadParms->pfnCurrentEndThread = pfnEndThread;
slouken@1895
   130
    // Also save the real parameters we have to pass to thread function
slouken@1895
   131
    pThreadParms->args = args;
slouken@0
   132
slouken@1895
   133
    if (pfnBeginThread) {
slouken@1895
   134
        thread->handle =
slouken@1895
   135
            (SYS_ThreadHandle) pfnBeginThread(NULL, 0, RunThread,
slouken@1895
   136
                                              pThreadParms, 0, &threadid);
slouken@1895
   137
    } else {
slouken@1895
   138
        thread->handle =
slouken@1895
   139
            CreateThread(NULL, 0, RunThread, pThreadParms, 0, &threadid);
slouken@1895
   140
    }
slouken@1895
   141
    if (thread->handle == NULL) {
slouken@1895
   142
        SDL_SetError("Not enough resources to create thread");
slouken@1895
   143
        return (-1);
slouken@1895
   144
    }
slouken@1895
   145
    return (0);
slouken@0
   146
}
slouken@0
   147
slouken@1895
   148
void
slouken@1895
   149
SDL_SYS_SetupThread(void)
slouken@0
   150
{
slouken@1895
   151
    return;
slouken@0
   152
}
slouken@0
   153
slouken@3578
   154
SDL_threadID
slouken@1895
   155
SDL_ThreadID(void)
slouken@0
   156
{
slouken@3578
   157
    return ((SDL_threadID) GetCurrentThreadId());
slouken@0
   158
}
slouken@0
   159
slouken@1895
   160
void
slouken@1895
   161
SDL_SYS_WaitThread(SDL_Thread * thread)
slouken@0
   162
{
slouken@1895
   163
    WaitForSingleObject(thread->handle, INFINITE);
slouken@1895
   164
    CloseHandle(thread->handle);
slouken@0
   165
}
slouken@0
   166
slouken@1895
   167
/* vi: set ts=4 sw=4 expandtab: */