Merge trunk r45185
[reactos.git] / reactos / lib / 3rdparty / mingw / tlssup.c
1 /**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the w64 mingw-runtime package.
4 * No warranty is given; refer to the file DISCLAIMER within this package.
5 */
6
7 #ifdef CRTDLL
8 #undef CRTDLL
9 #endif
10
11 #include <internal.h>
12 #include <sect_attribs.h>
13 #include <windows.h>
14 #include <malloc.h>
15 #include <crtdbg.h>
16
17 extern BOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
18
19 #define FUNCS_PER_NODE 30
20
21 typedef struct TlsDtorNode {
22 int count;
23 struct TlsDtorNode *next;
24 _PVFV funcs[FUNCS_PER_NODE];
25 } TlsDtorNode;
26
27 ULONG _tls_index = 0;
28
29 /* TLS raw template data start and end. */
30 _CRTALLOC(".tls$AAA") char _tls_start = 0;
31 _CRTALLOC(".tls$ZZZ") char _tls_end = 0;
32
33 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
34 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
35
36 #ifdef _WIN64
37 _CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY64 _tls_used = {
38 (ULONGLONG) &_tls_start+1, (ULONGLONG) &_tls_end, (ULONGLONG) &_tls_index,
39 (ULONGLONG) (&__xl_a+1), (ULONG) 0, (ULONG) 0
40 };
41 #else
42 _CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY _tls_used = {
43 (ULONG)(ULONG_PTR) &_tls_start+1, (ULONG)(ULONG_PTR) &_tls_end,
44 (ULONG)(ULONG_PTR) &_tls_index, (ULONG)(ULONG_PTR) (&__xl_a+1),
45 (ULONG) 0, (ULONG) 0
46 };
47 #endif
48
49 #ifndef __CRT_THREAD
50 #ifdef HAVE_ATTRIBUTE_THREAD
51 #define __CRT_THREAD __declspec(thread)
52 #else
53 #define __CRT_THREAD __thread
54 #endif
55 #endif
56
57 #define DISABLE_MS_TLS 1
58
59 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
60 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
61
62 #if !defined (DISABLE_MS_TLS)
63 static __CRT_THREAD TlsDtorNode *dtor_list;
64 static __CRT_THREAD TlsDtorNode dtor_list_head;
65 #endif
66
67 extern int _CRT_MT;
68
69 BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
70
71 BOOL WINAPI
72 __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
73 {
74 _PVFV *pfunc;
75
76 /* We don't let us trick here. */
77 if (_CRT_MT != 2)
78 _CRT_MT = 2;
79
80 if (dwReason != DLL_THREAD_ATTACH)
81 {
82 if (dwReason == DLL_PROCESS_ATTACH)
83 __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
84 return TRUE;
85 }
86
87 for (pfunc = &__xd_a + 1; pfunc != &__xd_z; ++pfunc)
88 {
89 if (*pfunc != NULL)
90 (*pfunc)();
91 }
92 return TRUE;
93 }
94
95 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init;
96 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init;
97
98 int __cdecl __tlregdtor (_PVFV);
99
100 int __cdecl
101 __tlregdtor (_PVFV func)
102 {
103 if (!func)
104 return 0;
105 #if !defined (DISABLE_MS_TLS)
106 if (dtor_list == NULL)
107 {
108 dtor_list = &dtor_list_head;
109 dtor_list_head.count = 0;
110 }
111 else if (dtor_list->count == FUNCS_PER_NODE)
112 {
113 TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
114 if (pnode == NULL)
115 return -1;
116 pnode->count = 0;
117 pnode->next = dtor_list;
118 dtor_list = pnode;
119
120 dtor_list->count = 0;
121 }
122 dtor_list->funcs[dtor_list->count++] = func;
123 #endif
124 return 0;
125 }
126
127 static BOOL WINAPI
128 __dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
129 {
130 #if !defined (DISABLE_MS_TLS)
131 TlsDtorNode *pnode, *pnext;
132 int i;
133 #endif
134
135 if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
136 return TRUE;
137 /* As TLS variables are detroyed already by DLL_THREAD_DETACH
138 call, we have to avoid access on the possible DLL_PROCESS_DETACH
139 call the already destroyed TLS vars.
140 TODO: The used local thread based variables have to be handled
141 manually, so that we can control their lifetime here. */
142 #if !defined (DISABLE_MS_TLS)
143 if (dwReason != DLL_PROCESS_DETACH)
144 {
145 for (pnode = dtor_list; pnode != NULL; pnode = pnext)
146 {
147 for (i = pnode->count - 1; i >= 0; --i)
148 {
149 if (pnode->funcs[i] != NULL)
150 (*pnode->funcs[i])();
151 }
152 pnext = pnode->next;
153 if (pnext != NULL)
154 free ((void *) pnode);
155 }
156 }
157 #endif
158 __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
159 return TRUE;
160 }
161
162 _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor;
163
164
165 int mingw_initltsdrot_force = 0;
166 int mingw_initltsdyn_force=0;
167 int mingw_initltssuo_force = 0;