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