OSDN Git Service

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