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