1 // $Id: tss_pe.cpp 72431 2011-06-06 08:28:31Z anthonyw $
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/thread/detail/config.hpp>
12 #if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
14 #if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__)
16 #include <boost/thread/detail/tss_hooks.hpp>
24 void tss_cleanup_implemented() {}
28 void NTAPI on_tls_callback(void* h, DWORD dwReason, PVOID pv)
32 case DLL_THREAD_DETACH:
34 boost::on_thread_exit();
41 #if defined(__MINGW64__) || (__MINGW32_MAJOR_VERSION >3) || \
42 ((__MINGW32_MAJOR_VERSION==3) && (__MINGW32_MINOR_VERSION>=18))
45 PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback;
50 void (* after_ctors )() __attribute__((section(".ctors"))) = boost::on_process_enter;
51 void (* before_dtors)() __attribute__((section(".dtors"))) = boost::on_thread_exit;
52 void (* after_dtors )() __attribute__((section(".dtors.zzz"))) = boost::on_process_exit;
54 ULONG __tls_index__ = 0;
55 char __tls_end__ __attribute__((section(".tls$zzz"))) = 0;
56 char __tls_start__ __attribute__((section(".tls"))) = 0;
59 PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0;
60 PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0;
62 extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) =
64 (DWORD) &__tls_start__,
66 (DWORD) &__tls_index__,
67 (DWORD) (&__crt_xl_start__+1),
74 #elif defined(_MSC_VER) && !defined(UNDER_CE)
76 #include <boost/thread/detail/tss_hooks.hpp>
80 #define WIN32_LEAN_AND_MEAN
83 //Definitions required by implementation
85 #if (_MSC_VER < 1300) // 1300 == VC++ 7.0
86 typedef void (__cdecl *_PVFV)();
88 #define PVAPI void __cdecl
90 typedef int (__cdecl *_PVFV)();
91 #define INIRETSUCCESS 0
92 #define PVAPI int __cdecl
95 typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
97 //Symbols for connection to the runtime environment
101 extern DWORD _tls_used; //the tls directory (located in .rdata segment)
102 extern _TLSCB __xl_a[], __xl_z[]; //tls initializers */
107 //Forward declarations
109 static PVAPI on_tls_prepare();
110 static PVAPI on_process_init();
111 static PVAPI on_process_term();
112 static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID);
114 //The .CRT$Xxx information is taken from Codeguru:
115 //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/
117 #if (_MSC_VER >= 1400)
118 #pragma section(".CRT$XIU",long,read)
119 #pragma section(".CRT$XCU",long,read)
120 #pragma section(".CRT$XTU",long,read)
121 #pragma section(".CRT$XLC",long,read)
122 __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback;
123 __declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare;
124 __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init;
125 __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term;
127 #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
128 # pragma data_seg(push, old_seg)
130 //Callback to run tls glue code first.
131 //I don't think it is necessary to run it
132 //at .CRT$XIB level, since we are only
133 //interested in thread detachement. But
134 //this could be changed easily if required.
136 #pragma data_seg(".CRT$XIU")
137 static _PVFV p_tls_prepare = on_tls_prepare;
140 //Callback after all global ctors.
142 #pragma data_seg(".CRT$XCU")
143 static _PVFV p_process_init = on_process_init;
146 //Callback for tls notifications.
148 #pragma data_seg(".CRT$XLB")
149 _TLSCB p_thread_callback = on_tls_callback;
151 //Callback for termination.
153 #pragma data_seg(".CRT$XTU")
154 static _PVFV p_process_term = on_process_term;
156 #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
157 # pragma data_seg(pop, old_seg)
162 #pragma warning(push)
163 #pragma warning(disable:4189)
166 PVAPI on_tls_prepare()
168 //The following line has an important side effect:
169 //if the TLS directory is not already there, it will
170 //be created by the linker. In other words, it forces a tls
171 //directory to be generated by the linker even when static tls
172 //(i.e. __declspec(thread)) is not used.
173 //The volatile should prevent the optimizer
174 //from removing the reference.
176 DWORD volatile dw = _tls_used;
178 #if (_MSC_VER < 1300) // 1300 == VC++ 7.0
179 _TLSCB* pfbegin = __xl_a;
180 _TLSCB* pfend = __xl_z;
181 _TLSCB* pfdst = pfbegin;
182 //pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks;
184 //The following loop will merge the address pointers
185 //into a contiguous area, since the tlssup code seems
186 //to require this (at least on MSVC 6)
188 while (pfbegin < pfend)
201 return INIRETSUCCESS;
207 PVAPI on_process_init()
209 //Schedule on_thread_exit() to be called for the main
210 //thread before destructors of global objects have been
213 //It will not be run when 'quick' exiting the
214 //library; however, this is the standard behaviour
215 //for destructors of global objects, so that
216 //shouldn't be a problem.
218 atexit(boost::on_thread_exit);
220 //Call Boost process entry callback here
222 boost::on_process_enter();
224 return INIRETSUCCESS;
227 PVAPI on_process_term()
229 boost::on_process_exit();
230 return INIRETSUCCESS;
233 void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/)
237 case DLL_THREAD_DETACH:
238 boost::on_thread_exit();
243 BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID)
247 case DLL_THREAD_DETACH:
248 boost::on_thread_exit();
250 case DLL_PROCESS_DETACH:
251 boost::on_process_exit();
260 extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID)=&dll_callback;
264 void tss_cleanup_implemented()
267 This function's sole purpose is to cause a link error in cases where
268 automatic tss cleanup is not implemented by Boost.Threads as a
269 reminder that user code is responsible for calling the necessary
270 functions at the appropriate times (and for implementing an a
271 tss_cleanup_implemented() function to eliminate the linker's
272 missing symbol error).
274 If Boost.Threads later implements automatic tss cleanup in cases
275 where it currently doesn't (which is the plan), the duplicate
276 symbol error will warn the user that their custom solution is no
277 longer needed and can be removed.
282 #endif //defined(_MSC_VER) && !defined(UNDER_CE)
284 #endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)