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.PD within this package.
6 * Written by Kai Tietz <kai.tietz@onevision.com>
13 #include <sect_attribs.h>
15 #ifndef WIN32_LEAN_AND_MEAN
16 #define WIN32_LEAN_AND_MEAN
24 #include <stdlib.h> /* for _winmajor */
27 #ifndef __INTERNAL_FUNC_DEFINED
28 #define __INTERNAL_FUNC_DEFINED
29 typedef void (__cdecl
*_PVFV
)(void);
30 typedef int (__cdecl
*_PIFV
)(void);
31 typedef void (__cdecl
*_PVFI
)(int);
34 extern WINBOOL
__mingw_TLScallback (HANDLE hDllHandle
, DWORD reason
, LPVOID reserved
);
36 #define FUNCS_PER_NODE 30
38 typedef struct TlsDtorNode
{
40 struct TlsDtorNode
*next
;
41 _PVFV funcs
[FUNCS_PER_NODE
];
46 /* TLS raw template data start and end. */
47 _CRTALLOC(".tls$AAA") char _tls_start
= 0;
48 _CRTALLOC(".tls$ZZZ") char _tls_end
= 0;
50 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a
= 0;
51 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z
= 0;
54 _CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY64 _tls_used
= {
55 (ULONGLONG
) &_tls_start
+1, (ULONGLONG
) &_tls_end
, (ULONGLONG
) &_tls_index
,
56 (ULONGLONG
) (&__xl_a
+1), (ULONG
) 0, (ULONG
) 0
59 _CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY _tls_used
= {
60 (ULONG
)(ULONG_PTR
) &_tls_start
+1, (ULONG
)(ULONG_PTR
) &_tls_end
,
61 (ULONG
)(ULONG_PTR
) &_tls_index
, (ULONG
)(ULONG_PTR
) (&__xl_a
+1),
67 #ifdef HAVE_ATTRIBUTE_THREAD
68 #define __CRT_THREAD __declspec(thread)
70 #define __CRT_THREAD __thread
74 #define DISABLE_MS_TLS 1
76 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a
= 0;
77 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z
= 0;
79 #if !defined (DISABLE_MS_TLS)
80 static __CRT_THREAD TlsDtorNode
*dtor_list
;
81 static __CRT_THREAD TlsDtorNode dtor_list_head
;
87 #define MINGWM10_DLL "mingwm10.dll"
88 typedef int (*fMTRemoveKeyDtor
)(DWORD key
);
89 typedef int (*fMTKeyDtor
)(DWORD key
, void (*dtor
)(void *));
90 fMTRemoveKeyDtor __mingw_gMTRemoveKeyDtor
;
91 fMTKeyDtor __mingw_gMTKeyDtor
;
92 int __mingw_usemthread_dll
;
93 static HANDLE __mingw_mthread_hdll
;
96 BOOL WINAPI
__dyn_tls_init (HANDLE
, DWORD
, LPVOID
);
99 __dyn_tls_init (HANDLE hDllHandle
, DWORD dwReason
, LPVOID lpreserved
)
107 __mingw_usemthread_dll
= 1;
108 __mingw_mthread_hdll
= LoadLibrary (MINGWM10_DLL
);
109 if (__mingw_mthread_hdll
!= NULL
)
111 __mingw_gMTRemoveKeyDtor
= (fMTRemoveKeyDtor
) GetProcAddress (__mingw_mthread_hdll
, "__mingwthr_remove_key_dtor");
112 __mingw_gMTKeyDtor
= (fMTKeyDtor
) GetProcAddress (__mingw_mthread_hdll
, "__mingwthr_key_dtor");
114 if (__mingw_mthread_hdll
== NULL
|| !__mingw_gMTRemoveKeyDtor
|| !__mingw_gMTKeyDtor
)
116 __mingw_gMTKeyDtor
= NULL
;
117 __mingw_gMTRemoveKeyDtor
= NULL
;
118 if (__mingw_mthread_hdll
)
119 FreeLibrary (__mingw_mthread_hdll
);
120 __mingw_mthread_hdll
= NULL
;
128 /* We don't let us trick here. */
132 if (dwReason
!= DLL_THREAD_ATTACH
)
134 if (dwReason
== DLL_PROCESS_ATTACH
)
135 __mingw_TLScallback (hDllHandle
, dwReason
, lpreserved
);
139 ps
= (uintptr_t) &__xd_a
;
140 ps
+= sizeof (uintptr_t);
141 for ( ; ps
!= (uintptr_t) &__xd_z
; ps
+= sizeof (uintptr_t))
143 pfunc
= (_PVFV
*) ps
;
150 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback
= (const PIMAGE_TLS_CALLBACK
) __dyn_tls_init
;
151 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c
= (PIMAGE_TLS_CALLBACK
) __dyn_tls_init
;
153 int __cdecl
__tlregdtor (_PVFV
);
156 __tlregdtor (_PVFV func
)
160 #if !defined (DISABLE_MS_TLS)
161 if (dtor_list
== NULL
)
163 dtor_list
= &dtor_list_head
;
164 dtor_list_head
.count
= 0;
166 else if (dtor_list
->count
== FUNCS_PER_NODE
)
168 TlsDtorNode
*pnode
= (TlsDtorNode
*) malloc (sizeof (TlsDtorNode
));
172 pnode
->next
= dtor_list
;
175 dtor_list
->count
= 0;
177 dtor_list
->funcs
[dtor_list
->count
++] = func
;
183 __dyn_tls_dtor (HANDLE hDllHandle
, DWORD dwReason
, LPVOID lpreserved
)
185 #if !defined (DISABLE_MS_TLS)
186 TlsDtorNode
*pnode
, *pnext
;
190 if (dwReason
!= DLL_THREAD_DETACH
&& dwReason
!= DLL_PROCESS_DETACH
)
192 /* As TLS variables are detroyed already by DLL_THREAD_DETACH
193 call, we have to avoid access on the possible DLL_PROCESS_DETACH
194 call the already destroyed TLS vars.
195 TODO: The used local thread based variables have to be handled
196 manually, so that we can control their lifetime here. */
197 #if !defined (DISABLE_MS_TLS)
198 if (dwReason
!= DLL_PROCESS_DETACH
)
200 for (pnode
= dtor_list
; pnode
!= NULL
; pnode
= pnext
)
202 for (i
= pnode
->count
- 1; i
>= 0; --i
)
204 if (pnode
->funcs
[i
] != NULL
)
205 (*pnode
->funcs
[i
])();
209 free ((void *) pnode
);
213 __mingw_TLScallback (hDllHandle
, dwReason
, lpreserved
);
217 _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d
= (PIMAGE_TLS_CALLBACK
) __dyn_tls_dtor
;
220 int mingw_initltsdrot_force
= 0;
221 int mingw_initltsdyn_force
= 0;
222 int mingw_initltssuo_force
= 0;