2010-01-25 Kai Tietz <kai.tietz@onevision.com>

Implement TLS Callback.

        * tlsmcrt.c: New file.
        * tlsmthread.c: Ditto.
        * tlssup.c: Ditto.
        * tlsthrd.c: Ditto.
        * Makefile.in: Include new files.
        * crt1.c: Implement TLS Callback.
        * dllcrt1.c: Ditto.
        * mthr_stub.c: Remove.
This commit is contained in:
Chris Sutcliffe 2010-01-25 22:58:03 +00:00
parent 8944c6af48
commit d359eb2e1f
9 changed files with 472 additions and 48 deletions

View File

@ -1,3 +1,16 @@
2010-01-25 Kai Tietz <kai.tietz@onevision.com>
Implement TLS Callback.
* tlsmcrt.c: New file.
* tlsmthread.c: Ditto.
* tlssup.c: Ditto.
* tlsthrd.c: Ditto.
* Makefile.in: Include new files.
* crt1.c: Implement TLS Callback.
* dllcrt1.c: Ditto.
* mthr_stub.c: Remove.
2009-11-29 Chris Sutcliffe <ir0nh34d@users.sourceforge.net>
* include/_mingw.h: Increment version to 3.17.

View File

@ -227,8 +227,9 @@ FLAGS_TO_PASS:=\
CRT0S = crt1.o dllcrt1.o crt2.o dllcrt2.o CRT_noglob.o crtmt.o crtst.o \
CRT_fp8.o CRT_fp10.o txtmode.o binmode.o
MINGW_OBJS = CRTglob.o CRTfmode.o CRTinit.o dllmain.o gccmain.o \
main.o crtst.o mthr_stub.o CRT_fp10.o txtmode.o \
pseudo-reloc.o pseudo-reloc-list.o cpu_features.o
main.o crtst.o CRT_fp10.o txtmode.o \
pseudo-reloc.o pseudo-reloc-list.o cpu_features.o \
tlsmcrt.o tlsmthread.o tlssup.o tlsthrd.o
MOLD_OBJS = isascii.o iscsym.o iscsymf.o toascii.o \
strcasecmp.o strncasecmp.o wcscmpi.o
@ -247,6 +248,7 @@ LIBS = libcrtdll.a \
libmoldname80.a libmoldname80d.a \
libmoldname90.a libmoldname90d.a \
$(LIBM_A) \
libmingwthrd_old.a \
libmingwthrd.a
DLLS = $(THREAD_DLL_NAME)
@ -260,7 +262,7 @@ Makefile.in README TODO config.guess config.sub configure configure.in \
aclocal.m4 crt1.c crtdll.def crtmt.c crtst.c dllcrt1.c dllmain.c \
gccmain.c init.c install-sh jamfile main.c mkinstalldirs \
moldname.def.in msvcrt.def.in ofmt_stub.s \
mthr.c mthr_init.c mthr_stub.c readme.txt \
mthr.c mthr_init.c tlsmcrt.c tlsmthread.c tlssup.c tlsthrd.c readme.txt \
isascii.c iscsym.c iscsymf.c toascii.c \
strcasecmp.c strncasecmp.c wcscmpi.c \
CRT_fp8.c CRT_fp10.c test_headers.c txtmode.c binmode.c pseudo-reloc.c \
@ -290,7 +292,11 @@ libm.a: _libm_dummy.o
$(AR) rc $@ _libm_dummy.o
$(RANLIB) $@
libmingwthrd.a: crtmt.o mingwthrd.def
libmingwthrd.a: crtmt.o
$(AR) $(ARFLAGS) $@ crtmt.o
$(RANLIB) $@
libmingwthrd_old.a: crtmt.o mingwthrd.def
$(DLLTOOL) $(DLLTOOL_FLAGS) --dllname $(THREAD_DLL_NAME) \
--def mingwthrd.def --output-lib $@
$(AR) $(ARFLAGS) $@ crtmt.o

View File

@ -34,6 +34,9 @@ extern void _pei386_runtime_relocator (void);
extern int main (int, char **, char **);
/* TLS initialization hook. */
extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
/*
* Must have the correct app type for MSVCRT.
*/
@ -186,6 +189,10 @@ __mingw_CRTStartup (void)
{
int nRet;
/* Initialize TLS callback. */
if (__dyn_tls_init_callback != NULL)
__dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
/*
* Set up the top-level exception handler so that signal handling
* works as expected. The mapping between ANSI/POSIX signals and

View File

@ -14,6 +14,9 @@
#include <errno.h>
#include <windows.h>
/* TLS initialization hook. */
extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
/* Unlike normal crt1, I don't initialize the FPU, because the process
* should have done that already. I also don't set the file handle modes,
* because that would be rude. */
@ -62,6 +65,12 @@ DllMainCRTStartup (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
*first_atexit = NULL;
next_atexit = first_atexit;
/* Initialize TLS callback. */
if (__dyn_tls_init_callback != NULL)
{
__dyn_tls_init_callback (hDll, DLL_THREAD_ATTACH, lpReserved);
}
/* Adust references to dllimported data (from other DLL's)
that have non-zero offsets. */
_pei386_runtime_relocator ();

View File

@ -1,44 +0,0 @@
/*
* mthr_stub.c
*
* Implement Mingw thread-support stubs for single-threaded C++ apps.
*
* This file is used by if gcc is built with --enable-threads=win32 and
* iff gcc does *NOT* use -mthreads option.
*
* The -mthreads implementation is in mthr.c.
*
* Created by Mumit Khan <khan@nanotech.wisc.edu>
*
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
/*
* __mingwthr_register_key_dtor (DWORD key, void (*dtor) (void *))
*
* Public interface called by C++ exception handling mechanism in
* libgcc (cf: __gthread_key_create).
* No-op versions.
*/
int
__mingwthr_key_dtor (DWORD key, void (*dtor) (void *))
{
#ifdef DEBUG
printf ("%s: ignoring key: (%ld) / dtor: (%x)\n",
__FUNCTION__, key, dtor);
#endif
return 0;
}
int
__mingwthr_remove_key_dtor (DWORD key )
{
#ifdef DEBUG
printf ("%s: ignoring key: (%ld)\n", __FUNCTION__, key );
#endif
return 0;
}

13
winsup/mingw/tlsmcrt.c Normal file
View File

@ -0,0 +1,13 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the w64 mingw-runtime package.
* No warranty is given; refer to the file DISCLAIMER within this package.
*
* Written by Kai Tietz <kai.tietz@onevision.com>
*/
/* We support TLS cleanup code in any case. If shared version of libgcc is used _CRT_MT has value 1,
otherwise
we do tls cleanup in runtime and _CRT_MT has value 2. */
int _CRT_MT = 2;

59
winsup/mingw/tlsmthread.c Normal file
View File

@ -0,0 +1,59 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the w64 mingw-runtime package.
* No warranty is given; refer to the file DISCLAIMER within this package.
*
* Written by Kai Tietz <kai.tietz@onevision.com>
*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <stdlib.h>
int __mingwthr_key_dtor (DWORD key, void (*dtor)(void *));
int __mingwthr_remove_key_dtor (DWORD key);
extern int ___w64_mingwthr_remove_key_dtor (DWORD key);
extern int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
#ifndef _WIN64
#define MINGWM10_DLL "mingwm10.dll"
typedef int (*fMTRemoveKeyDtor)(DWORD key);
typedef int (*fMTKeyDtor)(DWORD key, void (*dtor)(void *));
extern fMTRemoveKeyDtor __mingw_gMTRemoveKeyDtor;
extern fMTKeyDtor __mingw_gMTKeyDtor;
extern int __mingw_usemthread_dll;
#endif
int
__mingwthr_remove_key_dtor (DWORD key)
{
#ifndef _WIN64
if (!__mingw_usemthread_dll)
#endif
return ___w64_mingwthr_remove_key_dtor (key);
#ifndef _WIN64
if (__mingw_gMTRemoveKeyDtor)
return (*__mingw_gMTRemoveKeyDtor) (key);
return 0;
#endif
}
int
__mingwthr_key_dtor (DWORD key, void (*dtor)(void *))
{
if (dtor)
{
#ifndef _WIN64
if (!__mingw_usemthread_dll)
#endif
return ___w64_mingwthr_add_key_dtor (key, dtor);
#ifndef _WIN64
if (__mingw_gMTKeyDtor)
return (*__mingw_gMTKeyDtor) (key, dtor);
#endif
}
return 0;
}

213
winsup/mingw/tlssup.c Normal file
View File

@ -0,0 +1,213 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the w64 mingw-runtime package.
* No warranty is given; refer to the file DISCLAIMER within this package.
*
* Written by Kai Tietz <kai.tietz@onevision.com>
*/
#ifdef CRTDLL
#undef CRTDLL
#endif
#include <windows.h>
#include <stdio.h>
#include <memory.h>
#include <malloc.h>
#ifndef _CRTALLOC
#define _CRTALLOC(x) __attribute__ ((section (x) ))
#endif
#ifndef __INTERNAL_FUNC_DEFINED
#define __INTERNAL_FUNC_DEFINED
typedef void (__cdecl *_PVFV)(void);
typedef int (__cdecl *_PIFV)(void);
typedef void (__cdecl *_PVFI)(int);
#endif
extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
#define FUNCS_PER_NODE 30
typedef struct TlsDtorNode {
int count;
struct TlsDtorNode *next;
_PVFV funcs[FUNCS_PER_NODE];
} TlsDtorNode;
ULONG _tls_index = 0;
/* TLS raw template data start and end. */
_CRTALLOC(".tls$AAA") char _tls_start = 0;
_CRTALLOC(".tls$ZZZ") char _tls_end = 0;
_CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
_CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
#ifdef _WIN64
_CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY64 _tls_used = {
(ULONGLONG) &_tls_start+1, (ULONGLONG) &_tls_end, (ULONGLONG) &_tls_index,
(ULONGLONG) (&__xl_a+1), (ULONG) 0, (ULONG) 0
};
#else
_CRTALLOC(".tls") const IMAGE_TLS_DIRECTORY _tls_used = {
(ULONG)(ULONG_PTR) &_tls_start+1, (ULONG)(ULONG_PTR) &_tls_end,
(ULONG)(ULONG_PTR) &_tls_index, (ULONG)(ULONG_PTR) (&__xl_a+1),
(ULONG) 0, (ULONG) 0
};
#endif
#ifndef __CRT_THREAD
#ifdef HAVE_ATTRIBUTE_THREAD
#define __CRT_THREAD __declspec(thread)
#else
#define __CRT_THREAD __thread
#endif
#endif
#define DISABLE_MS_TLS 1
static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
#if !defined (DISABLE_MS_TLS)
static __CRT_THREAD TlsDtorNode *dtor_list;
static __CRT_THREAD TlsDtorNode dtor_list_head;
#endif
extern int _CRT_MT;
#ifndef _WIN64
#define MINGWM10_DLL "mingwm10.dll"
typedef int (*fMTRemoveKeyDtor)(DWORD key);
typedef int (*fMTKeyDtor)(DWORD key, void (*dtor)(void *));
fMTRemoveKeyDtor __mingw_gMTRemoveKeyDtor;
fMTKeyDtor __mingw_gMTKeyDtor;
int __mingw_usemthread_dll;
static HANDLE __mingw_mthread_hdll;
#endif
BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
BOOL WINAPI
__dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
{
_PVFV *pfunc;
#ifndef _WIN64
if (_winmajor < 4)
{
__mingw_usemthread_dll = 1;
__mingw_mthread_hdll = LoadLibrary (MINGWM10_DLL);
if (__mingw_mthread_hdll != NULL)
{
__mingw_gMTRemoveKeyDtor = (fMTRemoveKeyDtor) GetProcAddress (__mingw_mthread_hdll, "__mingwthr_remove_key_dtor");
__mingw_gMTKeyDtor = (fMTKeyDtor) GetProcAddress (__mingw_mthread_hdll, "__mingwthr_key_dtor");
}
if (__mingw_mthread_hdll == NULL || !__mingw_gMTRemoveKeyDtor || !__mingw_gMTKeyDtor)
{
__mingw_gMTKeyDtor = NULL;
__mingw_gMTRemoveKeyDtor = NULL;
if (__mingw_mthread_hdll)
FreeLibrary (__mingw_mthread_hdll);
__mingw_mthread_hdll = NULL;
_CRT_MT = 0;
return TRUE;
}
_CRT_MT = 1;
return TRUE;
}
#endif
/* We don't let us trick here. */
if (_CRT_MT != 2)
_CRT_MT = 2;
if (dwReason != DLL_THREAD_ATTACH)
{
if (dwReason == DLL_PROCESS_ATTACH)
__mingw_TLScallback (hDllHandle, dwReason, lpreserved);
return TRUE;
}
for (pfunc = &__xd_a + 1; pfunc != &__xd_z; ++pfunc)
{
if (*pfunc != NULL)
(*pfunc)();
}
return TRUE;
}
const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init;
_CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init;
int __cdecl __tlregdtor (_PVFV);
int __cdecl
__tlregdtor (_PVFV func)
{
if (!func)
return 0;
#if !defined (DISABLE_MS_TLS)
if (dtor_list == NULL)
{
dtor_list = &dtor_list_head;
dtor_list_head.count = 0;
}
else if (dtor_list->count == FUNCS_PER_NODE)
{
TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
if (pnode == NULL)
return -1;
pnode->count = 0;
pnode->next = dtor_list;
dtor_list = pnode;
dtor_list->count = 0;
}
dtor_list->funcs[dtor_list->count++] = func;
#endif
return 0;
}
static BOOL WINAPI
__dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
{
#if !defined (DISABLE_MS_TLS)
TlsDtorNode *pnode, *pnext;
int i;
#endif
if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
return TRUE;
/* As TLS variables are detroyed already by DLL_THREAD_DETACH
call, we have to avoid access on the possible DLL_PROCESS_DETACH
call the already destroyed TLS vars.
TODO: The used local thread based variables have to be handled
manually, so that we can control their lifetime here. */
#if !defined (DISABLE_MS_TLS)
if (dwReason != DLL_PROCESS_DETACH)
{
for (pnode = dtor_list; pnode != NULL; pnode = pnext)
{
for (i = pnode->count - 1; i >= 0; --i)
{
if (pnode->funcs[i] != NULL)
(*pnode->funcs[i])();
}
pnext = pnode->next;
if (pnext != NULL)
free ((void *) pnode);
}
}
#endif
__mingw_TLScallback (hDllHandle, dwReason, lpreserved);
return TRUE;
}
_CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor;
int mingw_initltsdrot_force = 0;
int mingw_initltsdyn_force=0;
int mingw_initltssuo_force = 0;

148
winsup/mingw/tlsthrd.c Normal file
View File

@ -0,0 +1,148 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the w64 mingw-runtime package.
* No warranty is given; refer to the file DISCLAIMER within this package.
*
* Written by Kai Tietz <kai.tietz@onevision.com>
*
* This file is used by if gcc is built with --enable-threads=win32.
*
* Based on version created by Mumit Khan <khan@nanotech.wisc.edu>
*
*/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <stdlib.h>
WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
int ___w64_mingwthr_remove_key_dtor (DWORD key);
int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
/* To protect the thread/key association data structure modifications. */
static CRITICAL_SECTION __mingwthr_cs;
static volatile int __mingwthr_cs_init = 0;
typedef struct __mingwthr_key __mingwthr_key_t;
/* The list of threads active with key/dtor pairs. */
struct __mingwthr_key {
DWORD key;
void (*dtor)(void *);
__mingwthr_key_t volatile *next;
};
static __mingwthr_key_t volatile *key_dtor_list;
int
___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *))
{
__mingwthr_key_t *new_key;
if (__mingwthr_cs_init == 0)
return 0;
new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
if (new_key == NULL)
return -1;
new_key->key = key;
new_key->dtor = dtor;
EnterCriticalSection (&__mingwthr_cs);
new_key->next = key_dtor_list;
key_dtor_list = new_key;
LeaveCriticalSection (&__mingwthr_cs);
return 0;
}
int
___w64_mingwthr_remove_key_dtor (DWORD key)
{
__mingwthr_key_t volatile *prev_key;
__mingwthr_key_t volatile *cur_key;
if (__mingwthr_cs_init == 0)
return 0;
EnterCriticalSection (&__mingwthr_cs);
prev_key = NULL;
cur_key = key_dtor_list;
while (cur_key != NULL)
{
if ( cur_key->key == key)
{
if (prev_key == NULL)
key_dtor_list = cur_key->next;
else
prev_key->next = cur_key->next;
free ((void*)cur_key);
break;
}
prev_key = cur_key;
cur_key = cur_key->next;
}
LeaveCriticalSection (&__mingwthr_cs);
return 0;
}
static void
__mingwthr_run_key_dtors (void)
{
__mingwthr_key_t volatile *keyp;
if (__mingwthr_cs_init == 0)
return;
EnterCriticalSection (&__mingwthr_cs);
for (keyp = key_dtor_list; keyp; )
{
LPVOID value = TlsGetValue (keyp->key);
if (GetLastError () == ERROR_SUCCESS)
{
if (value)
(*keyp->dtor) (value);
}
keyp = keyp->next;
}
LeaveCriticalSection (&__mingwthr_cs);
}
WINBOOL
__mingw_TLScallback (HANDLE hDllHandle __attribute__ ((__unused__)),
DWORD reason,
LPVOID reserved __attribute__ ((__unused__)))
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
if (__mingwthr_cs_init == 0)
InitializeCriticalSection (&__mingwthr_cs);
__mingwthr_cs_init = 1;
break;
case DLL_PROCESS_DETACH:
__mingwthr_run_key_dtors();
if (__mingwthr_cs_init == 1)
{
__mingwthr_cs_init = 0;
DeleteCriticalSection (&__mingwthr_cs);
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
__mingwthr_run_key_dtors();
break;
}
return TRUE;
}