blob: 22880ce153e9ca66ed352c35c75fac841ddb2e45 [file]
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD 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 <sect_attribs.h>
#include <memory.h>
#include <malloc.h>
#include <corecrt_startup.h>
#include <thread_local.h>
#define FUNCS_PER_NODE 30
typedef struct TlsDtorNode {
int count;
struct TlsDtorNode *next;
_PVFV funcs[FUNCS_PER_NODE];
} TlsDtorNode;
static TlsDtorNode **get_dtor_list_ptr (void)
{
TlsDtorNode **dtor_list_ptr = __MINGW_ALLOC_THREAD_LOCAL_OR_NULL(TlsDtorNode*);
return dtor_list_ptr;
}
static TlsDtorNode *get_dtor_list_head_ptr (void)
{
TlsDtorNode *dtor_list_head_ptr = __MINGW_ALLOC_THREAD_LOCAL_OR_NULL(TlsDtorNode);
return dtor_list_head_ptr;
}
int __cdecl __tlregdtor (_PVFV);
int __cdecl
__tlregdtor (_PVFV func)
{
TlsDtorNode **dtor_list_ptr = get_dtor_list_ptr();
TlsDtorNode *dtor_list_head_ptr = get_dtor_list_head_ptr();
if (!dtor_list_ptr || !dtor_list_head_ptr)
return -1;
#define dtor_list (*dtor_list_ptr)
#define dtor_list_head (*dtor_list_head_ptr)
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;
return 0;
#undef dtor_list
#undef dtor_list_head
}
static void WINAPI
__dyn_tls_dtor (HANDLE hDllHandle __attribute__((unused)), DWORD dwReason, LPVOID lpreserved __attribute__((unused)))
{
TlsDtorNode *pnode, *pnext;
int i;
TlsDtorNode **dtor_list_ptr = get_dtor_list_ptr();
if (!dtor_list_ptr)
return;
if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
return;
for (pnode = *dtor_list_ptr; 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);
*dtor_list_ptr = pnext;
}
}
static _CRTALLOC(".CRT$XLD") const PIMAGE_TLS_CALLBACK __xl_d = __dyn_tls_dtor;
/* Force tlssup.c (_tls_used symbol for .tls linker section) to be linked. */
extern const IMAGE_TLS_DIRECTORY _tls_used;
static __attribute__((destructor)) void _include_tls_used(void) { asm volatile ("" :: "r" (&_tls_used)); }