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