[MINGW-W64]
[reactos.git] / reactos / lib / 3rdparty / mingw / tlssup.c
1 /**
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.
5 *
6 * Written by Kai Tietz <kai.tietz@onevision.com>
7 */
8
9 #ifdef CRTDLL
10 #undef CRTDLL
11 #endif
12
13 #include <sect_attribs.h>
14
15 #ifndef WIN32_LEAN_AND_MEAN
16 #define WIN32_LEAN_AND_MEAN
17 #endif
18 #include <windows.h>
19
20 #include <stdio.h>
21 #include <memory.h>
22 #include <malloc.h>
23 #ifndef _WIN64
24 #include <stdlib.h> /* for _winmajor */
25 #endif
26
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);
32 #endif
33
34 extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
35
36 #define FUNCS_PER_NODE 30
37
38 typedef struct TlsDtorNode {
39 int count;
40 struct TlsDtorNode *next;
41 _PVFV funcs[FUNCS_PER_NODE];
42 } TlsDtorNode;
43
44 ULONG _tls_index = 0;
45
46 /* TLS raw template data start and end. */
47 _CRTALLOC(".tls$AAA") char _tls_start = 0;
48 _CRTALLOC(".tls$ZZZ") char _tls_end = 0;
49
50 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
51 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
52
53 #ifdef _WIN64
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
57 };
58 #else
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),
62 (ULONG) 0, (ULONG) 0
63 };
64 #endif
65
66 #ifndef __CRT_THREAD
67 #ifdef HAVE_ATTRIBUTE_THREAD
68 #define __CRT_THREAD __declspec(thread)
69 #else
70 #define __CRT_THREAD __thread
71 #endif
72 #endif
73
74 #define DISABLE_MS_TLS 1
75
76 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
77 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
78
79 #if !defined (DISABLE_MS_TLS)
80 static __CRT_THREAD TlsDtorNode *dtor_list;
81 static __CRT_THREAD TlsDtorNode dtor_list_head;
82 #endif
83
84 extern int _CRT_MT;
85
86 #ifndef _WIN64
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;
94 #endif
95
96 BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
97
98 BOOL WINAPI
99 __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
100 {
101 _PVFV *pfunc;
102
103 #ifndef _WIN64
104 if (_winmajor < 4)
105 {
106 __mingw_usemthread_dll = 1;
107 __mingw_mthread_hdll = LoadLibrary (MINGWM10_DLL);
108 if (__mingw_mthread_hdll != NULL)
109 {
110 __mingw_gMTRemoveKeyDtor = (fMTRemoveKeyDtor) GetProcAddress (__mingw_mthread_hdll, "__mingwthr_remove_key_dtor");
111 __mingw_gMTKeyDtor = (fMTKeyDtor) GetProcAddress (__mingw_mthread_hdll, "__mingwthr_key_dtor");
112 }
113 if (__mingw_mthread_hdll == NULL || !__mingw_gMTRemoveKeyDtor || !__mingw_gMTKeyDtor)
114 {
115 __mingw_gMTKeyDtor = NULL;
116 __mingw_gMTRemoveKeyDtor = NULL;
117 if (__mingw_mthread_hdll)
118 FreeLibrary (__mingw_mthread_hdll);
119 __mingw_mthread_hdll = NULL;
120 _CRT_MT = 0;
121 return TRUE;
122 }
123 _CRT_MT = 1;
124 return TRUE;
125 }
126 #endif
127 /* We don't let us trick here. */
128 if (_CRT_MT != 2)
129 _CRT_MT = 2;
130
131 if (dwReason != DLL_THREAD_ATTACH)
132 {
133 if (dwReason == DLL_PROCESS_ATTACH)
134 __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
135 return TRUE;
136 }
137
138 for (pfunc = &__xd_a + 1; pfunc != &__xd_z; ++pfunc)
139 {
140 if (*pfunc != NULL)
141 (*pfunc)();
142 }
143 return TRUE;
144 }
145
146 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init;
147 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init;
148
149 int __cdecl __tlregdtor (_PVFV);
150
151 int __cdecl
152 __tlregdtor (_PVFV func)
153 {
154 if (!func)
155 return 0;
156 #if !defined (DISABLE_MS_TLS)
157 if (dtor_list == NULL)
158 {
159 dtor_list = &dtor_list_head;
160 dtor_list_head.count = 0;
161 }
162 else if (dtor_list->count == FUNCS_PER_NODE)
163 {
164 TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
165 if (pnode == NULL)
166 return -1;
167 pnode->count = 0;
168 pnode->next = dtor_list;
169 dtor_list = pnode;
170
171 dtor_list->count = 0;
172 }
173 dtor_list->funcs[dtor_list->count++] = func;
174 #endif
175 return 0;
176 }
177
178 static BOOL WINAPI
179 __dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
180 {
181 #if !defined (DISABLE_MS_TLS)
182 TlsDtorNode *pnode, *pnext;
183 int i;
184 #endif
185
186 if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
187 return TRUE;
188 /* As TLS variables are detroyed already by DLL_THREAD_DETACH
189 call, we have to avoid access on the possible DLL_PROCESS_DETACH
190 call the already destroyed TLS vars.
191 TODO: The used local thread based variables have to be handled
192 manually, so that we can control their lifetime here. */
193 #if !defined (DISABLE_MS_TLS)
194 if (dwReason != DLL_PROCESS_DETACH)
195 {
196 for (pnode = dtor_list; pnode != NULL; pnode = pnext)
197 {
198 for (i = pnode->count - 1; i >= 0; --i)
199 {
200 if (pnode->funcs[i] != NULL)
201 (*pnode->funcs[i])();
202 }
203 pnext = pnode->next;
204 if (pnext != NULL)
205 free ((void *) pnode);
206 }
207 }
208 #endif
209 __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
210 return TRUE;
211 }
212
213 _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor;
214
215
216 int mingw_initltsdrot_force = 0;
217 int mingw_initltsdyn_force = 0;
218 int mingw_initltssuo_force = 0;