cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_systhread.c (8062B)


      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))
     38typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
     39        unsigned (__stdcall *func)(void *), void *arg,
     40        unsigned, unsigned *threadID);
     41typedef 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
     48typedef 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);
     58typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
     59
     60#else
     61typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
     62                                                        unsigned (__stdcall *
     63                                                                  func) (void
     64                                                                         *),
     65                                                        void *arg, unsigned,
     66                                                        unsigned *threadID);
     67typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
     68#endif
     69#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
     70
     71
     72typedef struct ThreadStartParms
     73{
     74    void *args;
     75    pfnSDL_CurrentEndThread pfnCurrentEndThread;
     76} tThreadStartParms, *pThreadStartParms;
     77
     78static DWORD
     79RunThread(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
     91static DWORD WINAPI
     92RunThreadViaCreateThread(LPVOID data)
     93{
     94  return RunThread(data);
     95}
     96
     97static unsigned __stdcall
     98RunThreadViaBeginThreadEx(void *data)
     99{
    100  return (unsigned) RunThread(data);
    101}
    102
    103#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
    104int
    105SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
    106                     pfnSDL_CurrentBeginThread pfnBeginThread,
    107                     pfnSDL_CurrentEndThread pfnEndThread)
    108{
    109#elif defined(__CYGWIN__)
    110int
    111SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
    112{
    113    pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
    114    pfnSDL_CurrentEndThread pfnEndThread = NULL;
    115#else
    116int
    117SDL_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)
    152typedef 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
    161static EXCEPTION_DISPOSITION
    162ignore_exception(void *a, void *b, void *c, void *d)
    163{
    164    return ExceptionContinueExecution;
    165}
    166#endif
    167#endif
    168
    169void
    170SDL_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
    206SDL_threadID
    207SDL_ThreadID(void)
    208{
    209    return ((SDL_threadID) GetCurrentThreadId());
    210}
    211
    212int
    213SDL_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
    230void
    231SDL_SYS_WaitThread(SDL_Thread * thread)
    232{
    233    WaitForSingleObject(thread->handle, INFINITE);
    234    CloseHandle(thread->handle);
    235}
    236
    237void
    238SDL_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: */