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