Commit 7ae2951fca4629508e135b43bbc3b711bca525d7

Ryan C. Gordon 2016-04-12T14:38:50

threads: Handle SDL_HINT_THREAD_STACK_SIZE at top level, implement elsewhere.

diff --git a/src/thread/SDL_thread.c b/src/thread/SDL_thread.c
index e66c581..1306ae0 100644
--- a/src/thread/SDL_thread.c
+++ b/src/thread/SDL_thread.c
@@ -26,6 +26,7 @@
 #include "SDL_thread.h"
 #include "SDL_thread_c.h"
 #include "SDL_systhread.h"
+#include "SDL_hints.h"
 #include "../SDL_error_c.h"
 
 
@@ -304,15 +305,15 @@ SDL_RunThread(void *data)
 #endif
 
 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
-DECLSPEC SDL_Thread *SDLCALL
-SDL_CreateThread(int (SDLCALL * fn) (void *),
-                 const char *name, void *data,
+static SDL_Thread *
+SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
+                 const char *name, const size_t stacksize, void *data,
                  pfnSDL_CurrentBeginThread pfnBeginThread,
                  pfnSDL_CurrentEndThread pfnEndThread)
 #else
-DECLSPEC SDL_Thread *SDLCALL
-SDL_CreateThread(int (SDLCALL * fn) (void *),
-                 const char *name, void *data)
+static SDL_Thread *
+SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
+                const char *name, const size_t stacksize, void *data)
 #endif
 {
     SDL_Thread *thread;
@@ -362,6 +363,8 @@ SDL_CreateThread(int (SDLCALL * fn) (void *),
         return (NULL);
     }
 
+    thread->stacksize = stacksize;
+
     /* Create the thread and go! */
 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
     ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
@@ -386,6 +389,40 @@ SDL_CreateThread(int (SDLCALL * fn) (void *),
     return (thread);
 }
 
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(int (SDLCALL * fn) (void *),
+                 const char *name, void *data,
+                 pfnSDL_CurrentBeginThread pfnBeginThread,
+                 pfnSDL_CurrentEndThread pfnEndThread)
+#else
+DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(int (SDLCALL * fn) (void *),
+                 const char *name, void *data)
+#endif
+{
+    /* !!! FIXME: in 2.1, just make stackhint part of the usual API. */
+    const char *stackhint = SDL_GetHint(SDL_HINT_THREAD_STACK_SIZE);
+    size_t stacksize = 0;
+
+    /* If the SDL_HINT_THREAD_STACK_SIZE exists, use it */
+    if (stackhint != NULL) {
+        char *endp = NULL;
+        const Sint64 hintval = SDL_strtoll(stackhint, &endp, 10);
+        if ((*stackhint != '\0') && (*endp == '\0')) {  /* a valid number? */
+            if (hintval > 0) {  /* reject bogus values. */
+                stacksize = (size_t) hintval;
+            }
+        }
+    }
+
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+    return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, pfnBeginThread, pfnEndThread);
+#else
+    return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
+#endif
+}
+
 SDL_threadID
 SDL_GetThreadID(SDL_Thread * thread)
 {
diff --git a/src/thread/SDL_thread_c.h b/src/thread/SDL_thread_c.h
index a283a0e..7749183 100644
--- a/src/thread/SDL_thread_c.h
+++ b/src/thread/SDL_thread_c.h
@@ -59,6 +59,7 @@ struct SDL_Thread
     SDL_atomic_t state;  /* SDL_THREAD_STATE_* */
     SDL_error errbuf;
     char *name;
+    size_t stacksize;  /* 0 for default, >0 for user-specified stack size. */
     void *data;
 };
 
@@ -89,6 +90,19 @@ extern SDL_TLSData *SDL_Generic_GetTLSData();
  */
 extern int SDL_Generic_SetTLSData(SDL_TLSData *data);
 
+/* !!! FIXME: for 2.1, remove this and make stack size part of SDL_CreateThread. */
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+SDL_Thread *SDLCALL
+SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
+                 const char *name, const size_t stacksize, void *data,
+                 pfnSDL_CurrentBeginThread pfnBeginThread,
+                 pfnSDL_CurrentEndThread pfnEndThread)
+#else
+SDL_Thread *SDLCALL
+SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
+                const char *name, const size_t stacksize, void *data)
+#endif
+
 #endif /* _SDL_thread_c_h */
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/thread/psp/SDL_systhread.c b/src/thread/psp/SDL_systhread.c
index ab8aff3..96f2e1d 100644
--- a/src/thread/psp/SDL_systhread.c
+++ b/src/thread/psp/SDL_systhread.c
@@ -52,8 +52,8 @@ int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
         priority = status.currentPriority;
     }
 
-    thread->handle = sceKernelCreateThread("SDL thread", ThreadEntry,
-                           priority, 0x8000,
+    thread->handle = sceKernelCreateThread(thread->name, ThreadEntry,
+                           priority, thread->stacksize ? ((int) stacksize) : 0x8000,
                            PSP_THREAD_ATTR_VFPU, NULL);
     if (thread->handle < 0) {
         return SDL_SetError("sceKernelCreateThread() failed");
diff --git a/src/thread/pthread/SDL_systhread.c b/src/thread/pthread/SDL_systhread.c
index 22f7bd5..79d6543 100644
--- a/src/thread/pthread/SDL_systhread.c
+++ b/src/thread/pthread/SDL_systhread.c
@@ -45,7 +45,6 @@
 
 #include "SDL_platform.h"
 #include "SDL_thread.h"
-#include "SDL_hints.h"
 #include "../SDL_thread_c.h"
 #include "../SDL_systhread.h"
 #ifdef __ANDROID__
@@ -87,7 +86,6 @@ int
 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
 {
     pthread_attr_t type;
-    const char *hint = SDL_GetHint(SDL_HINT_THREAD_STACK_SIZE);
 
     /* do this here before any threads exist, so there's no race condition. */
     #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
@@ -108,12 +106,9 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
     }
     pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
     
-    /* If the SDL_HINT_THREAD_STACK_SIZE exists and it seems to be a positive number, use it */
-    if (hint && hint[0] >= '0' && hint[0] <= '9') {
-        const size_t stacksize = (size_t) SDL_atoi(hint);
-        if (stacksize > 0) {
-            pthread_attr_setstacksize(&type, stacksize);
-        }
+    /* Set caller-requested stack size. Otherwise: use the system default. */
+    if (thread->stacksize) {
+        pthread_attr_setstacksize(&type, (size_t) thread->stacksize);
     }
 
     /* Create the thread and go! */
diff --git a/src/thread/stdcpp/SDL_systhread.cpp b/src/thread/stdcpp/SDL_systhread.cpp
index 219c67e..6e5ef47 100644
--- a/src/thread/stdcpp/SDL_systhread.cpp
+++ b/src/thread/stdcpp/SDL_systhread.cpp
@@ -48,6 +48,7 @@ int
 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
 {
     try {
+        // !!! FIXME: no way to set a thread stack size here.
         std::thread cpp_thread(RunThread, args);
         thread->handle = (void *) new std::thread(std::move(cpp_thread));
         return 0;
diff --git a/src/thread/windows/SDL_systhread.c b/src/thread/windows/SDL_systhread.c
index 2f22b89..249e361 100644
--- a/src/thread/windows/SDL_systhread.c
+++ b/src/thread/windows/SDL_systhread.c
@@ -129,14 +129,17 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
     /* Also save the real parameters we have to pass to thread function */
     pThreadParms->args = args;
 
+    /* thread->stacksize == 0 means "system default", same as win32 expects */
     if (pfnBeginThread) {
         unsigned threadid = 0;
         thread->handle = (SYS_ThreadHandle)
-            ((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx,
+            ((size_t) pfnBeginThread(NULL, (unsigned int) thread->stacksize,
+                                     RunThreadViaBeginThreadEx,
                                      pThreadParms, 0, &threadid));
     } else {
         DWORD threadid = 0;
-        thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread,
+        thread->handle = CreateThread(NULL, thread->stacksize,
+                                      RunThreadViaCreateThread,
                                       pThreadParms, 0, &threadid);
     }
     if (thread->handle == NULL) {