]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // $Id$ |
2 | // (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004. | |
3 | // (C) Copyright 2007 Roland Schwarz | |
4 | // (C) Copyright 2007 Anthony Williams | |
5 | // (C) Copyright 2007 David Deakins | |
6 | // Use, modification and distribution are subject to the | |
7 | // Boost Software License, Version 1.0. (See accompanying file | |
8 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | ||
10 | #include <boost/detail/winapi/config.hpp> | |
11 | #include <boost/thread/detail/config.hpp> | |
12 | ||
b32b8144 | 13 | #if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) |
7c673cae FG |
14 | |
15 | #if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) | |
16 | ||
17 | #include <boost/thread/detail/tss_hooks.hpp> | |
18 | ||
19 | #include <windows.h> | |
20 | ||
21 | #include <cstdlib> | |
22 | ||
23 | namespace boost | |
24 | { | |
25 | void tss_cleanup_implemented() {} | |
26 | } | |
27 | ||
28 | namespace { | |
29 | void NTAPI on_tls_callback(void* , DWORD dwReason, PVOID ) | |
30 | { | |
31 | switch (dwReason) | |
32 | { | |
33 | case DLL_THREAD_DETACH: | |
34 | { | |
35 | boost::on_thread_exit(); | |
36 | break; | |
37 | } | |
38 | } | |
39 | } | |
40 | } | |
41 | ||
b32b8144 | 42 | #if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32__) || (__MINGW32_MAJOR_VERSION >3) || \ |
7c673cae FG |
43 | ((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18)) |
44 | extern "C" | |
45 | { | |
46 | PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback; | |
47 | } | |
48 | #else | |
49 | extern "C" { | |
50 | ||
51 | void (* after_ctors )() __attribute__((section(".ctors"))) = boost::on_process_enter; | |
52 | void (* before_dtors)() __attribute__((section(".dtors"))) = boost::on_thread_exit; | |
53 | void (* after_dtors )() __attribute__((section(".dtors.zzz"))) = boost::on_process_exit; | |
54 | ||
55 | ULONG __tls_index__ = 0; | |
56 | char __tls_end__ __attribute__((section(".tls$zzz"))) = 0; | |
57 | char __tls_start__ __attribute__((section(".tls"))) = 0; | |
58 | ||
59 | ||
60 | PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0; | |
61 | PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0; | |
62 | } | |
63 | extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) = | |
64 | { | |
65 | (DWORD) &__tls_start__, | |
66 | (DWORD) &__tls_end__, | |
67 | (DWORD) &__tls_index__, | |
68 | (DWORD) (&__crt_xl_start__+1), | |
69 | (DWORD) 0, | |
70 | (DWORD) 0 | |
71 | }; | |
72 | #endif | |
73 | ||
74 | ||
75 | #elif defined(_MSC_VER) && !defined(UNDER_CE) | |
76 | ||
77 | #include <boost/thread/detail/tss_hooks.hpp> | |
78 | ||
79 | #include <stdlib.h> | |
80 | ||
81 | #include <windows.h> | |
82 | ||
83 | ||
84 | // _pRawDllMainOrig can be defined by including boost/thread/win32/mfc_thread_init.hpp | |
85 | // into your dll; it ensures that MFC-Dll-initialization will be done properly | |
86 | // The following code is adapted from the MFC-Dll-init code | |
87 | /* | |
88 | * _pRawDllMainOrig MUST be an extern const variable, which will be aliased to | |
89 | * _pDefaultRawDllMainOrig if no real user definition is present, thanks to the | |
90 | * alternatename directive. | |
91 | */ | |
92 | ||
93 | // work at least with _MSC_VER 1500 (MSVC++ 9.0, VS 2008) | |
94 | #if (_MSC_VER >= 1500) | |
95 | ||
96 | extern "C" { | |
b32b8144 FG |
97 | extern BOOL (WINAPI * const _pRawDllMainOrig)(HINSTANCE, DWORD, LPVOID); |
98 | extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HINSTANCE, DWORD, LPVOID) = NULL; | |
7c673cae FG |
99 | #if defined (_M_IX86) |
100 | #pragma comment(linker, "/alternatename:__pRawDllMainOrig=__pDefaultRawDllMainOrig") | |
101 | #elif defined (_M_X64) || defined (_M_ARM) | |
102 | #pragma comment(linker, "/alternatename:_pRawDllMainOrig=_pDefaultRawDllMainOrig") | |
103 | #else /* defined (_M_X64) || defined (_M_ARM) */ | |
104 | #error Unsupported platform | |
105 | #endif /* defined (_M_X64) || defined (_M_ARM) */ | |
106 | } | |
107 | ||
108 | #endif | |
109 | ||
110 | ||
111 | ||
112 | ||
113 | //Definitions required by implementation | |
b32b8144 FG |
114 | #if (_MSC_VER < 1300) || ((_MSC_VER > 1900) && (_MSC_VER < 1910)) // 1300 == VC++ 7.0, 1900 == VC++ 14.0, 1910 == VC++ 2017 |
115 | typedef void ( __cdecl *_PVFV_ )(); | |
116 | typedef void ( __cdecl *_PIFV_ )(); | |
117 | #define INIRETSUCCESS_V | |
118 | #define INIRETSUCCESS_I | |
119 | #define PVAPI_V void __cdecl | |
120 | #define PVAPI_I void __cdecl | |
121 | #elif (_MSC_VER >= 1910) | |
122 | typedef void ( __cdecl *_PVFV_ )(); | |
123 | typedef int ( __cdecl *_PIFV_ )(); | |
124 | #define INIRETSUCCESS_V | |
125 | #define INIRETSUCCESS_I 0 | |
126 | #define PVAPI_V void __cdecl | |
127 | #define PVAPI_I int __cdecl | |
7c673cae | 128 | #else |
b32b8144 FG |
129 | typedef int ( __cdecl *_PVFV_ )(); |
130 | typedef int ( __cdecl *_PIFV_ )(); | |
131 | #define INIRETSUCCESS_V 0 | |
132 | #define INIRETSUCCESS_I 0 | |
133 | #define PVAPI_V int __cdecl | |
134 | #define PVAPI_I int __cdecl | |
7c673cae FG |
135 | #endif |
136 | ||
137 | typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID); | |
138 | ||
139 | //Symbols for connection to the runtime environment | |
140 | ||
141 | extern "C" | |
142 | { | |
143 | extern DWORD _tls_used; //the tls directory (located in .rdata segment) | |
144 | extern _TLSCB __xl_a[], __xl_z[]; //tls initializers */ | |
145 | } | |
146 | ||
147 | namespace | |
148 | { | |
149 | //Forward declarations | |
150 | ||
b32b8144 FG |
151 | static PVAPI_I on_tls_prepare(); |
152 | static PVAPI_V on_process_init(); | |
153 | static PVAPI_V on_process_term(); | |
7c673cae FG |
154 | static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID); |
155 | ||
156 | //The .CRT$Xxx information is taken from Codeguru: | |
157 | //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/ | |
158 | ||
159 | #if (_MSC_VER >= 1400) | |
160 | #pragma section(".CRT$XIU",long,read) | |
161 | #pragma section(".CRT$XCU",long,read) | |
162 | #pragma section(".CRT$XTU",long,read) | |
163 | #pragma section(".CRT$XLC",long,read) | |
164 | __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback; | |
b32b8144 FG |
165 | __declspec(allocate(".CRT$XIU"))_PIFV_ p_tls_prepare = on_tls_prepare; |
166 | __declspec(allocate(".CRT$XCU"))_PVFV_ p_process_init = on_process_init; | |
167 | __declspec(allocate(".CRT$XTU"))_PVFV_ p_process_term = on_process_term; | |
7c673cae FG |
168 | #else |
169 | #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 | |
170 | # pragma data_seg(push, old_seg) | |
171 | #endif | |
172 | //Callback to run tls glue code first. | |
173 | //I don't think it is necessary to run it | |
174 | //at .CRT$XIB level, since we are only | |
175 | //interested in thread detachement. But | |
176 | //this could be changed easily if required. | |
177 | ||
178 | #pragma data_seg(".CRT$XIU") | |
b32b8144 | 179 | static _PIFV_ p_tls_prepare = on_tls_prepare; |
7c673cae FG |
180 | #pragma data_seg() |
181 | ||
182 | //Callback after all global ctors. | |
183 | ||
184 | #pragma data_seg(".CRT$XCU") | |
b32b8144 | 185 | static _PVFV_ p_process_init = on_process_init; |
7c673cae FG |
186 | #pragma data_seg() |
187 | ||
188 | //Callback for tls notifications. | |
189 | ||
190 | #pragma data_seg(".CRT$XLB") | |
191 | _TLSCB p_thread_callback = on_tls_callback; | |
192 | #pragma data_seg() | |
193 | //Callback for termination. | |
194 | ||
195 | #pragma data_seg(".CRT$XTU") | |
b32b8144 | 196 | static _PVFV_ p_process_term = on_process_term; |
7c673cae FG |
197 | #pragma data_seg() |
198 | #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 | |
199 | # pragma data_seg(pop, old_seg) | |
200 | #endif | |
201 | #endif | |
202 | ||
203 | #ifdef BOOST_MSVC | |
204 | #pragma warning(push) | |
205 | #pragma warning(disable:4189) | |
206 | #endif | |
207 | ||
b32b8144 | 208 | PVAPI_I on_tls_prepare() |
7c673cae FG |
209 | { |
210 | //The following line has an important side effect: | |
211 | //if the TLS directory is not already there, it will | |
212 | //be created by the linker. In other words, it forces a tls | |
213 | //directory to be generated by the linker even when static tls | |
214 | //(i.e. __declspec(thread)) is not used. | |
215 | //The volatile should prevent the optimizer | |
216 | //from removing the reference. | |
217 | ||
218 | DWORD volatile dw = _tls_used; | |
219 | ||
220 | #if (_MSC_VER < 1300) // 1300 == VC++ 7.0 | |
221 | _TLSCB* pfbegin = __xl_a; | |
222 | _TLSCB* pfend = __xl_z; | |
223 | _TLSCB* pfdst = pfbegin; | |
224 | //pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks; | |
225 | ||
226 | //The following loop will merge the address pointers | |
227 | //into a contiguous area, since the tlssup code seems | |
228 | //to require this (at least on MSVC 6) | |
229 | ||
230 | while (pfbegin < pfend) | |
231 | { | |
232 | if (*pfbegin != 0) | |
233 | { | |
234 | *pfdst = *pfbegin; | |
235 | ++pfdst; | |
236 | } | |
237 | ++pfbegin; | |
238 | } | |
239 | ||
240 | *pfdst = 0; | |
241 | #endif | |
242 | ||
b32b8144 | 243 | return INIRETSUCCESS_I; |
7c673cae FG |
244 | } |
245 | #ifdef BOOST_MSVC | |
246 | #pragma warning(pop) | |
247 | #endif | |
248 | ||
b32b8144 | 249 | PVAPI_V on_process_init() |
7c673cae FG |
250 | { |
251 | //Schedule on_thread_exit() to be called for the main | |
252 | //thread before destructors of global objects have been | |
253 | //called. | |
254 | ||
255 | //It will not be run when 'quick' exiting the | |
256 | //library; however, this is the standard behaviour | |
257 | //for destructors of global objects, so that | |
258 | //shouldn't be a problem. | |
259 | ||
260 | atexit(boost::on_thread_exit); | |
261 | ||
262 | //Call Boost process entry callback here | |
263 | ||
264 | boost::on_process_enter(); | |
265 | ||
b32b8144 | 266 | return INIRETSUCCESS_V; |
7c673cae FG |
267 | } |
268 | ||
b32b8144 | 269 | PVAPI_V on_process_term() |
7c673cae FG |
270 | { |
271 | boost::on_process_exit(); | |
b32b8144 | 272 | return INIRETSUCCESS_V; |
7c673cae FG |
273 | } |
274 | ||
275 | void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/) | |
276 | { | |
277 | switch (dwReason) | |
278 | { | |
279 | case DLL_THREAD_DETACH: | |
280 | boost::on_thread_exit(); | |
281 | break; | |
282 | } | |
283 | } | |
284 | ||
285 | #if (_MSC_VER >= 1500) | |
b32b8144 | 286 | BOOL WINAPI dll_callback(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) |
7c673cae | 287 | #else |
b32b8144 | 288 | BOOL WINAPI dll_callback(HINSTANCE, DWORD dwReason, LPVOID) |
7c673cae FG |
289 | #endif |
290 | { | |
291 | switch (dwReason) | |
292 | { | |
293 | case DLL_THREAD_DETACH: | |
294 | boost::on_thread_exit(); | |
295 | break; | |
296 | case DLL_PROCESS_DETACH: | |
297 | boost::on_process_exit(); | |
298 | break; | |
299 | } | |
300 | ||
301 | #if (_MSC_VER >= 1500) | |
302 | if( _pRawDllMainOrig ) | |
303 | { | |
304 | return _pRawDllMainOrig(hInstance, dwReason, lpReserved); | |
305 | } | |
306 | #endif | |
307 | return true; | |
308 | } | |
309 | } //namespace | |
310 | ||
311 | extern "C" | |
312 | { | |
b32b8144 | 313 | extern BOOL (WINAPI * const _pRawDllMain)(HINSTANCE, DWORD, LPVOID)=&dll_callback; |
7c673cae FG |
314 | } |
315 | namespace boost | |
316 | { | |
317 | void tss_cleanup_implemented() | |
318 | { | |
319 | /* | |
320 | This function's sole purpose is to cause a link error in cases where | |
321 | automatic tss cleanup is not implemented by Boost.Threads as a | |
322 | reminder that user code is responsible for calling the necessary | |
323 | functions at the appropriate times (and for implementing an a | |
324 | tss_cleanup_implemented() function to eliminate the linker's | |
325 | missing symbol error). | |
326 | ||
327 | If Boost.Threads later implements automatic tss cleanup in cases | |
328 | where it currently doesn't (which is the plan), the duplicate | |
329 | symbol error will warn the user that their custom solution is no | |
330 | longer needed and can be removed. | |
331 | */ | |
332 | } | |
333 | } | |
334 | ||
335 | #endif //defined(_MSC_VER) && !defined(UNDER_CE) | |
336 | ||
337 | #endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) |