OSDN Git Service

Remove filters for CRTDLL and __MSVCRT__.
[mingw/mingw-org-wsl.git] / src / libcrt / crt / tlssup.c
1 /**
2  * @file tlssup.c
3  * @copy 2012 MinGW.org project
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  * 
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  * 
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 #include <windows.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <malloc.h>
28
29 #ifndef _CRTALLOC
30 #define _CRTALLOC(x) __attribute__ ((section (x) ))
31 #endif
32
33 #ifndef __INTERNAL_FUNC_DEFINED
34 #define __INTERNAL_FUNC_DEFINED
35   typedef void (__cdecl *_PVFV)(void);
36   typedef int (__cdecl *_PIFV)(void);
37   typedef void (__cdecl *_PVFI)(int);
38 #endif
39
40 extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
41
42 #define FUNCS_PER_NODE 30
43
44 typedef struct TlsDtorNode {
45   int count;
46   struct TlsDtorNode *next;
47   _PVFV funcs[FUNCS_PER_NODE];
48 } TlsDtorNode;
49
50 ULONG _tls_index = 0;
51
52 /* TLS raw template data start and end. */
53 _CRTALLOC(".tls$AAA") char _tls_start = 0;
54 _CRTALLOC(".tls$ZZZ") char _tls_end = 0;
55
56 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
57 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
58
59 #ifdef _WIN64
60 _CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY64 _tls_used = {
61   (ULONGLONG) &_tls_start+1, (ULONGLONG) &_tls_end, (ULONGLONG) &_tls_index,
62   (ULONGLONG) (&__xl_a+1), (ULONG) 0, (ULONG) 0
63 };
64 #else
65 _CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY _tls_used = {
66   (ULONG)(ULONG_PTR) &_tls_start+1, (ULONG)(ULONG_PTR) &_tls_end,
67   (ULONG)(ULONG_PTR) &_tls_index, (ULONG)(ULONG_PTR) (&__xl_a+1),
68   (ULONG) 0, (ULONG) 0
69 };
70 #endif
71
72 #ifndef __CRT_THREAD
73 #ifdef HAVE_ATTRIBUTE_THREAD
74 #define __CRT_THREAD  __declspec(thread)
75 #else
76 #define __CRT_THREAD  __thread
77 #endif
78 #endif
79
80 #define DISABLE_MS_TLS 1
81
82 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
83 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
84
85 #if !defined (DISABLE_MS_TLS)
86 static __CRT_THREAD TlsDtorNode *dtor_list;
87 static __CRT_THREAD TlsDtorNode dtor_list_head;
88 #endif
89
90 extern int _CRT_MT;
91
92 BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
93
94 BOOL WINAPI
95 __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
96 {
97   _PVFV *pfunc;
98   int nfuncs, ifunc;
99
100   /* We don't let us trick here.  */
101   if (_CRT_MT != 2)
102    _CRT_MT = 2;
103
104   if (dwReason != DLL_THREAD_ATTACH)
105     {
106       if (dwReason == DLL_PROCESS_ATTACH)
107         __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
108       return TRUE;
109     }
110
111   /* Use the nfuncs variable to iterate the TLS functions instead of pfunc to
112      avoid nasty compiler optimizations when comparing two global pointers. */
113   nfuncs = &__xd_z - (&__xd_a + 1);
114   for (ifunc=0; ifunc < nfuncs; ++ifunc)
115     {
116       pfunc = (&__xd_a + 1) + ifunc;
117       if (*pfunc != NULL)
118         (*pfunc)();
119     }
120   return TRUE;
121 }
122
123 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init;
124 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init;
125
126 int __cdecl __tlregdtor (_PVFV);
127
128 int __cdecl
129 __tlregdtor (_PVFV func)
130 {
131   if (!func)
132     return 0;
133 #if !defined (DISABLE_MS_TLS)
134   if (dtor_list == NULL)
135     {
136       dtor_list = &dtor_list_head;
137       dtor_list_head.count = 0;
138     }
139     else if (dtor_list->count == FUNCS_PER_NODE)
140     {
141       TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
142       if (pnode == NULL)
143         return -1;
144       pnode->count = 0;
145       pnode->next = dtor_list;
146       dtor_list = pnode;
147
148       dtor_list->count = 0;
149     }
150   dtor_list->funcs[dtor_list->count++] = func;
151 #endif
152   return 0;
153 }
154
155 static BOOL WINAPI
156 __dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
157 {
158 #if !defined (DISABLE_MS_TLS)
159   TlsDtorNode *pnode, *pnext;
160   int i;
161 #endif
162
163   if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
164     return TRUE;
165   /* As TLS variables are detroyed already by DLL_THREAD_DETACH
166      call, we have to avoid access on the possible DLL_PROCESS_DETACH
167      call the already destroyed TLS vars.
168      TODO: The used local thread based variables have to be handled
169      manually, so that we can control their lifetime here.  */
170 #if !defined (DISABLE_MS_TLS)
171   if (dwReason != DLL_PROCESS_DETACH)
172     {
173       for (pnode = dtor_list; pnode != NULL; pnode = pnext)
174         {
175           for (i = pnode->count - 1; i >= 0; --i)
176             {
177               if (pnode->funcs[i] != NULL)
178                 (*pnode->funcs[i])();
179             }
180           pnext = pnode->next;
181           if (pnext != NULL)
182             free ((void *) pnode);
183         }
184     }
185 #endif
186   __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
187   return TRUE;
188 }
189
190 _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor;
191
192
193 int mingw_initltsdrot_force = 0;
194 int mingw_initltsdyn_force=0;
195 int mingw_initltssuo_force = 0;