3 * @copy 2012 MinGW.org project
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 /* @FIXME - Is this used by current GCC? */
28 * Created by Mumit Khan <khan@nanotech.wisc.edu>
30 * Implement Mingw thread-support DLL .
32 * This file is used iff the following conditions are met:
33 * - gcc uses -mthreads option
34 * - user code uses C++ exceptions
36 * The sole job of the Mingw thread support DLL (MingwThr) is to catch
37 * all the dying threads and clean up the data allocated in the TLSs
38 * for exception contexts during C++ EH. Posix threads have key dtors,
39 * but win32 TLS keys do not, hence the magic. Without this, there's at
40 * least `6 * sizeof (void*)' bytes leaks for each catch/throw in each
41 * thread. The only public interface is __mingwthr_key_dtor().
44 #define WIN32_LEAN_AND_MEAN
46 #undef WIN32_LEAN_AND_MEAN
49 /* To protect the thread/key association data structure modifications. */
50 CRITICAL_SECTION __mingwthr_cs;
52 typedef struct __mingwthr_key __mingwthr_key_t;
54 /* The list of threads active with key/dtor pairs. */
55 struct __mingwthr_key {
57 void (*dtor) (void *);
58 __mingwthr_key_t *next;
62 static __mingwthr_key_t *key_dtor_list;
67 * Add key/dtor association for this thread. If the thread entry does not
68 * exist, create a new one and add to the head of the threads list; add
69 * the new assoc at the head of the keys list.
74 ___mingwthr_add_key_dtor ( DWORD key, void (*dtor) (void *))
76 __mingwthr_key_t *new_key;
78 new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
85 EnterCriticalSection (&__mingwthr_cs);
87 new_key->next = key_dtor_list;
88 key_dtor_list = new_key;
90 LeaveCriticalSection (&__mingwthr_cs);
93 printf ("%s: allocating: (%ld, %x)\n",
94 __FUNCTION__, key, dtor);
101 ___mingwthr_remove_key_dtor ( DWORD key )
103 __mingwthr_key_t *prev_key;
104 __mingwthr_key_t *cur_key;
106 EnterCriticalSection (&__mingwthr_cs);
109 cur_key = key_dtor_list;
111 while( cur_key != NULL )
113 if( cur_key->key == key )
115 // take key/dtor out of list
116 if( prev_key == NULL )
118 key_dtor_list = cur_key->next;
122 prev_key->next = cur_key->next;
126 printf ("%s: removing: (%ld)\n",
135 cur_key = cur_key->next;
138 LeaveCriticalSection (&__mingwthr_cs);
144 * __mingwthr_run_key_dtors (void):
146 * Callback from DllMain when thread detaches to clean up the key
149 * Note that this does not delete the key itself, but just runs
150 * the dtor if the current value are both non-NULL. Note that the
151 * keys with NULL dtors are not added by __mingwthr_key_dtor, the
152 * only public interface, so we don't need to check.
157 __mingwthr_run_key_dtors (void)
159 __mingwthr_key_t *keyp;
162 printf ("%s: Entering Thread id %ld\n", __FUNCTION__, GetCurrentThreadId() );
165 EnterCriticalSection (&__mingwthr_cs);
167 for (keyp = key_dtor_list; keyp; )
169 LPVOID value = TlsGetValue (keyp->key);
170 if (GetLastError () == ERROR_SUCCESS)
173 printf (" (%ld, %x)\n", keyp->key, keyp->dtor);
176 (*keyp->dtor) (value);
181 printf (" TlsGetValue FAILED (%ld, %x)\n",
182 keyp->key, keyp->dtor);
188 LeaveCriticalSection (&__mingwthr_cs);
191 printf ("%s: Exiting Thread id %ld\n", __FUNCTION__, GetCurrentThreadId() );
196 * __mingwthr_register_key_dtor (DWORD key, void (*dtor) (void *))
198 * Public interface called by C++ exception handling mechanism in
199 * libgcc (cf: __gthread_key_create).
203 __declspec(dllexport)
205 __mingwthr_key_dtor (DWORD key, void (*dtor) (void *))
209 return ___mingwthr_add_key_dtor (key, dtor);
215 __declspec(dllexport)
217 __mingwthr_remove_key_dtor (DWORD key )
219 return ___mingwthr_remove_key_dtor ( key );