summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2010-05-09 14:24:24 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2010-05-09 14:24:24 -0400
commit164fe215f2c904cf74537caf9d76b7f9ce2667ec (patch)
tree31e4c2476e8fdda6d74767dfec51e857f9af62ba
parente1594f204d3a3c2d2083793c8830f0ebf390ed66 (diff)
parent5158d6740c8e2643611a623a0caa649f4b0bc5bd (diff)
Merge branch 'for-master'
-rw-r--r--configure.ac3
-rw-r--r--pixman/pixman-compiler.h65
2 files changed, 68 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index aabe721..c9d0c66 100644
--- a/configure.ac
+++ b/configure.ac
@@ -524,6 +524,9 @@ support_for__thread=no
AC_MSG_CHECKING(for __thread)
AC_COMPILE_IFELSE([
+#ifdef __MINGW32__
+#error MinGW has broken __thread support
+#endif
__thread int x ;
int main () { return 0; }
], support_for__thread=yes)
diff --git a/pixman/pixman-compiler.h b/pixman/pixman-compiler.h
index c410717..f0f9d91 100644
--- a/pixman/pixman-compiler.h
+++ b/pixman/pixman-compiler.h
@@ -84,6 +84,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) \