[Pixman] [PATCH] Adding TLS for Windows XP

Gang Ji gangji at google.com
Mon Mar 28 11:01:57 PDT 2011


Hi everyone,

It turned out that Windows XP does't support __declspec(thread).  In order
to make a multi-thread safe app using pixman, we tried to add TLS for
Windows XP. We have added using TLS primitives and tried to avoid memory
leak during cleaning up.

Thanks a lot!

Regards,
Gang

---

Index: pixman/pixman-win32-tls.c
===================================================================
--- pixman/pixman-win32-tls.c (revision 0)
+++ pixman/pixman-win32-tls.c (revision 235)
@@ -0,0 +1,85 @@
+#if defined(__MINGW32__) || (defined(_MSC_VER) && _WIN32_WINNT < 0x0600)
+
+#include "pixman-win32-tls.h"
+
+#include <stdlib.h>
+#include <windows.h>
+
+#include "pixman-compiler.h"
+#include "pixman-win32-tls-private.h"
+
+struct tls_entry {
+  DWORD *index;
+  volatile int *initialized;
+  struct tls_entry *next;
+};
+
+static struct tls_entry *tls_entries = NULL;
+static HANDLE win32_tls_mutex = NULL;
+
+static void tls_register (unsigned *index, volatile int *initialized) {
+  struct tls_entry *entry = malloc (sizeof(struct tls_entry));
+  if (entry != NULL) {
+    entry->index = index;
+    entry->initialized = initialized;
+    entry->next = tls_entries;
+    tls_entries = entry;
+  }
+}
+
+void _pixman_win32_tls_create (unsigned *index, volatile int *initialized)
{
+  if (win32_tls_mutex == NULL) {
+    HANDLE mutex = CreateMutex (NULL, 0, NULL);
+    if (InterlockedCompareExchangePointer (&win32_tls_mutex, mutex, NULL)
+        != NULL) {
+      CloseHandle (mutex);
+    }
+  }
+  WaitForSingleObject (win32_tls_mutex, INFINITE);
+  if (!(*initialized)) {
+    *index = TlsAlloc ();
+    tls_register (index, initialized);
+    *initialized = 1;
+  }
+  ReleaseMutex (win32_tls_mutex);
+}
+
+PIXMAN_EXPORT void pixman_win32_tls_shutdown_thread (void) {
+  struct tls_entry *entry = tls_entries;
+  while (entry != NULL) {
+    struct tls_entry *next = entry->next;
+    DWORD index = *entry->index;
+    void *data = TlsGetValue (index);
+    if (data != NULL) {
+      TlsSetValue (index, NULL);
+      free (data);
+    }
+    entry = next;
+  }
+}
+
+PIXMAN_EXPORT void pixman_win32_tls_shutdown (void) {
+  struct tls_entry *entry = tls_entries;
+  pixman_win32_tls_shutdown_thread ();
+  while (entry != NULL) {
+    struct tls_entry *next = entry->next;
+    DWORD index = *entry->index;
+    TlsFree (index);
+    entry->initialized = 0;
+    free (entry);
+    entry = next;
+  }
+  tls_entries = NULL;
+  CloseHandle (win32_tls_mutex);
+  win32_tls_mutex = NULL;
+}
+
+#elif defined(_MSC_VER)
+
+PIXMAN_EXPORT void pixman_win32_tls_shutdown_thread (void) {
+}
+
+PIXMAN_EXPORT void pixman_win32_tls_shutdown (void) {
+}
+
+#endif
Index: pixman/pixman-win32-tls.h
===================================================================
--- pixman/pixman-win32-tls.h (revision 0)
+++ pixman/pixman-win32-tls.h (revision 235)
@@ -0,0 +1,19 @@
+#ifndef PIXMAN_WIN32_TLS_H
+#define PIXMAN_WIN32_TLS_H
+
+#if defined(__MINGW32__) || defined(_MSC_VER)
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+void pixman_win32_tls_shutdown_thread (void);
+void pixman_win32_tls_shutdown (void);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
+
+#endif
Index: pixman/pixman-win32-tls-private.h
===================================================================
--- pixman/pixman-win32-tls-private.h (revision 0)
+++ pixman/pixman-win32-tls-private.h (revision 235)
@@ -0,0 +1,10 @@
+#ifndef PIXMAN_WIN32_TLS_PRIVATE_H
+#define PIXMAN_WIN32_TLS_PRIVATE_H
+
+#if defined(__MINGW32__) || (defined(_MSC_VER) && _WIN32_WINNT < 0x0600)
+
+void _pixman_win32_tls_create (unsigned *index, volatile int *initialized);
+
+#endif
+
+#endif
Index: pixman/pixman-compiler.h
===================================================================
--- pixman/pixman-compiler.h (revision 234)
+++ pixman/pixman-compiler.h (revision 235)
@@ -89,14 +89,13 @@
 #   define PIXMAN_GET_THREAD_LOCAL(name) \
     (&name)

-#elif defined(__MINGW32__)
+#elif defined(__MINGW32__) || (defined(_MSC_VER) && _WIN32_WINNT < 0x0600)

-#   define _NO_W32_PSEUDO_MODIFIERS
-#   include <windows.h>
+    /* MinGW and Windows XP doesn't support __declspec(thread) */
+#   include "pixman-win32-tls-private.h"

 #   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 * \
@@ -114,22 +113,8 @@
  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); \
+    _pixman_win32_tls_create (&tls_ ## name ## _index, \
+      &tls_ ## name ## _initialized); \
  } \
  if (tls_ ## name ## _index == 0xFFFFFFFF) \
     return NULL; \
Index: pixman/pixman.c
===================================================================
--- pixman/pixman.c (revision 234)
+++ pixman/pixman.c (revision 235)
@@ -26,6 +26,10 @@
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
+#if defined(__MINGW32__) || (defined(_MSC_VER) && _WIN32_WINNT < 0x0600)
+#include <windows.h>
+#endif
+
 #include "pixman-private.h"

 #include <stdlib.h>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/pixman/attachments/20110328/c266a166/attachment.htm>


More information about the Pixman mailing list