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.PD 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 <sect_attribs.h> 14 15 /*#ifndef WIN32_LEAN_AND_MEAN 16 #define WIN32_LEAN_AND_MEAN 17 #endif 18 #include <windows.h>*/ 19 20 #include <stdarg.h> 21 #include <windef.h> 22 #include <winbase.h> 23 24 #include <stdio.h> 25 #include <memory.h> 26 #include <malloc.h> 27 #ifndef _WIN64 28 #include <stdlib.h> /* for _winmajor */ 29 #endif 30 31 #ifndef __INTERNAL_FUNC_DEFINED 32 #define __INTERNAL_FUNC_DEFINED 33 typedef void (__cdecl *_PVFV)(void); 34 typedef int (__cdecl *_PIFV)(void); 35 typedef void (__cdecl *_PVFI)(int); 36 #endif 37 38 extern WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved); 39 40 #define FUNCS_PER_NODE 30 41 42 typedef struct TlsDtorNode { 43 int count; 44 struct TlsDtorNode *next; 45 _PVFV funcs[FUNCS_PER_NODE]; 46 } TlsDtorNode; 47 48 ULONG _tls_index = 0; 49 50 /* TLS raw template data start and end. */ 51 _CRTALLOC(".tls") char _tls_start = 0; 52 _CRTALLOC(".tls$ZZZ") char _tls_end = 0; 53 54 _CRTALLOC(".CRT$XLA") PIMAGE_TLS_CALLBACK __xl_a = 0; 55 _CRTALLOC(".CRT$XLZ") PIMAGE_TLS_CALLBACK __xl_z = 0; 56 57 _CRTALLOC(".rdata$T") const IMAGE_TLS_DIRECTORY _tls_used = { 58 (ULONG_PTR) &_tls_start+1, (ULONG_PTR) &_tls_end, 59 (ULONG_PTR) &_tls_index, (ULONG_PTR) (&__xl_a+1), 60 (ULONG) 0, (ULONG) 0 61 }; 62 63 #ifndef __CRT_THREAD 64 #ifdef HAVE_ATTRIBUTE_THREAD 65 #define __CRT_THREAD __declspec(thread) 66 #else 67 #define __CRT_THREAD __thread 68 #endif 69 #endif 70 71 #define DISABLE_MS_TLS 1 72 73 static _CRTALLOC(".CRT$XDA") _PVFV __xd_a = 0; 74 static _CRTALLOC(".CRT$XDZ") _PVFV __xd_z = 0; 75 76 #if !defined (DISABLE_MS_TLS) 77 static __CRT_THREAD TlsDtorNode *dtor_list; 78 static __CRT_THREAD TlsDtorNode dtor_list_head; 79 #endif 80 81 extern int _CRT_MT; 82 83 #ifndef _WIN64 84 int __mingw_usemthread_dll; 85 #endif 86 87 BOOL WINAPI __dyn_tls_init (HANDLE, DWORD, LPVOID); 88 89 BOOL WINAPI 90 __dyn_tls_init (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) 91 { 92 _PVFV *pfunc; 93 uintptr_t ps; 94 95 /* We don't let us trick here. */ 96 if (_CRT_MT != 2) 97 _CRT_MT = 2; 98 99 if (dwReason != DLL_THREAD_ATTACH) 100 { 101 if (dwReason == DLL_PROCESS_ATTACH) 102 __mingw_TLScallback (hDllHandle, dwReason, lpreserved); 103 return TRUE; 104 } 105 106 ps = (uintptr_t) &__xd_a; 107 ps += sizeof (uintptr_t); 108 for ( ; ps != (uintptr_t) &__xd_z; ps += sizeof (uintptr_t)) 109 { 110 pfunc = (_PVFV *) ps; 111 if (*pfunc != NULL) 112 (*pfunc)(); 113 } 114 return TRUE; 115 } 116 117 const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback = (const PIMAGE_TLS_CALLBACK) __dyn_tls_init; 118 _CRTALLOC(".CRT$XLC") PIMAGE_TLS_CALLBACK __xl_c = (PIMAGE_TLS_CALLBACK) __dyn_tls_init; 119 120 int __cdecl __tlregdtor (_PVFV); 121 122 int __cdecl 123 __tlregdtor (_PVFV func) 124 { 125 if (!func) 126 return 0; 127 #if !defined (DISABLE_MS_TLS) 128 if (dtor_list == NULL) 129 { 130 dtor_list = &dtor_list_head; 131 dtor_list_head.count = 0; 132 } 133 else if (dtor_list->count == FUNCS_PER_NODE) 134 { 135 TlsDtorNode *pnode = (TlsDtorNode *) malloc (sizeof (TlsDtorNode)); 136 if (pnode == NULL) 137 return -1; 138 pnode->count = 0; 139 pnode->next = dtor_list; 140 dtor_list = pnode; 141 142 dtor_list->count = 0; 143 } 144 dtor_list->funcs[dtor_list->count++] = func; 145 #endif 146 return 0; 147 } 148 149 static BOOL WINAPI 150 __dyn_tls_dtor (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) 151 { 152 #if !defined (DISABLE_MS_TLS) 153 TlsDtorNode *pnode, *pnext; 154 int i; 155 #endif 156 157 if (dwReason != DLL_THREAD_DETACH && dwReason != DLL_PROCESS_DETACH) 158 return TRUE; 159 /* As TLS variables are detroyed already by DLL_THREAD_DETACH 160 call, we have to avoid access on the possible DLL_PROCESS_DETACH 161 call the already destroyed TLS vars. 162 TODO: The used local thread based variables have to be handled 163 manually, so that we can control their lifetime here. */ 164 #if !defined (DISABLE_MS_TLS) 165 if (dwReason != DLL_PROCESS_DETACH) 166 { 167 for (pnode = dtor_list; pnode != NULL; pnode = pnext) 168 { 169 for (i = pnode->count - 1; i >= 0; --i) 170 { 171 if (pnode->funcs[i] != NULL) 172 (*pnode->funcs[i])(); 173 } 174 pnext = pnode->next; 175 if (pnext != NULL) 176 free ((void *) pnode); 177 } 178 } 179 #endif 180 __mingw_TLScallback (hDllHandle, dwReason, lpreserved); 181 return TRUE; 182 } 183 184 _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK __xl_d = (PIMAGE_TLS_CALLBACK) __dyn_tls_dtor; 185 186 187 int mingw_initltsdrot_force = 0; 188 int mingw_initltsdyn_force = 0; 189 int mingw_initltssuo_force = 0; 190