• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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