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