3 * @copy 2012 MinGW.org project
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
30 #define _CRTALLOC(x) __attribute__ ((section (x) ))
33 #ifndef __INTERNAL_FUNC_DEFINED
34 #define __INTERNAL_FUNC_DEFINED
35 typedef void (__cdecl *_PVFV)(void);
36 typedef int (__cdecl *_PIFV)(void);
37 typedef void (__cdecl *_PVFI)(int);
40 extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
42 #define FUNCS_PER_NODE 30
44 typedef struct TlsDtorNode {
46 struct TlsDtorNode *next;
47 _PVFV funcs[FUNCS_PER_NODE];
52 /* TLS raw template data start and end. */
53 _CRTALLOC(".tls$AAA") char _tls_start = 0;
54 _CRTALLOC(".tls$ZZZ") char _tls_end = 0;
56 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
57 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
60 _CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY64 _tls_used = {
61 (ULONGLONG) &_tls_start+1, (ULONGLONG) &_tls_end, (ULONGLONG) &_tls_index,
62 (ULONGLONG) (&__xl_a+1), (ULONG) 0, (ULONG) 0
65 _CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY _tls_used = {
66 (ULONG)(ULONG_PTR) &_tls_start+1, (ULONG)(ULONG_PTR) &_tls_end,
67 (ULONG)(ULONG_PTR) &_tls_index, (ULONG)(ULONG_PTR) (&__xl_a+1),
73 #ifdef HAVE_ATTRIBUTE_THREAD
74 #define __CRT_THREAD __declspec(thread)
76 #define __CRT_THREAD __thread
80 #define DISABLE_MS_TLS 1
82 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
83 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
85 #if !defined (DISABLE_MS_TLS)
86 static __CRT_THREAD TlsDtorNode *dtor_list;
87 static __CRT_THREAD TlsDtorNode dtor_list_head;
92 BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
95 __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
100 /* We don't let us trick here. */
104 if (dwReason != DLL_THREAD_ATTACH)
106 if (dwReason == DLL_PROCESS_ATTACH)
107 __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
111 /* Use the nfuncs variable to iterate the TLS functions instead of pfunc to
112 avoid nasty compiler optimizations when comparing two global pointers. */
113 nfuncs = &__xd_z - (&__xd_a + 1);
114 for (ifunc=0; ifunc < nfuncs; ++ifunc)
116 pfunc = (&__xd_a + 1) + ifunc;
123 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init;
124 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init;
126 int __cdecl __tlregdtor (_PVFV);
129 __tlregdtor (_PVFV func)
133 #if !defined (DISABLE_MS_TLS)
134 if (dtor_list == NULL)
136 dtor_list = &dtor_list_head;
137 dtor_list_head.count = 0;
139 else if (dtor_list->count == FUNCS_PER_NODE)
141 TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
145 pnode->next = dtor_list;
148 dtor_list->count = 0;
150 dtor_list->funcs[dtor_list->count++] = func;
156 __dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
158 #if !defined (DISABLE_MS_TLS)
159 TlsDtorNode *pnode, *pnext;
163 if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
165 /* As TLS variables are detroyed already by DLL_THREAD_DETACH
166 call, we have to avoid access on the possible DLL_PROCESS_DETACH
167 call the already destroyed TLS vars.
168 TODO: The used local thread based variables have to be handled
169 manually, so that we can control their lifetime here. */
170 #if !defined (DISABLE_MS_TLS)
171 if (dwReason != DLL_PROCESS_DETACH)
173 for (pnode = dtor_list; pnode != NULL; pnode = pnext)
175 for (i = pnode->count - 1; i >= 0; --i)
177 if (pnode->funcs[i] != NULL)
178 (*pnode->funcs[i])();
182 free ((void *) pnode);
186 __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
190 _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor;
193 int mingw_initltsdrot_force = 0;
194 int mingw_initltsdyn_force=0;
195 int mingw_initltssuo_force = 0;