thread: Reworked SDL_CreateThread to be consistent across platforms.

Also documented missing and weird bits, rename typedefs to fit SDL standards.
This commit is contained in:
Ryan C. Gordon
2024-05-21 01:46:48 -04:00
parent 983544a53e
commit 0ec716819e
30 changed files with 214 additions and 219 deletions

View File

@@ -36,13 +36,9 @@ extern "C" {
saves a system-dependent thread id in thread->id, and returns 0
on success.
*/
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
extern int SDL_SYS_CreateThread(SDL_Thread *thread,
pfnSDL_CurrentBeginThread pfnBeginThread,
pfnSDL_CurrentEndThread pfnEndThread);
#else
extern int SDL_SYS_CreateThread(SDL_Thread *thread);
#endif
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread);
/* This function does any necessary setup in the child thread */
extern void SDL_SYS_SetupThread(const char *name);
@@ -64,11 +60,6 @@ extern SDL_TLSData *SDL_SYS_GetTLSData(void);
/* Set the thread local storage for this thread */
extern int SDL_SYS_SetTLSData(SDL_TLSData *data);
/* This is for internal SDL use, so we don't need #ifdefs everywhere. */
extern SDL_Thread *
SDL_CreateThreadInternal(int(SDLCALL *fn)(void *), const char *name,
const size_t stacksize, void *data);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}

View File

@@ -307,28 +307,22 @@ void SDL_RunThread(SDL_Thread *thread)
}
}
#ifdef SDL_CreateThread
#undef SDL_CreateThread
#undef SDL_CreateThreadWithStackSize
#endif
#if SDL_DYNAMIC_API
#define SDL_CreateThread SDL_CreateThread_REAL
#define SDL_CreateThreadWithStackSize SDL_CreateThreadWithStackSize_REAL
#endif
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
SDL_Thread *SDL_CreateThreadWithStackSize(int(SDLCALL *fn)(void *),
SDL_Thread *SDL_CreateThreadWithStackSizeRuntime(SDL_ThreadFunction fn,
const char *name, const size_t stacksize, void *data,
pfnSDL_CurrentBeginThread pfnBeginThread,
pfnSDL_CurrentEndThread pfnEndThread)
#else
SDL_Thread *SDL_CreateThreadWithStackSize(int(SDLCALL *fn)(void *),
const char *name, const size_t stacksize, void *data)
#endif
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread)
{
SDL_Thread *thread;
int ret;
// rather than check this in every backend, just make sure it's correct upfront. Only allow non-NULL if non-WinRT Windows, or Microsoft GDK.
#if (!defined(SDL_PLATFORM_WIN32) && !defined(SDL_PLATFORM_GDK)) || defined(SDL_PLATFORM_WINRT)
if (pfnBeginThread || pfnEndThread) {
SDL_SetError("_beginthreadex/_endthreadex not supported on this platform");
return NULL;
}
#endif
/* Allocate memory for the thread info structure */
thread = (SDL_Thread *)SDL_calloc(1, sizeof(*thread));
if (!thread) {
@@ -351,11 +345,7 @@ SDL_Thread *SDL_CreateThreadWithStackSize(int(SDLCALL *fn)(void *),
thread->stacksize = stacksize;
/* Create the thread and go! */
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
ret = SDL_SYS_CreateThread(thread, pfnBeginThread, pfnEndThread);
#else
ret = SDL_SYS_CreateThread(thread);
#endif
if (ret < 0) {
/* Oops, failed. Gotta free everything */
SDL_free(thread->name);
@@ -367,31 +357,12 @@ SDL_Thread *SDL_CreateThreadWithStackSize(int(SDLCALL *fn)(void *),
return thread;
}
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
SDL_Thread *SDLCALL SDL_CreateThread(int(SDLCALL *fn)(void *),
SDL_Thread *SDL_CreateThreadRuntime(SDL_ThreadFunction fn,
const char *name, void *data,
pfnSDL_CurrentBeginThread pfnBeginThread,
pfnSDL_CurrentEndThread pfnEndThread)
#else
SDL_Thread *SDLCALL SDL_CreateThread(int(SDLCALL *fn)(void *),
const char *name, void *data)
#endif
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread)
{
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
return SDL_CreateThreadWithStackSize(fn, name, 0, data, pfnBeginThread, pfnEndThread);
#else
return SDL_CreateThreadWithStackSize(fn, name, 0, data);
#endif
}
SDL_Thread *SDL_CreateThreadInternal(int(SDLCALL *fn)(void *), const char *name,
const size_t stacksize, void *data)
{
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, NULL, NULL);
#else
return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
#endif
return SDL_CreateThreadWithStackSizeRuntime(fn, name, 0, data, pfnBeginThread, pfnEndThread);
}
SDL_ThreadID SDL_GetThreadID(SDL_Thread *thread)

View File

@@ -24,13 +24,9 @@
#include "../SDL_systhread.h"
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
int SDL_SYS_CreateThread(SDL_Thread *thread,
pfnSDL_CurrentBeginThread pfnBeginThread,
pfnSDL_CurrentEndThread pfnEndThread)
#else
int SDL_SYS_CreateThread(SDL_Thread *thread)
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread)
{
return SDL_SetError("Threads are not supported on this platform");
}

View File

@@ -42,11 +42,10 @@ static void ThreadEntry(void *arg)
threadExit(0);
}
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
#error "SDL_PASSED_BEGINTHREAD_ENDTHREAD is not supported on N3DS"
#endif
int SDL_SYS_CreateThread(SDL_Thread *thread)
int SDL_SYS_CreateThread(SDL_Thread *thread,
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread)
{
s32 priority = 0x30;
int cpu = -1;

View File

@@ -57,7 +57,9 @@ int CreateUnique(TInt (*aFunc)(const TDesC &aName, TAny *, TAny *), TAny *aPtr1,
return status;
}
int SDL_SYS_CreateThread(SDL_Thread *thread)
int SDL_SYS_CreateThread(SDL_Thread *thread,
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread)
{
RThread rthread;

View File

@@ -54,7 +54,9 @@ static int childThread(void *arg)
return res;
}
int SDL_SYS_CreateThread(SDL_Thread *thread)
int SDL_SYS_CreateThread(SDL_Thread *thread,
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread)
{
ee_thread_status_t status;
ee_thread_t eethread;

View File

@@ -38,7 +38,9 @@ static int ThreadEntry(SceSize args, void *argp)
return 0;
}
int SDL_SYS_CreateThread(SDL_Thread *thread)
int SDL_SYS_CreateThread(SDL_Thread *thread,
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread)
{
SceKernelThreadInfo status;
int priority = 32;

View File

@@ -77,7 +77,9 @@ static int (*ppthread_setname_np)(const char *) = NULL;
static SDL_bool checked_setname = SDL_FALSE;
static int (*ppthread_setname_np)(pthread_t, const char *) = NULL;
#endif
int SDL_SYS_CreateThread(SDL_Thread *thread)
int SDL_SYS_CreateThread(SDL_Thread *thread,
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread)
{
pthread_attr_t type;

View File

@@ -41,7 +41,9 @@ static void RunThread(void *args)
}
extern "C" int
SDL_SYS_CreateThread(SDL_Thread *thread)
SDL_SYS_CreateThread(SDL_Thread *thread,
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread)
{
try {
// !!! FIXME: no way to set a thread stack size here.

View File

@@ -48,7 +48,10 @@ static int ThreadEntry(SceSize args, void *argp)
return 0;
}
int SDL_SYS_CreateThread(SDL_Thread *thread)
int SDL_SYS_CreateThread(SDL_Thread *thread,
SDL_FunctionPointer pfnBeginThread,
SDL_FunctionPointer pfnEndThread)
{
char thread_name[VITA_THREAD_NAME_MAX];
size_t stack_size = VITA_THREAD_STACK_SIZE_DEFAULT;

View File

@@ -32,20 +32,15 @@
#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
#endif
#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
/* We'll use the C library from this DLL */
#include <process.h>
typedef uintptr_t(__cdecl *pfnSDL_CurrentBeginThread)(void *, unsigned,
unsigned(__stdcall *func)(void*),
void *arg, unsigned,
unsigned *threadID);
typedef void(__cdecl *pfnSDL_CurrentEndThread)(unsigned code);
#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
typedef void (__cdecl * SDL_EndThreadExCallback) (unsigned retval);
typedef uintptr_t (__cdecl * SDL_BeginThreadExCallback)
(void *security, unsigned stacksize, unsigned (__stdcall *startaddr)(void *),
void * arglist, unsigned initflag, unsigned *threadaddr);
static DWORD RunThread(void *data)
{
SDL_Thread *thread = (SDL_Thread *)data;
pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)thread->endfunc;
SDL_EndThreadExCallback pfnEndThread = (SDL_EndThreadExCallback)thread->endfunc;
SDL_RunThread(thread);
if (pfnEndThread) {
pfnEndThread(0);
@@ -63,26 +58,16 @@ static unsigned __stdcall MINGW32_FORCEALIGN RunThreadViaBeginThreadEx(void *dat
return (unsigned)RunThread(data);
}
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
int SDL_SYS_CreateThread(SDL_Thread *thread,
pfnSDL_CurrentBeginThread pfnBeginThread,
pfnSDL_CurrentEndThread pfnEndThread)
SDL_FunctionPointer vpfnBeginThread,
SDL_FunctionPointer vpfnEndThread)
{
#elif defined(SDL_PLATFORM_CYGWIN) || defined(SDL_PLATFORM_WINRT)
int SDL_SYS_CreateThread(SDL_Thread *thread)
{
pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
pfnSDL_CurrentEndThread pfnEndThread = NULL;
#else
int SDL_SYS_CreateThread(SDL_Thread *thread)
{
pfnSDL_CurrentBeginThread pfnBeginThread = (pfnSDL_CurrentBeginThread)_beginthreadex;
pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)_endthreadex;
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
SDL_BeginThreadExCallback pfnBeginThread = (SDL_BeginThreadExCallback) vpfnBeginThread;
const DWORD flags = thread->stacksize ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0;
/* Save the function which we will have to call to clear the RTL of calling app! */
thread->endfunc = (SDL_FunctionPointer)pfnEndThread;
thread->endfunc = vpfnEndThread;
/* thread->stacksize == 0 means "system default", same as win32 expects */
if (pfnBeginThread) {