From e8c1dc340f7ec5efd078d0a79ccff442056c71c6 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Mon, 22 Apr 2013 10:48:40 +0200 Subject: core: Rewrite code for thread local storage The original code in wcore_tinfo.c for handling thread local info was a mess. It was my first time writing thread local code in a non-classroom setting. This patch rewrites wcore_tinfo.c, reducing the lines of code from ~130 to ~50. The rewrite does the following: - Require that the compiler support thread local storage through the keyword '__thread'. This allows us to remove use of pthread_key_t. - Remove all mutexes. There is no need to protect thread-local storage with mutexes. Tested with `make check-func` on GLX, XEGL, and Wayland. Signed-off-by: Chad Versace --- src/waffle/core/wcore_tinfo.c | 115 ++++++------------------------------------ src/waffle/core/wcore_tinfo.h | 2 + 2 files changed, 18 insertions(+), 99 deletions(-) diff --git a/src/waffle/core/wcore_tinfo.c b/src/waffle/core/wcore_tinfo.c index 87c1579..e40cb30 100644 --- a/src/waffle/core/wcore_tinfo.c +++ b/src/waffle/core/wcore_tinfo.c @@ -28,6 +28,7 @@ /// @file +#include #include #include #include @@ -37,14 +38,7 @@ #include "wcore_error.h" #include "wcore_tinfo.h" -/// @brief Key for @ref wcore_tinfo_tl_singleton. -static pthread_key_t wcore_tinfo_key; - -#ifdef WAFFLE_HAS_TLS - -/// @brief Thread-local singleton for thread info. -/// -/// There exists a distinct pointer for each thread. +/// @brief Thread-local storage for all of Waffle. /// /// For documentation on the tls_model, see the GCC manual [1] and /// Drepper [2]. @@ -55,115 +49,38 @@ static pthread_key_t wcore_tinfo_key; /// [2] Ulrich Drepper. "Elf Handling For Thread Local Storage". /// http://people.redhat.com/drepper/tls.pdf -static __thread struct wcore_tinfo *wcore_tinfo_tl_singleton +static __thread struct wcore_tinfo wcore_tinfo #ifdef WAFFLE_HAS_TLS_MODEL_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) #endif ; -#endif - static void -wcore_tinfo_destroy(struct wcore_tinfo *self) +wcore_tinfo_init(void) { - if (!self) - return; - - if (self->error) - wcore_error_tinfo_destroy(self->error); + assert(!wcore_tinfo.is_init); - free(self); -} - -static struct wcore_tinfo* -wcore_tinfo_create(void) -{ - struct wcore_tinfo *self = calloc(1, sizeof(*self)); - if (!self) - goto error; - - self->error = wcore_error_tinfo_create(); - if (!self->error) + // FIXME: wcore_tinfo.error leaks at thread exit. To fix this, Waffle + // FIXME: needs a function like eglTerminate(). + wcore_tinfo.error = wcore_error_tinfo_create(); + if (!wcore_tinfo.error) goto error; - return self; + wcore_tinfo.is_init = true; + return; error: - wcore_tinfo_destroy(self); - return NULL; -} - -/// @brief Initialize @ref wcore_tinfo_key. -/// -/// Once intialized, the key is never de-initialized. -static void -wcore_tinfo_key_init(void) -{ - static bool is_init = false; - - // The mutex protects is_init. - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - - if (is_init) - return; - - pthread_mutex_lock(&mutex); - { - int error; - - // Another thread may have initialized the key while this thread - // blocked on the mutex. - if (is_init) - goto unlock; - - error = pthread_key_create(&wcore_tinfo_key, - (void (*)(void*)) wcore_tinfo_destroy); - if (error) { - printf("waffle: fatal-error: pthread_key_create failed at " - "%s:%d\n", __FILE__, __LINE__); - abort(); - } - - is_init = true; - unlock:; - } - pthread_mutex_unlock(&mutex); + printf("waffle: fatal-error: failed to initialize thread local info\n"); + abort(); } struct wcore_tinfo* wcore_tinfo_get(void) { - struct wcore_tinfo *t; - - wcore_tinfo_key_init(); - - #ifdef WAFFLE_HAS_TLS - t = wcore_tinfo_tl_singleton; - #else - t = pthread_getspecific(wcore_tinfo_key); - #endif - - if (t == NULL) { - // If a key is assigned a non-null pointer, then the key's - // destructor will be called on that pointer when the thread exits. - // - // The key should be assigned to the pointer before the thread-local - // storage is assigned. If not, a memory leak will occur if a - // disaster occurs between assignment to thread-local storage and - // assignment to the key. - t = wcore_tinfo_create(); - if (!t) { - printf("waffle: fatal-error: failed to allocate thread info\n"); - abort(); - } - pthread_setspecific(wcore_tinfo_key, t); - - #ifdef WAFFLE_HAS_TLS - wcore_tinfo_tl_singleton = t; - #endif - } + if (!wcore_tinfo.is_init) + wcore_tinfo_init(); - return t; + return &wcore_tinfo; } /// @} diff --git a/src/waffle/core/wcore_tinfo.h b/src/waffle/core/wcore_tinfo.h index 8b8d1fa..a810d89 100644 --- a/src/waffle/core/wcore_tinfo.h +++ b/src/waffle/core/wcore_tinfo.h @@ -39,6 +39,8 @@ struct wcore_error_tinfo; struct wcore_tinfo { /// @brief Info for @ref wcore_error. struct wcore_error_tinfo *error; + + bool is_init; }; /// @brief Get the thread-local info for the current thread. -- cgit v1.2.3