summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2010-03-16 12:23:50 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2010-03-16 14:58:12 -0400
commit7c9f121efe7ee6afafad8b294974f5498054559b (patch)
treef87d863242a83d1b519ab113ac76aa21ede2f710
parent6b9c54820015f69e667ed54441e83042c9a84cc1 (diff)
Add PIXMAN_DEFINE_THREAD_LOCAL() and PIXMAN_GET_THREAD_LOCAL() macros
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.
-rw-r--r--pixman/pixman-compiler.h63
-rw-r--r--pixman/pixman.c37
2 files changed, 79 insertions, 21 deletions
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: