2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the w64 mingw-runtime package.
4 * No warranty is given; refer to the file DISCLAIMER within this package.
6 * Written by Kai Tietz <kai.tietz@onevision.com>
19 #define _CRTALLOC(x) __attribute__ ((section (x) ))
22 #ifndef __INTERNAL_FUNC_DEFINED
23 #define __INTERNAL_FUNC_DEFINED
24 typedef void (__cdecl *_PVFV)(void);
25 typedef int (__cdecl *_PIFV)(void);
26 typedef void (__cdecl *_PVFI)(int);
29 extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
31 #define FUNCS_PER_NODE 30
33 typedef struct TlsDtorNode {
35 struct TlsDtorNode *next;
36 _PVFV funcs[FUNCS_PER_NODE];
41 /* TLS raw template data start and end. */
42 _CRTALLOC(".tls$AAA") char _tls_start = 0;
43 _CRTALLOC(".tls$ZZZ") char _tls_end = 0;
45 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
46 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
49 _CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY64 _tls_used = {
50 (ULONGLONG) &_tls_start+1, (ULONGLONG) &_tls_end, (ULONGLONG) &_tls_index,
51 (ULONGLONG) (&__xl_a+1), (ULONG) 0, (ULONG) 0
54 _CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY _tls_used = {
55 (ULONG)(ULONG_PTR) &_tls_start+1, (ULONG)(ULONG_PTR) &_tls_end,
56 (ULONG)(ULONG_PTR) &_tls_index, (ULONG)(ULONG_PTR) (&__xl_a+1),
62 #ifdef HAVE_ATTRIBUTE_THREAD
63 #define __CRT_THREAD __declspec(thread)
65 #define __CRT_THREAD __thread
69 #define DISABLE_MS_TLS 1
71 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
72 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
74 #if !defined (DISABLE_MS_TLS)
75 static __CRT_THREAD TlsDtorNode *dtor_list;
76 static __CRT_THREAD TlsDtorNode dtor_list_head;
81 BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
84 __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
89 /* We don't let us trick here. */
93 if (dwReason != DLL_THREAD_ATTACH)
95 if (dwReason == DLL_PROCESS_ATTACH)
96 __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
100 /* Use the nfuncs variable to iterate the TLS functions instead of pfunc to
101 avoid nasty compiler optimizations when comparing two global pointers. */
102 nfuncs = &__xd_z - (&__xd_a + 1);
103 for (ifunc=0; ifunc < nfuncs; ++ifunc)
105 pfunc = (&__xd_a + 1) + ifunc;
112 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init;
113 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init;
115 int __cdecl __tlregdtor (_PVFV);
118 __tlregdtor (_PVFV func)
122 #if !defined (DISABLE_MS_TLS)
123 if (dtor_list == NULL)
125 dtor_list = &dtor_list_head;
126 dtor_list_head.count = 0;
128 else if (dtor_list->count == FUNCS_PER_NODE)
130 TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
134 pnode->next = dtor_list;
137 dtor_list->count = 0;
139 dtor_list->funcs[dtor_list->count++] = func;
145 __dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
147 #if !defined (DISABLE_MS_TLS)
148 TlsDtorNode *pnode, *pnext;
152 if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
154 /* As TLS variables are detroyed already by DLL_THREAD_DETACH
155 call, we have to avoid access on the possible DLL_PROCESS_DETACH
156 call the already destroyed TLS vars.
157 TODO: The used local thread based variables have to be handled
158 manually, so that we can control their lifetime here. */
159 #if !defined (DISABLE_MS_TLS)
160 if (dwReason != DLL_PROCESS_DETACH)
162 for (pnode = dtor_list; pnode != NULL; pnode = pnext)
164 for (i = pnode->count - 1; i >= 0; --i)
166 if (pnode->funcs[i] != NULL)
167 (*pnode->funcs[i])();
171 free ((void *) pnode);
175 __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
179 _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor;
182 int mingw_initltsdrot_force = 0;
183 int mingw_initltsdyn_force=0;
184 int mingw_initltssuo_force = 0;