unify static TLS support, make use of gcc __thread attribute if available
authorLennart Poettering <lennart@poettering.net>
Mon, 10 Sep 2007 23:57:10 +0000 (23:57 +0000)
committerLennart Poettering <lennart@poettering.net>
Mon, 10 Sep 2007 23:57:10 +0000 (23:57 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1797 fefdeb5f-60dc-0310-8127-8f9354f1896f

configure.ac
src/daemon/main.c
src/pulsecore/atomic.h
src/pulsecore/rtsig.c
src/pulsecore/thread-mq.c
src/pulsecore/thread-posix.c
src/pulsecore/thread.h

index c4f26c4..7c8f388 100644 (file)
@@ -118,6 +118,18 @@ else
     AC_MSG_RESULT([no])
 fi
 
+AC_MSG_CHECKING([whether $CC knows __thread])
+AC_LANG_CONFTEST([static __thread int a = 6; int main() { a = 5; }])
+$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null
+ret=$?
+rm -f conftest.o conftest
+if test $ret -eq 0 ; then
+    AC_DEFINE([HAVE_TLS_BUILTIN], 1, [Have __thread().])
+    AC_MSG_RESULT([yes])
+else
+    AC_MSG_RESULT([no])
+fi
+
 #### libtool stuff ####
 
 AC_LTDL_ENABLE_INSTALL
index 135a9ab..ed5aa44 100644 (file)
@@ -324,14 +324,14 @@ static void libtool_unlock(void) {
     pa_mutex_unlock(libtool_mutex);
 }
 
-PA_STATIC_TLS_DECLARE(libtool_tls, NULL);
+PA_STATIC_TLS_DECLARE_NO_FREE(libtool_tls);
 
 static void libtool_set_error(const char * error) {
-    pa_tls_set(PA_STATIC_TLS_GET(libtool_tls), (char*) error);
+    PA_STATIC_TLS_SET(libtool_tls, (char*) error);
 }
 
 static const char *libtool_get_error(void) {
-    return pa_tls_get(PA_STATIC_TLS_GET(libtool_tls));
+    return PA_STATIC_TLS_GET(libtool_tls);
 }
 
 static void libtool_init(void)  {
index 6fb85f0..0e3bfb9 100644 (file)
@@ -37,7 +37,7 @@
  * libatomic_ops
  */
 
-/* We have to include config.h here, which sucks */
+/* We have to include config.h here (for the __sync stuff), which sucks */
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
index a3226a0..3513bed 100644 (file)
@@ -71,13 +71,13 @@ int pa_rtsig_get_for_thread(void) {
     int sig;
     void *p;
 
-    if ((p = pa_tls_get(PA_STATIC_TLS_GET(rtsig_tls))))
+    if ((p = PA_STATIC_TLS_GET(rtsig_tls)))
         return PA_PTR_TO_INT(p);
     
     if ((sig = pa_rtsig_get()) < 0)
         return -1;
 
-    pa_tls_set(PA_STATIC_TLS_GET(rtsig_tls), PA_INT_TO_PTR(sig));
+    PA_STATIC_TLS_SET(rtsig_tls, PA_INT_TO_PTR(sig));
     return sig;
 }
 
index 3c466ce..3000246 100644 (file)
@@ -41,8 +41,7 @@
 
 #include "thread-mq.h"
 
-static pa_once once = PA_ONCE_INIT;
-static pa_tls *tls;
+PA_STATIC_TLS_DECLARE_NO_FREE(thread_mq);
 
 static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
     pa_thread_mq *q = userdata;
@@ -101,20 +100,15 @@ void pa_thread_mq_done(pa_thread_mq *q) {
     q->mainloop = NULL;
 }
 
-static void init_tls(void) {
-    tls = pa_tls_new(NULL);
-}
-
 void pa_thread_mq_install(pa_thread_mq *q) {
     pa_assert(q);
 
-    pa_run_once(&once, init_tls);
-    pa_tls_set(tls, q);
+    pa_assert(!(PA_STATIC_TLS_GET(thread_mq)));
+    PA_STATIC_TLS_SET(thread_mq, q);
 }
 
 pa_thread_mq *pa_thread_mq_get(void) {
-    pa_run_once(&once, init_tls);
-    return pa_tls_get(tls);
+    return PA_STATIC_TLS_GET(thread_mq);
 }
 
 int pa_thread_mq_process(pa_thread_mq *q) {
index 6ad5ac4..3c69adf 100644 (file)
@@ -49,9 +49,6 @@ struct pa_tls {
     pthread_key_t key;
 };
 
-static pthread_key_t thread_key;
-static pthread_once_t thread_once = PTHREAD_ONCE_INIT;
-
 static void thread_free_cb(void *p) {
     pa_thread *t = p;
 
@@ -62,9 +59,7 @@ static void thread_free_cb(void *p) {
         pa_xfree(t);
 }
 
-static void thread_once_func(void) {
-    pa_assert_se(pthread_key_create(&thread_key, thread_free_cb) == 0);
-}
+PA_STATIC_TLS_DECLARE(current_thread, thread_free_cb);
 
 static void* internal_thread_func(void *userdata) {
     pa_thread *t = userdata;
@@ -72,8 +67,7 @@ static void* internal_thread_func(void *userdata) {
 
     t->id = pthread_self();
 
-    pthread_once(&thread_once, thread_once_func);
-    pthread_setspecific(thread_key, t);
+    PA_STATIC_TLS_SET(current_thread, t);
 
     pa_atomic_inc(&t->running);
     t->thread_func(t->userdata);
@@ -130,11 +124,9 @@ int pa_thread_join(pa_thread *t) {
 pa_thread* pa_thread_self(void) {
     pa_thread *t;
 
-    pthread_once(&thread_once, thread_once_func);
-
-    if ((t = pthread_getspecific(thread_key)))
+    if ((t = PA_STATIC_TLS_GET(current_thread)))
         return t;
-
+        
     /* This is a foreign thread, let's create a pthread structure to
      * make sure that we can always return a sensible pointer */
 
@@ -144,7 +136,7 @@ pa_thread* pa_thread_self(void) {
     t->userdata = NULL;
     pa_atomic_store(&t->running, 2);
 
-    pthread_setspecific(thread_key, t);
+    PA_STATIC_TLS_SET(current_thread, t);
 
     return t;
 }
index 44b80a0..a0e331b 100644 (file)
 ***/
 
 #include <pulse/def.h>
+#include <pulsecore/once.h>
+
+/* We have to include config.h here (for the __tls stuff), which sucks */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 typedef struct pa_thread pa_thread;
 
@@ -48,8 +54,6 @@ void pa_tls_free(pa_tls *t);
 void * pa_tls_get(pa_tls *t);
 void *pa_tls_set(pa_tls *t, void *userdata);
 
-/* To make use of the static TLS stuff you have to include once.h, as well */
-
 #define PA_STATIC_TLS_DECLARE(name, free_cb)                            \
     static struct {                                                     \
         pa_once once;                                                   \
@@ -61,7 +65,7 @@ void *pa_tls_set(pa_tls *t, void *userdata);
     static void name##_tls_init(void) {                                 \
         name##_tls.tls = pa_tls_new(free_cb);                           \
     }                                                                   \
-    static inline pa_tls* name##_tls_get(void) {                        \
+    static inline pa_tls* name##_tls_obj(void) {                        \
         pa_run_once(&name##_tls.once, name##_tls_init);                 \
         return name##_tls.tls;                                          \
     }                                                                   \
@@ -70,8 +74,33 @@ void *pa_tls_set(pa_tls *t, void *userdata);
         if (name##_tls.tls)                                             \
             pa_tls_free(name##_tls.tls);                                \
     }                                                                   \
+    static inline void* name##_tls_get(void) {                          \
+        return pa_tls_get(name##_tls_obj());                            \
+    }                                                                   \
+    static inline void* name##_tls_set(void *p) {                       \
+        return pa_tls_set(name##_tls_obj(), p);                         \
+    }                                                                   \
     struct __stupid_useless_struct_to_allow_trailing_semicolon
 
+#ifdef HAVE_TLS_BUILTIN
+/* An optimized version of the above that requires no dynamic
+ * allocation if the compiler supports __thread */
+#define PA_STATIC_TLS_DECLARE_NO_FREE(name)                             \
+    static __thread void *name##_tls;                                   \
+    static inline void* name##_tls_get(void) {                          \
+        return name##_tls;                                              \
+    }                                                                   \
+    static inline void* name##_tls_set(void *p) {                       \
+        void *r = name##_tls;                                           \
+        name##_tls = p;                                                 \
+        return r;                                                       \
+    }                                                                   \
+    struct __stupid_useless_struct_to_allow_trailing_semicolon
+#else
+#define PA_STATIC_TLS_DECLARE_NO_FREE(name) PA_STATIC_TLS_DECLARE(name, NULL)
+#endif
+
 #define PA_STATIC_TLS_GET(name) (name##_tls_get())
+#define PA_STATIC_TLS_SET(name, p) (name##_tls_set(p))
 
 #endif