1 /**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 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 __REACTOS__
24 #include <corecrt_startup.h>
25 #else
26 #include <internal.h>
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 We use here pointer-types for start/end so that tls-data remains
43 aligned on pointer-size-width. This seems to be required for
44 pe-loader. */
45 _CRTALLOC(".tls") char *_tls_start = NULL;
46 _CRTALLOC(".tls$ZZZ") char *_tls_end = NULL;
47
48 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
49 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
50
51 const IMAGE_TLS_DIRECTORY _tls_used = {
52 (ULONG_PTR) &_tls_start, (ULONG_PTR) &_tls_end,
53 (ULONG_PTR) &_tls_index, (ULONG_PTR) (&__xl_a+1),
54 (ULONG) 0, (ULONG) 0
55 };
56
57 #ifndef __CRT_THREAD
58 #ifdef HAVE_ATTRIBUTE_THREAD
59 #define __CRT_THREAD __declspec(thread)
60 #else
61 #define __CRT_THREAD __thread
62 #endif
63 #endif
64
65 #define DISABLE_MS_TLS 1
66
67 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
68 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
69
70 #if !defined (DISABLE_MS_TLS)
71 static __CRT_THREAD TlsDtorNode *dtor_list;
72 static __CRT_THREAD TlsDtorNode dtor_list_head;
73 #endif
74
75 extern int _CRT_MT;
76
77 BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
78
79 BOOL WINAPI
__dyn_tls_init(HANDLE hDllHandle,DWORD dwReason,LPVOID lpreserved)80 __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
81 {
82 _PVFV *pfunc;
83 uintptr_t ps;
84
85 /* We don't let us trick here. */
86 if (_CRT_MT != 2)
87 _CRT_MT = 2;
88
89 if (dwReason != DLL_THREAD_ATTACH)
90 {
91 if (dwReason == DLL_PROCESS_ATTACH)
92 __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
93 return TRUE;
94 }
95
96 ps = (uintptr_t) &__xd_a;
97 ps += sizeof (uintptr_t);
98 for ( ; ps != (uintptr_t) &__xd_z; ps += sizeof (uintptr_t))
99 {
100 pfunc = (_PVFV *) ps;
101 if (*pfunc != NULL)
102 (*pfunc)();
103 }
104 return TRUE;
105 }
106
107 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init;
108 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init;
109
110 int __cdecl __tlregdtor (_PVFV);
111
112 int __cdecl
__tlregdtor(_PVFV func)113 __tlregdtor (_PVFV func)
114 {
115 if (!func)
116 return 0;
117 #if !defined (DISABLE_MS_TLS)
118 if (dtor_list == NULL)
119 {
120 dtor_list = &dtor_list_head;
121 dtor_list_head.count = 0;
122 }
123 else if (dtor_list->count == FUNCS_PER_NODE)
124 {
125 TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
126 if (pnode == NULL)
127 return -1;
128 pnode->count = 0;
129 pnode->next = dtor_list;
130 dtor_list = pnode;
131
132 dtor_list->count = 0;
133 }
134 dtor_list->funcs[dtor_list->count++] = func;
135 #endif
136 return 0;
137 }
138
139 static BOOL WINAPI
__dyn_tls_dtor(HANDLE hDllHandle,DWORD dwReason,LPVOID lpreserved)140 __dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
141 {
142 #if !defined (DISABLE_MS_TLS)
143 TlsDtorNode *pnode, *pnext;
144 int i;
145 #endif
146
147 if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
148 return TRUE;
149 /* As TLS variables are detroyed already by DLL_THREAD_DETACH
150 call, we have to avoid access on the possible DLL_PROCESS_DETACH
151 call the already destroyed TLS vars.
152 TODO: The used local thread based variables have to be handled
153 manually, so that we can control their lifetime here. */
154 #if !defined (DISABLE_MS_TLS)
155 if (dwReason != DLL_PROCESS_DETACH)
156 {
157 for (pnode = dtor_list; pnode != NULL; pnode = pnext)
158 {
159 for (i = pnode->count - 1; i >= 0; --i)
160 {
161 if (pnode->funcs[i] != NULL)
162 (*pnode->funcs[i])();
163 }
164 pnext = pnode->next;
165 if (pnext != NULL)
166 free ((void *) pnode);
167 }
168 }
169 #endif
170 __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
171 return TRUE;
172 }
173
174 _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor;
175
176
177 int mingw_initltsdrot_force = 0;
178 int mingw_initltsdyn_force = 0;
179 int mingw_initltssuo_force = 0;
180