]> git.draconx.ca Git - cdecl99.git/blobdiff - src/thread-w32.h
libcdecl: Fix TLS cleanup on Windows.
[cdecl99.git] / src / thread-w32.h
index 181ebfc6191a48e30f9afb3ecec3a830802b4682..393f0ded0f95fef5420d0313f1a0fd6be721aab0 100644 (file)
@@ -33,7 +33,7 @@
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
-static DWORD tls_key;
+static DWORD tls_key = TLS_OUT_OF_INDEXES;
 #define tls_key_valid (tls_key != TLS_OUT_OF_INDEXES)
 
 static void init_once_cb(void);
@@ -158,3 +158,37 @@ static int init_once(void)
 
        return 1;
 }
+
+#if !TEST_W32_NO_DLLMAIN
+
+/*
+ * On Windows, DLLs are notified of thread exit via the DllMain entry point.
+ * This works in all versions.
+ */
+#if !DLL_EXPORT
+static
+#endif
+BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID p)
+{
+       if (reason == DLL_THREAD_DETACH && tls_key != TLS_OUT_OF_INDEXES)
+               free(TlsGetValue(tls_key));
+
+       return TRUE;
+}
+
+/*
+ * We can achieve similar behaviour with static linking executables by
+ * putting a pointer to the entry point in a special section.
+ *
+ * I believe this is supported beginning around Windows XP.
+ */
+#if !DLL_EXPORT
+#pragma data_seg(".CRT$XLF")
+#if __GNUC__
+__attribute__((section(".CRT$XLF")))
+#endif
+PIMAGE_TLS_CALLBACK cdecl__tls_hook = (PIMAGE_TLS_CALLBACK)DllMain;
+#pragma data_seg()
+#endif
+
+#endif