[MINGW-W64]
[reactos.git] / reactos / lib / 3rdparty / mingw / tlssup.c
index f933fa6..1c32d0d 100644 (file)
@@ -1,18 +1,37 @@
 /**
  * This file has no copyright assigned and is placed in the Public Domain.
  * This file is part of the w64 mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within this package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ *
+ * Written by Kai Tietz  <kai.tietz@onevision.com>
  */
 
 #ifdef CRTDLL
 #undef CRTDLL
 #endif
 
-#include <internal.h>
 #include <sect_attribs.h>
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
 #include <windows.h>
+
+#include <stdio.h>
+#include <memory.h>
 #include <malloc.h>
-#include <crtdbg.h>
+#ifndef _WIN64
+#include <stdlib.h> /* for _winmajor */
+#endif
+
+#ifndef __INTERNAL_FUNC_DEFINED
+#define __INTERNAL_FUNC_DEFINED
+typedef void (__cdecl *_PVFV)(void);
+typedef int (__cdecl *_PIFV)(void);
+typedef void (__cdecl *_PVFI)(int);
+#endif
+
+extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
 
 #define FUNCS_PER_NODE 30
 
@@ -24,20 +43,21 @@ typedef struct TlsDtorNode {
 
 ULONG _tls_index = 0;
 
-_CRTALLOC(".tls") char _tls_start = 0;
+/* TLS raw template data start and end. */
+_CRTALLOC(".tls$AAA") char _tls_start = 0;
 _CRTALLOC(".tls$ZZZ") char _tls_end = 0;
 
 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
 
 #ifdef _WIN64
-_CRTALLOC(".rdata$T") const IMAGE_TLS_DIRECTORY64 _tls_used = {
-  (ULONGLONG) &_tls_start, (ULONGLONG) &_tls_end, (ULONGLONG) &_tls_index,
+_CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY64 _tls_used = {
+  (ULONGLONG) &_tls_start+1, (ULONGLONG) &_tls_end, (ULONGLONG) &_tls_index,
   (ULONGLONG) (&__xl_a+1), (ULONG) 0, (ULONG) 0
 };
 #else
-_CRTALLOC(".rdata$T") const IMAGE_TLS_DIRECTORY _tls_used = {
-  (ULONG)(ULONG_PTR) &_tls_start, (ULONG)(ULONG_PTR) &_tls_end,
+_CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY _tls_used = {
+  (ULONG)(ULONG_PTR) &_tls_start+1, (ULONG)(ULONG_PTR) &_tls_end,
   (ULONG)(ULONG_PTR) &_tls_index, (ULONG)(ULONG_PTR) (&__xl_a+1),
   (ULONG) 0, (ULONG) 0
 };
@@ -47,38 +67,93 @@ _CRTALLOC(".rdata$T") const IMAGE_TLS_DIRECTORY _tls_used = {
 #ifdef HAVE_ATTRIBUTE_THREAD
 #define __CRT_THREAD   __declspec(thread)
 #else
-#define __CRT_THREAD
+#define __CRT_THREAD    __thread
 #endif
 #endif
 
+#define DISABLE_MS_TLS 1
+
 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
+
+#if !defined (DISABLE_MS_TLS)
 static __CRT_THREAD TlsDtorNode *dtor_list;
 static __CRT_THREAD TlsDtorNode dtor_list_head;
+#endif
+
+extern int _CRT_MT;
+
+#ifndef _WIN64
+#define MINGWM10_DLL "mingwm10.dll"
+typedef int (*fMTRemoveKeyDtor)(DWORD key);
+typedef int (*fMTKeyDtor)(DWORD key, void (*dtor)(void *));
+fMTRemoveKeyDtor __mingw_gMTRemoveKeyDtor;
+fMTKeyDtor __mingw_gMTKeyDtor;
+int __mingw_usemthread_dll;
+static HANDLE __mingw_mthread_hdll;
+#endif
+
+BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
 
 BOOL WINAPI
 __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
 {
   _PVFV *pfunc;
 
-  if (dwReason != DLL_THREAD_ATTACH)
+#ifndef _WIN64
+  if (_winmajor < 4)
+  {
+    __mingw_usemthread_dll = 1;
+    __mingw_mthread_hdll = LoadLibrary (MINGWM10_DLL);
+    if (__mingw_mthread_hdll != NULL)
+    {
+      __mingw_gMTRemoveKeyDtor = (fMTRemoveKeyDtor) GetProcAddress (__mingw_mthread_hdll, "__mingwthr_remove_key_dtor");
+      __mingw_gMTKeyDtor = (fMTKeyDtor)  GetProcAddress (__mingw_mthread_hdll, "__mingwthr_key_dtor");
+    }
+    if (__mingw_mthread_hdll == NULL || !__mingw_gMTRemoveKeyDtor || !__mingw_gMTKeyDtor)
+      {
+       __mingw_gMTKeyDtor = NULL;
+       __mingw_gMTRemoveKeyDtor = NULL;
+       if (__mingw_mthread_hdll)
+         FreeLibrary (__mingw_mthread_hdll);
+       __mingw_mthread_hdll = NULL;
+       _CRT_MT = 0;
+       return TRUE;
+      }
+    _CRT_MT = 1;
     return TRUE;
+  }
+#endif
+  /* We don't let us trick here.  */
+  if (_CRT_MT != 2)
+   _CRT_MT = 2;
+
+  if (dwReason != DLL_THREAD_ATTACH)
+    {
+      if (dwReason == DLL_PROCESS_ATTACH)
+        __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
+      return TRUE;
+    }
 
   for (pfunc = &__xd_a + 1; pfunc != &__xd_z; ++pfunc)
     {
       if (*pfunc != NULL)
        (*pfunc)();
     }
-
   return TRUE;
 }
 
 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init;
 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init;
 
+int __cdecl __tlregdtor (_PVFV);
+
 int __cdecl
 __tlregdtor (_PVFV func)
 {
+  if (!func)
+    return 0;
+#if !defined (DISABLE_MS_TLS)
   if (dtor_list == NULL)
     {
       dtor_list = &dtor_list_head;
@@ -96,29 +171,42 @@ __tlregdtor (_PVFV func)
       dtor_list->count = 0;
     }
   dtor_list->funcs[dtor_list->count++] = func;
+#endif
   return 0;
 }
 
 static BOOL WINAPI
 __dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
 {
+#if !defined (DISABLE_MS_TLS)
   TlsDtorNode *pnode, *pnext;
   int i;
+#endif
 
   if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
     return TRUE;
-
-  for (pnode = dtor_list; pnode != NULL; pnode = pnext)
+  /* As TLS variables are detroyed already by DLL_THREAD_DETACH
+     call, we have to avoid access on the possible DLL_PROCESS_DETACH
+     call the already destroyed TLS vars.
+     TODO: The used local thread based variables have to be handled
+     manually, so that we can control their lifetime here.  */
+#if !defined (DISABLE_MS_TLS)
+  if (dwReason != DLL_PROCESS_DETACH)
     {
-      for (i = pnode->count - 1; i >= 0; --i)
-       {
-         if (pnode->funcs[i] != NULL)
-           (*pnode->funcs[i])();
-       }
-      pnext = pnode->next;
-      if (pnext != NULL)
-       free ((void *) pnode);
+      for (pnode = dtor_list; pnode != NULL; pnode = pnext)
+        {
+          for (i = pnode->count - 1; i >= 0; --i)
+           {
+             if (pnode->funcs[i] != NULL)
+               (*pnode->funcs[i])();
+           }
+          pnext = pnode->next;
+          if (pnext != NULL)
+           free ((void *) pnode);
+        }
     }
+#endif
+  __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
   return TRUE;
 }
 
@@ -126,5 +214,5 @@ _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_t
 
 
 int mingw_initltsdrot_force = 0;
-int mingw_initltsdyn_force=0;
+int mingw_initltsdyn_force = 0;
 int mingw_initltssuo_force = 0;