master
  1/**
  2 * This file has no copyright assigned and is placed in the Public Domain.
  3 * This file is part of the mingw-w64 runtime package.
  4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  5 *
  6 * Written by Kai Tietz  <kai.tietz@onevision.com>
  7 */
  8
  9#include <sect_attribs.h>
 10
 11#ifndef WIN32_LEAN_AND_MEAN
 12#define WIN32_LEAN_AND_MEAN
 13#endif
 14#include <windows.h>
 15
 16#include <stdio.h>
 17#include <memory.h>
 18#include <malloc.h>
 19#include <corecrt_startup.h>
 20
 21extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
 22
 23#define FUNCS_PER_NODE 30
 24
 25typedef struct TlsDtorNode {
 26  int count;
 27  struct TlsDtorNode *next;
 28  _PVFV funcs[FUNCS_PER_NODE];
 29} TlsDtorNode;
 30
 31__attribute__((used))
 32ULONG _tls_index = 0;
 33
 34/* TLS raw template data start and end. 
 35   We use here pointer-types for start/end so that tls-data remains
 36   aligned on pointer-size-width.  This seems to be required for
 37   pe-loader. */
 38_CRTALLOC(".tls") char *_tls_start = NULL;
 39_CRTALLOC(".tls$ZZZ") char *_tls_end = NULL;
 40
 41_CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0;
 42_CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0;
 43
 44__attribute__((used))
 45const IMAGE_TLS_DIRECTORY _tls_used = {
 46  (ULONG_PTR) &_tls_start, (ULONG_PTR) &_tls_end,
 47  (ULONG_PTR) &_tls_index, (ULONG_PTR) (&__xl_a+1),
 48  (ULONG) 0, (ULONG) 0
 49};
 50
 51#ifndef __CRT_THREAD
 52#ifdef HAVE_ATTRIBUTE_THREAD
 53#define __CRT_THREAD	__declspec(thread)
 54#else
 55#define __CRT_THREAD    __thread
 56#endif
 57#endif
 58
 59#define DISABLE_MS_TLS 1
 60
 61static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0;
 62static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0;
 63
 64#if !defined (DISABLE_MS_TLS)
 65static __CRT_THREAD TlsDtorNode *dtor_list;
 66static __CRT_THREAD TlsDtorNode dtor_list_head;
 67#endif
 68
 69extern int _CRT_MT;
 70
 71void WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID);
 72void WINAPI __dyn_tls_dtor (HANDLE, DWORD, LPVOID);
 73
 74void WINAPI
 75__dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
 76{
 77  _PVFV *pfunc;
 78  uintptr_t ps;
 79
 80  /* We don't let us trick here.  */
 81  if (_CRT_MT != 2)
 82   _CRT_MT = 2;
 83
 84  if (dwReason != DLL_THREAD_ATTACH)
 85    {
 86      if (dwReason == DLL_PROCESS_ATTACH)
 87        __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
 88      return;
 89    }
 90
 91  ps = (uintptr_t) &__xd_a;
 92  ps += sizeof (uintptr_t);
 93  for ( ; ps != (uintptr_t) &__xd_z; ps += sizeof (uintptr_t))
 94    {
 95      pfunc = (_PVFV *) ps;
 96      if (*pfunc != NULL)
 97	(*pfunc)();
 98    }
 99}
100
101const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = __dyn_tls_init;
102_CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = __dyn_tls_init;
103
104int __cdecl __tlregdtor (_PVFV);
105
106int __cdecl
107__tlregdtor (_PVFV func)
108{
109  if (!func)
110    return 0;
111#if !defined (DISABLE_MS_TLS)
112  if (dtor_list == NULL)
113    {
114      dtor_list = &dtor_list_head;
115      dtor_list_head.count = 0;
116    }
117    else if (dtor_list->count == FUNCS_PER_NODE)
118    {
119      TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode));
120      if (pnode == NULL)
121	return -1;
122      pnode->count = 0;
123      pnode->next = dtor_list;
124      dtor_list = pnode;
125
126      dtor_list->count = 0;
127    }
128  dtor_list->funcs[dtor_list->count++] = func;
129#endif
130  return 0;
131}
132
133void WINAPI
134__dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
135{
136#if !defined (DISABLE_MS_TLS)
137  TlsDtorNode *pnode, *pnext;
138  int i;
139#endif
140
141  if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH)
142    return;
143  /* As TLS variables are detroyed already by DLL_THREAD_DETACH
144     call, we have to avoid access on the possible DLL_PROCESS_DETACH
145     call the already destroyed TLS vars.
146     TODO: The used local thread based variables have to be handled
147     manually, so that we can control their lifetime here.  */
148#if !defined (DISABLE_MS_TLS)
149  if (dwReason != DLL_PROCESS_DETACH)
150    {
151      for (pnode = dtor_list; pnode != NULL; pnode = pnext)
152        {
153          for (i = pnode->count - 1; i >= 0; --i)
154	    {
155	      if (pnode->funcs[i] != NULL)
156	        (*pnode->funcs[i])();
157	    }
158          pnext = pnode->next;
159          if (pnext != NULL)
160	    free ((void *) pnode);
161        }
162    }
163#endif
164  __mingw_TLScallback (hDllHandle, dwReason, lpreserved);
165}
166
167_CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = __dyn_tls_dtor;
168
169
170int __mingw_initltsdrot_force = 0;
171int __mingw_initltsdyn_force = 0;
172int __mingw_initltssuo_force = 0;