Hi everyone,<div><br></div><div>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.</div>
<div><br></div><div>Thanks a lot!</div><div><br></div><div>Regards,</div><div>Gang</div><div><br></div><div>---</div><div><br></div><div><div>Index: pixman/pixman-win32-tls.c</div><div>===================================================================</div>
<div>--- pixman/pixman-win32-tls.c<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 0)</div><div>+++ pixman/pixman-win32-tls.c<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 235)</div>
<div>@@ -0,0 +1,85 @@</div><div>+#if defined(__MINGW32__) || (defined(_MSC_VER) && _WIN32_WINNT < 0x0600)</div><div>+</div><div>+#include "pixman-win32-tls.h"</div><div>+</div><div>+#include <stdlib.h></div>
<div>+#include <windows.h></div><div>+</div><div>+#include "pixman-compiler.h"</div><div>+#include "pixman-win32-tls-private.h"</div><div>+</div><div>+struct tls_entry {</div><div>+ DWORD *index;</div>
<div>+ volatile int *initialized;</div><div>+ struct tls_entry *next;</div><div>+};</div><div>+</div><div>+static struct tls_entry *tls_entries = NULL;</div><div>+static HANDLE win32_tls_mutex = NULL;</div><div>+</div><div>
+static void tls_register (unsigned *index, volatile int *initialized) {</div><div>+ struct tls_entry *entry = malloc (sizeof(struct tls_entry));</div><div>+ if (entry != NULL) {</div><div>+ entry->index = index;</div>
<div>+ entry->initialized = initialized;</div><div>+ entry->next = tls_entries;</div><div>+ tls_entries = entry;</div><div>+ }</div><div>+}</div><div>+</div><div>+void _pixman_win32_tls_create (unsigned *index, volatile int *initialized) {</div>
<div>+ if (win32_tls_mutex == NULL) {</div><div>+ HANDLE mutex = CreateMutex (NULL, 0, NULL);</div><div>+ if (InterlockedCompareExchangePointer (&win32_tls_mutex, mutex, NULL)</div><div>+ != NULL) {</div>
<div>+ CloseHandle (mutex);</div><div>+ }</div><div>+ }</div><div>+ WaitForSingleObject (win32_tls_mutex, INFINITE);</div><div>+ if (!(*initialized)) {</div><div>+ *index = TlsAlloc ();</div><div>+ tls_register (index, initialized);</div>
<div>+ *initialized = 1;</div><div>+ }</div><div>+ ReleaseMutex (win32_tls_mutex);</div><div>+}</div><div>+</div><div>+PIXMAN_EXPORT void pixman_win32_tls_shutdown_thread (void) {</div><div>+ struct tls_entry *entry = tls_entries;</div>
<div>+ while (entry != NULL) {</div><div>+ struct tls_entry *next = entry->next;</div><div>+ DWORD index = *entry->index;</div><div>+ void *data = TlsGetValue (index);</div><div>+ if (data != NULL) {</div>
<div>+ TlsSetValue (index, NULL);</div><div>+ free (data);</div><div>+ }</div><div>+ entry = next;</div><div>+ }</div><div>+}</div><div>+</div><div>+PIXMAN_EXPORT void pixman_win32_tls_shutdown (void) {</div>
<div>+ struct tls_entry *entry = tls_entries;</div><div>+ pixman_win32_tls_shutdown_thread ();</div><div>+ while (entry != NULL) {</div><div>+ struct tls_entry *next = entry->next;</div><div>+ DWORD index = *entry->index;</div>
<div>+ TlsFree (index);</div><div>+ entry->initialized = 0;</div><div>+ free (entry);</div><div>+ entry = next;</div><div>+ }</div><div>+ tls_entries = NULL;</div><div>+ CloseHandle (win32_tls_mutex);</div>
<div>+ win32_tls_mutex = NULL;</div><div>+}</div><div>+</div><div>+#elif defined(_MSC_VER)</div><div>+</div><div>+PIXMAN_EXPORT void pixman_win32_tls_shutdown_thread (void) {</div><div>+}</div><div>+</div><div>+PIXMAN_EXPORT void pixman_win32_tls_shutdown (void) {</div>
<div>+}</div><div>+</div><div>+#endif</div><div>Index: pixman/pixman-win32-tls.h</div><div>===================================================================</div><div>--- pixman/pixman-win32-tls.h<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 0)</div>
<div>+++ pixman/pixman-win32-tls.h<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 235)</div><div>@@ -0,0 +1,19 @@</div><div>+#ifndef PIXMAN_WIN32_TLS_H</div><div>+#define PIXMAN_WIN32_TLS_H</div><div>
+</div><div>+#if defined(__MINGW32__) || defined(_MSC_VER)</div><div>+</div><div>+#ifdef __cplusplus</div><div>+extern "C" {</div><div>+#endif</div><div>+</div><div>+void pixman_win32_tls_shutdown_thread (void);</div>
<div>+void pixman_win32_tls_shutdown (void);</div><div>+</div><div>+#ifdef __cplusplus</div><div>+}</div><div>+#endif</div><div>+</div><div>+#endif</div><div>+</div><div>+#endif</div><div>Index: pixman/pixman-win32-tls-private.h</div>
<div>===================================================================</div><div>--- pixman/pixman-win32-tls-private.h<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 0)</div><div>+++ pixman/pixman-win32-tls-private.h<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 235)</div>
<div>@@ -0,0 +1,10 @@</div><div>+#ifndef PIXMAN_WIN32_TLS_PRIVATE_H</div><div>+#define PIXMAN_WIN32_TLS_PRIVATE_H</div><div>+</div><div>+#if defined(__MINGW32__) || (defined(_MSC_VER) && _WIN32_WINNT < 0x0600)</div>
<div>+</div><div>+void _pixman_win32_tls_create (unsigned *index, volatile int *initialized);</div><div>+</div><div>+#endif</div><div>+</div><div>+#endif</div><div>Index: pixman/pixman-compiler.h</div><div>===================================================================</div>
<div>--- pixman/pixman-compiler.h<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 234)</div><div>+++ pixman/pixman-compiler.h<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 235)</div>
<div>@@ -89,14 +89,13 @@</div><div> # define PIXMAN_GET_THREAD_LOCAL(name)<span class="Apple-tab-span" style="white-space:pre">                                </span>\</div><div> (&name)</div><div> </div><div>-#elif defined(__MINGW32__)</div>
<div>+#elif defined(__MINGW32__) || (defined(_MSC_VER) && _WIN32_WINNT < 0x0600)</div><div> </div><div>-# define _NO_W32_PSEUDO_MODIFIERS</div><div>-# include <windows.h></div><div>+ /* MinGW and Windows XP doesn't support __declspec(thread) */</div>
<div>+# include "pixman-win32-tls-private.h"</div><div> </div><div> # define PIXMAN_DEFINE_THREAD_LOCAL(type, name)<span class="Apple-tab-span" style="white-space:pre">                        </span>\</div><div> static volatile int tls_ ## name ## _initialized = 0;<span class="Apple-tab-span" style="white-space:pre">                </span>\</div>
<div>- static void *tls_ ## name ## _mutex = NULL;<span class="Apple-tab-span" style="white-space:pre">                                </span>\</div><div> static unsigned tls_ ## name ## _index;<span class="Apple-tab-span" style="white-space:pre">                                </span>\</div>
<div> <span class="Apple-tab-span" style="white-space:pre">                                                                        </span>\</div><div> static type *<span class="Apple-tab-span" style="white-space:pre">                                                        </span>\</div><div>@@ -114,22 +113,8 @@</div><div> <span class="Apple-tab-span" style="white-space:pre">        </span>type *value;<span class="Apple-tab-span" style="white-space:pre">                                                        </span>\</div>
<div> <span class="Apple-tab-span" style="white-space:pre">        </span>if (!tls_ ## name ## _initialized)<span class="Apple-tab-span" style="white-space:pre">                                </span>\</div><div> <span class="Apple-tab-span" style="white-space:pre">        </span>{<span class="Apple-tab-span" style="white-space:pre">                                                                </span>\</div>
<div>-<span class="Apple-tab-span" style="white-space:pre">        </span> if (!tls_ ## name ## _mutex)<span class="Apple-tab-span" style="white-space:pre">                                </span>\</div><div>-<span class="Apple-tab-span" style="white-space:pre">        </span> {<span class="Apple-tab-span" style="white-space:pre">                                                                </span>\</div>
<div>-<span class="Apple-tab-span" style="white-space:pre">                </span>void *mutex = CreateMutexA (NULL, 0, NULL);<span class="Apple-tab-span" style="white-space:pre">                </span>\</div><div>-<span class="Apple-tab-span" style="white-space:pre">                </span>if (InterlockedCompareExchangePointer (<span class="Apple-tab-span" style="white-space:pre">                        </span>\</div>
<div>-<span class="Apple-tab-span" style="white-space:pre">                        </span>&tls_ ## name ## _mutex, mutex, NULL) != NULL)<span class="Apple-tab-span" style="white-space:pre">        </span>\</div><div>-<span class="Apple-tab-span" style="white-space:pre">                </span>{<span class="Apple-tab-span" style="white-space:pre">                                                        </span>\</div>
<div>-<span class="Apple-tab-span" style="white-space:pre">                </span> CloseHandle (mutex);<span class="Apple-tab-span" style="white-space:pre">                                </span>\</div><div>-<span class="Apple-tab-span" style="white-space:pre">                </span>}<span class="Apple-tab-span" style="white-space:pre">                                                        </span>\</div>
<div>-<span class="Apple-tab-span" style="white-space:pre">        </span> }<span class="Apple-tab-span" style="white-space:pre">                                                                </span>\</div><div>-<span class="Apple-tab-span" style="white-space:pre">        </span> WaitForSingleObject (tls_ ## name ## _mutex, 0xFFFFFFFF);<span class="Apple-tab-span" style="white-space:pre">        </span>\</div>
<div>-<span class="Apple-tab-span" style="white-space:pre">        </span> if (!tls_ ## name ## _initialized)<span class="Apple-tab-span" style="white-space:pre">                                </span>\</div><div>-<span class="Apple-tab-span" style="white-space:pre">        </span> {<span class="Apple-tab-span" style="white-space:pre">                                                                </span>\</div>
<div>-<span class="Apple-tab-span" style="white-space:pre">                </span>tls_ ## name ## _index = TlsAlloc ();<span class="Apple-tab-span" style="white-space:pre">                        </span>\</div><div>-<span class="Apple-tab-span" style="white-space:pre">                </span>tls_ ## name ## _initialized = 1;<span class="Apple-tab-span" style="white-space:pre">                        </span>\</div>
<div>-<span class="Apple-tab-span" style="white-space:pre">        </span> }<span class="Apple-tab-span" style="white-space:pre">                                                                </span>\</div><div>-<span class="Apple-tab-span" style="white-space:pre">        </span> ReleaseMutex (tls_ ## name ## _mutex);<span class="Apple-tab-span" style="white-space:pre">                        </span>\</div>
<div>+<span class="Apple-tab-span" style="white-space:pre">        </span> _pixman_win32_tls_create (&tls_ ## name ## _index,<span class="Apple-tab-span" style="white-space:pre">                </span>\</div><div>+<span class="Apple-tab-span" style="white-space:pre">                                </span> &tls_ ## name ## _initialized);<span class="Apple-tab-span" style="white-space:pre">        </span>\</div>
<div> <span class="Apple-tab-span" style="white-space:pre">        </span>}<span class="Apple-tab-span" style="white-space:pre">                                                                </span>\</div><div> <span class="Apple-tab-span" style="white-space:pre">        </span>if (tls_ ## name ## _index == 0xFFFFFFFF)<span class="Apple-tab-span" style="white-space:pre">                        </span>\</div>
<div> <span class="Apple-tab-span" style="white-space:pre">        </span> return NULL;<span class="Apple-tab-span" style="white-space:pre">                                                </span>\</div><div>Index: pixman/pixman.c</div><div>===================================================================</div>
<div>--- pixman/pixman.c<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 234)</div><div>+++ pixman/pixman.c<span class="Apple-tab-span" style="white-space:pre">        </span>(revision 235)</div><div>@@ -26,6 +26,10 @@</div>
<div> #ifdef HAVE_CONFIG_H</div><div> #include <config.h></div><div> #endif</div><div>+#if defined(__MINGW32__) || (defined(_MSC_VER) && _WIN32_WINNT < 0x0600)</div><div>+#include <windows.h></div><div>
+#endif</div><div>+</div><div> #include "pixman-private.h"</div><div> </div><div> #include <stdlib.h></div></div>