summaryrefslogtreecommitdiffstats
path: root/winsup/mingw/tlssup.c
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/mingw/tlssup.c')
-rw-r--r--winsup/mingw/tlssup.c213
1 files changed, 213 insertions, 0 deletions
diff --git a/winsup/mingw/tlssup.c b/winsup/mingw/tlssup.c
new file mode 100644
index 000000000..b101d1124
--- /dev/null
+++ b/winsup/mingw/tlssup.c
@@ -0,0 +1,213 @@
+/**
+ * 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.
+ *
+ * Written by Kai Tietz <kai.tietz@onevision.com>
+ */
+
+#ifdef CRTDLL
+#undef CRTDLL
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include <memory.h>
+#include <malloc.h>
+
+#ifndef _CRTALLOC
+#define _CRTALLOC(x) __attribute__ ((section (x) ))
+#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
+
+typedef struct TlsDtorNode {
+ int count;
+ struct TlsDtorNode *next;
+ _PVFV funcs[FUNCS_PER_NODE];
+} TlsDtorNode;
+
+ULONG _tls_index = 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(".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(".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
+};
+#endif
+
+#ifndef __CRT_THREAD
+#ifdef HAVE_ATTRIBUTE_THREAD
+#define __CRT_THREAD __declspec(thread)
+#else
+#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;
+
+#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;
+ dtor_list_head.count = 0;
+ }
+ else if (dtor_list->count == FUNCS_PER_NODE)
+ {
+ TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
+ if (pnode == NULL)
+ return -1;
+ pnode->count = 0;
+ pnode->next = dtor_list;
+ dtor_list = pnode;
+
+ 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;
+ /* 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 (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;
+}
+
+_CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor;
+
+
+int mingw_initltsdrot_force = 0;
+int mingw_initltsdyn_force=0;
+int mingw_initltssuo_force = 0;