summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2010-04-24 18:43:38 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2010-05-03 11:12:43 +0300
commit5158d6740c8e2643611a623a0caa649f4b0bc5bd (patch)
tree7a5f27c9dbaf94eda3aa64a6e257b61ea03437eb
parent582fa58bba7008c2b852ba56557612866f7522d5 (diff)
Add macros for thread local storage on MinGW 32
These macros are identical to the ones that Tor Lillqvist posted here: http://lists.freedesktop.org/archives/pixman/2010-April/000160.html with one exception: the variable is allocated with calloc() and not malloc(). Cc: tml@iki.fi
-rw-r--r--pixman/pixman-compiler.h65
1 files changed, 65 insertions, 0 deletions
diff --git a/pixman/pixman-compiler.h b/pixman/pixman-compiler.h
index 531c8c9..1a1350d 100644
--- a/pixman/pixman-compiler.h
+++ b/pixman/pixman-compiler.h
@@ -77,6 +77,71 @@
# define PIXMAN_GET_THREAD_LOCAL(name) \
(&name)
+#elif defined(__MINGW32__) && !defined(__WIN64)
+
+/* We can't include <windows.h> as it causes carious clashes with
+ * identifiers in pixman, sigh. So just declare the functions we need
+ * here.
+ */
+extern __stdcall long InterlockedCompareExchange(long volatile *, long, long);
+#define InterlockedCompareExchangePointer(d,e,c) \
+ (void *)InterlockedCompareExchange((long volatile *)(d),(long)(e),(long)(c))
+extern __stdcall int TlsAlloc (void);
+extern __stdcall void *TlsGetValue (unsigned);
+extern __stdcall int TlsSetValue (unsigned, void *);
+extern __stdcall void *CreateMutexA(void *, int, char *);
+extern __stdcall int CloseHandle(void *);
+extern __stdcall unsigned WaitForSingleObject (void *, unsigned);
+extern __stdcall int ReleaseMutex (void *);
+
+# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
+ static volatile int tls_ ## name ## _initialized = 0; \
+ static void *tls_ ## name ## _mutex = NULL; \
+ static unsigned tls_ ## name ## _index; \
+ \
+ static type * \
+ tls_ ## name ## _alloc (void) \
+ { \
+ type *value = calloc (1, sizeof (type)); \
+ if (value) \
+ TlsSetValue (tls_ ## name ## _index, value); \
+ return value; \
+ } \
+ \
+ static force_inline type * \
+ tls_ ## name ## _get (void) \
+ { \
+ type *value; \
+ if (!tls_ ## name ## _initialized) \
+ { \
+ if (!tls_ ## name ## _mutex) \
+ { \
+ void *mutex = CreateMutexA (NULL, 0, NULL); \
+ if (InterlockedCompareExchangePointer ( \
+ &tls_ ## name ## _mutex, mutex, NULL) != NULL) \
+ { \
+ CloseHandle (mutex); \
+ } \
+ } \
+ WaitForSingleObject (tls_ ## name ## _mutex, 0xFFFFFFFF); \
+ if (!tls_ ## name ## _initialized) \
+ { \
+ tls_ ## name ## _index = TlsAlloc (); \
+ tls_ ## name ## _initialized = 1; \
+ } \
+ ReleaseMutex (tls_ ## name ## _mutex); \
+ } \
+ if (tls_ ## name ## _index == 0xFFFFFFFF) \
+ return NULL; \
+ value = TlsGetValue (tls_ ## name ## _index); \
+ if (!value) \
+ value = tls_ ## name ## _alloc (); \
+ return value; \
+ }
+
+# define PIXMAN_GET_THREAD_LOCAL(name) \
+ tls_ ## name ## _get ()
+
#elif defined(_MSC_VER)
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \