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 * This file is used by if gcc is built with --enable-threads=win32.
9 *
10 * Based on version created by Mumit Khan <khan@nanotech.wisc.edu>
11 *
12 */
13
14 #ifndef WIN32_LEAN_AND_MEAN
15 #define WIN32_LEAN_AND_MEAN
16 #endif
17 #include <windows.h>
18 #include <stdlib.h>
19
20 extern void __cdecl __MINGW_NOTHROW _fpreset (void);
21 WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
22 int ___w64_mingwthr_remove_key_dtor (DWORD key);
23 int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
24
25 /* To protect the thread/key association data structure modifications. */
26 static CRITICAL_SECTION __mingwthr_cs;
27 static volatile int __mingwthr_cs_init = 0;
28
29 typedef struct __mingwthr_key __mingwthr_key_t;
30
31 /* The list of threads active with key/dtor pairs. */
32 struct __mingwthr_key {
33 DWORD key;
34 void (*dtor)(void *);
35 __mingwthr_key_t volatile *next;
36 };
37
38
39 static __mingwthr_key_t volatile *key_dtor_list;
40
41 int
___w64_mingwthr_add_key_dtor(DWORD key,void (* dtor)(void *))42 ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *))
43 {
44 __mingwthr_key_t *new_key;
45
46 if (__mingwthr_cs_init == 0)
47 return 0;
48 new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
49 if (new_key == NULL)
50 return -1;
51
52 new_key->key = key;
53 new_key->dtor = dtor;
54
55 EnterCriticalSection (&__mingwthr_cs);
56
57 new_key->next = key_dtor_list;
58 key_dtor_list = new_key;
59
60 LeaveCriticalSection (&__mingwthr_cs);
61 return 0;
62 }
63
64 int
___w64_mingwthr_remove_key_dtor(DWORD key)65 ___w64_mingwthr_remove_key_dtor (DWORD key)
66 {
67 __mingwthr_key_t volatile *prev_key;
68 __mingwthr_key_t volatile *cur_key;
69
70 if (__mingwthr_cs_init == 0)
71 return 0;
72
73 EnterCriticalSection (&__mingwthr_cs);
74
75 prev_key = NULL;
76 cur_key = key_dtor_list;
77
78 while (cur_key != NULL)
79 {
80 if ( cur_key->key == key)
81 {
82 if (prev_key == NULL)
83 key_dtor_list = cur_key->next;
84 else
85 prev_key->next = cur_key->next;
86
87 free ((void*)cur_key);
88 break;
89 }
90 prev_key = cur_key;
91 cur_key = cur_key->next;
92 }
93
94 LeaveCriticalSection (&__mingwthr_cs);
95 return 0;
96 }
97
98 static void
__mingwthr_run_key_dtors(void)99 __mingwthr_run_key_dtors (void)
100 {
101 __mingwthr_key_t volatile *keyp;
102
103 if (__mingwthr_cs_init == 0)
104 return;
105 EnterCriticalSection (&__mingwthr_cs);
106
107 for (keyp = key_dtor_list; keyp; )
108 {
109 LPVOID value = TlsGetValue (keyp->key);
110 if (GetLastError () == ERROR_SUCCESS)
111 {
112 if (value)
113 (*keyp->dtor) (value);
114 }
115 keyp = keyp->next;
116 }
117
118 LeaveCriticalSection (&__mingwthr_cs);
119 }
120
121 WINBOOL
__mingw_TLScallback(HANDLE __UNUSED_PARAM (hDllHandle),DWORD reason,LPVOID __UNUSED_PARAM (reserved))122 __mingw_TLScallback (HANDLE __UNUSED_PARAM(hDllHandle),
123 DWORD reason,
124 LPVOID __UNUSED_PARAM(reserved))
125 {
126 switch (reason)
127 {
128 case DLL_PROCESS_ATTACH:
129 if (__mingwthr_cs_init == 0)
130 InitializeCriticalSection (&__mingwthr_cs);
131 __mingwthr_cs_init = 1;
132 break;
133 case DLL_PROCESS_DETACH:
134 __mingwthr_run_key_dtors();
135 if (__mingwthr_cs_init == 1)
136 {
137 __mingwthr_key_t volatile *keyp, *t;
138 for (keyp = key_dtor_list; keyp; )
139 {
140 t = keyp->next;
141 free((void *)keyp);
142 keyp = t;
143 }
144 key_dtor_list = NULL;
145 __mingwthr_cs_init = 0;
146 DeleteCriticalSection (&__mingwthr_cs);
147 }
148 break;
149 case DLL_THREAD_ATTACH:
150 _fpreset();
151 break;
152 case DLL_THREAD_DETACH:
153 __mingwthr_run_key_dtors();
154 break;
155 }
156 return TRUE;
157 }
158
159