|
Boost : |
From: Roland (roland.schwarz_at_[hidden])
Date: 2004-08-04 11:22:14
Below I am posting my version that worked successfully with
MSVC6 (SP6 and below)
and MSVC7.1
I put this file (pe_tls.cpp) in the src directory and added it to the Jamfile.
Both compilers did well. And testing was succesful. Usercode still
needs BOOST_THREAD_USE_LIB.
Could you please check if I set the conditions correctly so things
won't break for other compilers?
File pe_tls.cpp follows:
/*
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
This piece of code is a result of the work of:
Aaron W.LaFramboise, who showed how to implement TLS-callback
Michael Glassford, who factored out the startup code
Bronek Kozicki, who showed me, that it is not harmful
to access the CRT after thread end
Roland Schwarz, who did the writing, runtime initialization
(.CRTXxx), correct dtor behaviour and broken MSVC 6 fix
08.02.2004
*/
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && defined (BOOST_MSVC)
/* altough this file is essentially C we need to compile it as CPP because */
/* the config.hpp assumes this */
extern "C" {
#include <stdlib.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#if (BOOST_MSVC < 1310) // 1310 == VC++ 7.1 vers 7.0 still has to be evaluated yet!
typedef void (__cdecl *_PVFV)(void);
#define INIRETSUCCESS
#define PVAPI void
#else
typedef int (__cdecl *_PVFV)(void);
#define INIRETSUCCESS 0
#define PVAPI int
#endif
typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
/* some symbols for connection to the runtime environment */
extern DWORD _tls_used; /* the tls directory (located in .rdata segment) */
extern _TLSCB __xl_a[], __xl_z[]; /* tls initializers */
/* the boost tss startup interface */
extern void on_process_enter(void);
extern void on_process_exit(void);
extern void on_thread_exit(void);
/* some forward declarations */
static PVAPI on_tls_prepare(void);
static PVAPI on_process_init(void);
static PVAPI on_process_term(void);
static void NTAPI on_thread_callback(HINSTANCE, DWORD, PVOID);
/* The .CRT$Xxx information is taken from Codeguru: */
/* http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/ */
/* The tls glue code is to be run first */
/* I don't think it is necessary to run it */
/* at .CRT$XIB level, since we are only */
/* interested in thread detachement. But */
/* this could be changed easily if required. */
#pragma data_seg(".CRT$XIU")
static _PVFV p_tls_prepare = on_tls_prepare;
#pragma data_seg()
/* we need to get control after all global ctors */
#pragma data_seg(".CRT$XCU")
static _PVFV p_process_init = on_process_init;
#pragma data_seg()
/* this is the TLS callback */
#pragma data_seg(".CRT$XLB")
_TLSCB p_thread_callback = on_thread_callback;
#pragma data_seg()
/* we will run the termination late */
#pragma data_seg(".CRT$XTU")
static _PVFV p_process_term = on_process_term;
#pragma data_seg()
static PVAPI on_tls_prepare(void)
{
/* the following line has an important side effect: */
/* if the TLS directory is not already there, it will */
/* be created by the linker. (_tls_used) */
/* voltile should prevent the optimizer from removing the reference */
DWORD volatile dw = _tls_used;
#if (BOOST_MSVC < 1310) // 1310 == VC++ 7.1
_TLSCB* pfbegin;
_TLSCB* pfend;
_TLSCB* pfdst;
pfbegin = __xl_a;
pfend = __xl_z;
pfdst = pfbegin;
/*pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks; */
/* the following loop will merge the address pointers */
/* into a contiguous area, since the tlssup code seems */
/* to require this (at least on MSVC 6) */
while (pfbegin < pfend) {
if (*pfbegin != 0) {
*pfdst = *pfbegin;
++pfdst;
}
++pfbegin;
}
*pfdst = 0;
#endif
return INIRETSUCCESS;
}
static PVAPI on_process_init(void)
{
/* This hooks the main thread exit. It will run the */
/* termination before global dtors, but will not be run */
/* when 'quick' exiting the library! However, this is the */
/* standard behaviour for all global dtors anyways. */
atexit(on_thread_exit);
/* hand over to boost */
on_process_enter();
return INIRETSUCCESS;
}
static PVAPI on_process_term(void)
{
on_process_exit();
return INIRETSUCCESS;
}
void NTAPI on_thread_callback(HINSTANCE h, DWORD dwReason, PVOID pv)
{
if(dwReason == DLL_THREAD_DETACH)
on_thread_exit();
}
void tss_cleanup_implemented(void) {};
};
#endif // BOOST_HAS_WINTHREADS
--EOF---
Roland
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk