From: Søren Sandmann Pedersen <s...@redhat.com> These macros hide the various types of thread local support. On Linux and Unix, they expand to just __thread. On Microsoft Visual C++, they expand to __declspec(thread).
On OS X and other systems that don't have __thread, they expand to a complicated concoction that uses pthread_once() and pthread_get/set_specific() to get thread local variables. --- configure.ac | 2 +- pixman/pixman-compiler.h | 63 +++++++++++++++++++++++++++++++++++++++++---- pixman/pixman.c | 37 ++++++++++++++++----------- 3 files changed, 80 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index 0bf5658..d790bf3 100644 --- a/configure.ac +++ b/configure.ac @@ -532,7 +532,7 @@ AC_MSG_CHECKING(for __thread) AC_COMPILE_IFELSE([ __thread int x ; int main () { return 0; } -], support_for__thread=yes) +], support_for__thread=no) if test $support_for__thread = yes; then AC_DEFINE([TOOLCHAIN_SUPPORTS__THREAD],[],[Whether the tool chain supports __thread]) diff --git a/pixman/pixman-compiler.h b/pixman/pixman-compiler.h index 5aeef86..a4e3f88 100644 --- a/pixman/pixman-compiler.h +++ b/pixman/pixman-compiler.h @@ -70,11 +70,62 @@ #endif /* TLS */ -#if (defined (__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR >= 3) || __GNUC__ > 3)) || defined(__SUNPRO_C) -# define THREAD_LOCAL __thread -#elif defined (_MSC_VER) -# define THREAD_LOCAL __declspec(thread) +#if defined(TOOLCHAIN_SUPPORTS__THREAD) + +# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ + static __thread type name +# define PIXMAN_GET_THREAD_LOCAL(name) \ + (&name) + +#elif defined(_MSC_VER) + +# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ + static __declspec(thread) type name +# define PIXMAN_GET_THREAD_LOCAL(name) \ + (&name) + +#elif defined(HAVE_PTHREAD_SETSPECIFIC) + +#include <pthread.h> + +# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ + static pthread_once_t tls_ ## name ## _once_control = PTHREAD_ONCE_INIT; \ + static pthread_key_t tls_ ## name ## _key; \ + \ + static void \ + tls_ ## name ## _make_key (void) \ + { \ + pthread_key_create (&tls_ ## name ## _key, NULL); \ + } \ + \ + static type * \ + tls_ ## name ## _alloc (key) \ + { \ + type *value = malloc (sizeof (type)); \ + if (value) \ + pthread_setspecific (key, value); \ + return value; \ + } \ + \ + static force_inline type * \ + tls_ ## name ## _get (key) \ + { \ + type *value = NULL; \ + if (pthread_once (&tls_ ## name ## _once_control, \ + tls_ ## name ## _make_key) == 0) \ + { \ + value = pthread_getspecific (tls_ ## name ## _key); \ + if (!value) \ + value = tls_ ## name ## _alloc (key); \ + } \ + return value; \ + } + +# define PIXMAN_GET_THREAD_LOCAL(name) \ + tls_ ## name ## _get (tls_ ## name ## _key) + #else -# warning "unknown compiler" -# define THREAD_LOCAL __thread + +# error "Unknown thread local support for this system" + #endif diff --git a/pixman/pixman.c b/pixman/pixman.c index c71617e..68483a0 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -499,6 +499,15 @@ image_covers (pixman_image_t *image, return TRUE; } +#define N_CACHED_FAST_PATHS 8 + +typedef struct +{ + pixman_fast_path_t cache [N_CACHED_FAST_PATHS]; +} cache_t; + +PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache); + static void do_composite (pixman_implementation_t *imp, pixman_op_t op, @@ -514,8 +523,6 @@ do_composite (pixman_implementation_t *imp, int width, int height) { -#define N_CACHED_FAST_PATHS 8 - static THREAD_LOCAL pixman_fast_path_t tls_cache[N_CACHED_FAST_PATHS]; pixman_format_code_t src_format, mask_format, dest_format; uint32_t src_flags, mask_flags, dest_flags; pixman_region32_t region; @@ -527,8 +534,8 @@ do_composite (pixman_implementation_t *imp, uint32_t *dest_bits; int dest_dx, dest_dy; pixman_bool_t need_workaround; - pixman_fast_path_t *cache; const pixman_fast_path_t *info; + cache_t *cache; int i; src_format = src->common.extended_format_code; @@ -597,11 +604,11 @@ do_composite (pixman_implementation_t *imp, return; /* Check cache for fast paths */ - cache = tls_cache; + cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache); for (i = 0; i < N_CACHED_FAST_PATHS; ++i) { - info = &(cache[i]); + info = &(cache->cache[i]); /* Note that we check for equality here, not whether * the cached fast path matches. This is to prevent @@ -677,16 +684,16 @@ found: pixman_composite_func_t func = info->func; while (i--) - cache[i + 1] = cache[i]; - - cache[0].op = op; - cache[0].src_format = src_format; - cache[0].src_flags = src_flags; - cache[0].mask_format = mask_format; - cache[0].mask_flags = mask_flags; - cache[0].dest_format = dest_format; - cache[0].dest_flags = dest_flags; - cache[0].func = func; + cache->cache[i + 1] = cache->cache[i]; + + cache->cache[0].op = op; + cache->cache[0].src_format = src_format; + cache->cache[0].src_flags = src_flags; + cache->cache[0].mask_format = mask_format; + cache->cache[0].mask_flags = mask_flags; + cache->cache[0].dest_format = dest_format; + cache->cache[0].dest_flags = dest_flags; + cache->cache[0].func = func; } out: -- 1.7.0.1 _______________________________________________ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman