Welcome to mirror list, hosted at ThFree Co, Russian Federation.

tlssup.c « mingw « winsup - cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b101d1124509a00c7e5cc2f48ce37e1947b61e71 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
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;