xref: /reactos/sdk/lib/crt/startup/tlssup.c (revision 439aefb3)
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