[Pixman] [PATCH 2/2] Add PIXMAN_DEFINE_THREAD_LOCAL() and PIXMAN_GET_THREAD_LOCAL() macros
Søren Sandmann
sandmann at daimi.au.dk
Tue Mar 16 09:52:16 PDT 2010
From: Søren Sandmann Pedersen <ssp at 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
More information about the Pixman
mailing list