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)
10 #include <boost/detail/winapi/config.hpp>
11 #include <boost/thread/detail/config.hpp>
13 #if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
15 #if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR)
17 #include <boost/thread/detail/tss_hooks.hpp>
25 void tss_cleanup_implemented() {}
29 void NTAPI
on_tls_callback(void* , DWORD dwReason
, PVOID
)
33 case DLL_THREAD_DETACH
:
35 boost::on_thread_exit();
42 #if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32__) || (__MINGW32_MAJOR_VERSION >3) || \
43 ((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18))
46 PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__
__attribute__ ((section(".CRT$XLB"))) = on_tls_callback
;
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
;
55 ULONG __tls_index__
= 0;
56 char __tls_end__
__attribute__((section(".tls$zzz"))) = 0;
57 char __tls_start__
__attribute__((section(".tls"))) = 0;
60 PIMAGE_TLS_CALLBACK __crt_xl_start__
__attribute__ ((section(".CRT$XLA"))) = 0;
61 PIMAGE_TLS_CALLBACK __crt_xl_end__
__attribute__ ((section(".CRT$XLZ"))) = 0;
63 extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used
__attribute__ ((section(".rdata$T"))) =
65 (DWORD
) &__tls_start__
,
67 (DWORD
) &__tls_index__
,
68 (DWORD
) (&__crt_xl_start__
+1),
75 #elif defined(_MSC_VER) && !defined(UNDER_CE)
77 #include <boost/thread/detail/tss_hooks.hpp>
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
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.
93 // work at least with _MSC_VER 1500 (MSVC++ 9.0, VS 2008)
94 #if (_MSC_VER >= 1500)
97 extern BOOL (WINAPI
* const _pRawDllMainOrig
)(HINSTANCE
, DWORD
, LPVOID
);
98 extern BOOL (WINAPI
* const _pDefaultRawDllMainOrig
)(HINSTANCE
, DWORD
, LPVOID
) = NULL
;
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) */
113 //Definitions required by implementation
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
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
137 typedef void (NTAPI
* _TLSCB
)(HINSTANCE
, DWORD
, PVOID
);
139 //Symbols for connection to the runtime environment
143 extern DWORD _tls_used
; //the tls directory (located in .rdata segment)
144 extern _TLSCB __xl_a
[], __xl_z
[]; //tls initializers */
149 //Forward declarations
151 static PVAPI_I
on_tls_prepare();
152 static PVAPI_V
on_process_init();
153 static PVAPI_V
on_process_term();
154 static void NTAPI
on_tls_callback(HINSTANCE
, DWORD
, PVOID
);
156 //The .CRT$Xxx information is taken from Codeguru:
157 //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/
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
;
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
;
169 #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
170 # pragma data_seg(push, old_seg)
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.
178 #pragma data_seg(".CRT$XIU")
179 static _PIFV_ p_tls_prepare
= on_tls_prepare
;
182 //Callback after all global ctors.
184 #pragma data_seg(".CRT$XCU")
185 static _PVFV_ p_process_init
= on_process_init
;
188 //Callback for tls notifications.
190 #pragma data_seg(".CRT$XLB")
191 _TLSCB p_thread_callback
= on_tls_callback
;
193 //Callback for termination.
195 #pragma data_seg(".CRT$XTU")
196 static _PVFV_ p_process_term
= on_process_term
;
198 #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
199 # pragma data_seg(pop, old_seg)
204 #pragma warning(push)
205 #pragma warning(disable:4189)
208 PVAPI_I
on_tls_prepare()
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.
218 DWORD
volatile dw
= _tls_used
;
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;
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)
230 while (pfbegin
< pfend
)
243 return INIRETSUCCESS_I
;
249 PVAPI_V
on_process_init()
251 //Schedule on_thread_exit() to be called for the main
252 //thread before destructors of global objects have been
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.
260 atexit(boost::on_thread_exit
);
262 //Call Boost process entry callback here
264 boost::on_process_enter();
266 return INIRETSUCCESS_V
;
269 PVAPI_V
on_process_term()
271 boost::on_process_exit();
272 return INIRETSUCCESS_V
;
275 void NTAPI
on_tls_callback(HINSTANCE
/*h*/, DWORD dwReason
, PVOID
/*pv*/)
279 case DLL_THREAD_DETACH
:
280 boost::on_thread_exit();
285 #if (_MSC_VER >= 1500)
286 BOOL WINAPI
dll_callback(HINSTANCE hInstance
, DWORD dwReason
, LPVOID lpReserved
)
288 BOOL WINAPI
dll_callback(HINSTANCE
, DWORD dwReason
, LPVOID
)
293 case DLL_THREAD_DETACH
:
294 boost::on_thread_exit();
296 case DLL_PROCESS_DETACH
:
297 boost::on_process_exit();
301 #if (_MSC_VER >= 1500)
302 if( _pRawDllMainOrig
)
304 return _pRawDllMainOrig(hInstance
, dwReason
, lpReserved
);
313 extern BOOL (WINAPI
* const _pRawDllMain
)(HINSTANCE
, DWORD
, LPVOID
)=&dll_callback
;
317 void tss_cleanup_implemented()
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).
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.
335 #endif //defined(_MSC_VER) && !defined(UNDER_CE)
337 #endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)