Make Linux dynamically look up pthread_setname_np() for older glibc compat.
authorRyan C. Gordon <icculus@icculus.org>
Sat, 03 Nov 2012 12:06:27 -0400
changeset 6640 44a2e00e7c66
parent 6639 c7e81fae23c4
child 6641 45187a87d35b
Make Linux dynamically look up pthread_setname_np() for older glibc compat. Cleaned up the lookup code to make Mac OS X use most of the same code.
src/thread/pthread/SDL_systhread.c
--- a/src/thread/pthread/SDL_systhread.c	Fri Nov 02 16:48:47 2012 -0400
+++ b/src/thread/pthread/SDL_systhread.c	Sat Nov 03 12:06:27 2012 -0400
@@ -28,21 +28,19 @@
 #endif
 
 #include <signal.h>
+
 #ifdef __LINUX__
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/syscall.h>
 #include <unistd.h>
-
-#if HAVE_PTHREAD_SETNAME_NP
-extern int pthread_setname_np (pthread_t __target_thread, __const char *__name) __THROW __nonnull ((2));
-#endif
 #endif // __LINUX__
 
-#if ( (__MACOSX__ && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) || \
-      (__IPHONEOS__ && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)) )
-#define NEED_DYNAMIC_PTHREAD_SETNAME_NP
+#if defined(__LINUX__) || defined(__MACOSX__) || defined(__IPHONEOS__)
 #include <dlfcn.h>
+#ifndef RTLD_DEFAULT
+#define RTLD_DEFAULT NULL
+#endif
 #endif
 
 #include "SDL_platform.h"
@@ -53,6 +51,8 @@
 #include "../../core/android/SDL_android.h"
 #endif
 
+#include "SDL_assert.h"
+
 /* List of signals to mask in the subthreads */
 static const int sig_list[] = {
     SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
@@ -70,11 +70,31 @@
     return NULL;
 }
 
+#if defined(__MACOSX__) || defined(__IPHONEOS__)
+static SDL_bool checked_setname = SDL_FALSE;
+static int (*pthread_setname_np)(const char*) = NULL;
+#elif defined(__LINUX__)
+static SDL_bool checked_setname = SDL_FALSE;
+static int (*pthread_setname_np)(pthread_t, const char*) = NULL;
+#endif
 int
 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
 {
     pthread_attr_t type;
 
+    /* do this here before any threads exist, so there's no race condition. */
+    #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
+    if (!checked_setname) {
+        void *fn = dlsym(RTLD_DEFAULT, "pthread_setname_np");
+        #if defined(__MACOSX__) || defined(__IPHONEOS__)
+        pthread_setname_np = (int(*)(const char*)) fn;
+        #elif defined(__LINUX__)
+        pthread_setname_np = (int(*)(pthread_t, const char*)) fn;
+        #endif
+        checked_setname = SDL_TRUE;
+    }
+    #endif
+
     /* Set the thread attributes */
     if (pthread_attr_init(&type) != 0) {
         SDL_SetError("Couldn't initialize pthread attributes");
@@ -98,16 +118,20 @@
     sigset_t mask;
 
     if (name != NULL) {
-#ifdef NEED_DYNAMIC_PTHREAD_SETNAME_NP
-        int (*dynamic_pthread_setname_np)(const char*);
-        *(void**)(&dynamic_pthread_setname_np) = dlsym(RTLD_DEFAULT, "pthread_setname_np");
-        if ( dynamic_pthread_setname_np )
-            dynamic_pthread_setname_np( name );
-#elif HAVE_PTHREAD_SETNAME_NP
-        pthread_setname_np(pthread_self(), name);
-#elif HAVE_PTHREAD_SET_NAME_NP
-        pthread_set_name_np(pthread_self(), name);
-#endif
+        #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
+        SDL_assert(checked_setname);
+        if (pthread_setname_np) {
+            #if defined(__MACOSX__) || defined(__IPHONEOS__)
+            pthread_setname_np(name);
+            #elif defined(__LINUX__)
+            pthread_setname_np(pthread_self(), name);
+            #endif
+        }
+        #elif HAVE_PTHREAD_SETNAME_NP
+            pthread_setname_np(pthread_self(), name);
+        #elif HAVE_PTHREAD_SET_NAME_NP
+            pthread_set_name_np(pthread_self(), name);
+        #endif
     }
 
     /* Mask asynchronous signals for this thread */