4 * Implement Mingw thread-support DLL .
6 * This file is used iff the following conditions are met:
7 * - gcc uses -mthreads option
8 * - user code uses C++ exceptions
10 * The sole job of the Mingw thread support DLL (MingwThr) is to catch
11 * all the dying threads and clean up the data allocated in the TLSs
12 * for exception contexts during C++ EH. Posix threads have key dtors,
13 * but win32 TLS keys do not, hence the magic. Without this, there's at
14 * least `6 * sizeof (void*)' bytes leaks for each catch/throw in each
15 * thread. The only public interface is __mingwthr_key_dtor().
17 * Created by Mumit Khan <khan@nanotech.wisc.edu>
21 #define WIN32_LEAN_AND_MEAN
23 #undef WIN32_LEAN_AND_MEAN
26 /* To protect the thread/key association data structure modifications. */
27 CRITICAL_SECTION __mingwthr_cs;
29 typedef struct __mingwthr_key __mingwthr_key_t;
31 /* The list of threads active with key/dtor pairs. */
32 struct __mingwthr_key {
34 void (*dtor) (void *);
35 __mingwthr_key_t *next;
39 static __mingwthr_key_t *key_dtor_list;
44 * Add key/dtor association for this thread. If the thread entry does not
45 * exist, create a new one and add to the head of the threads list; add
46 * the new assoc at the head of the keys list.
51 ___mingwthr_add_key_dtor ( DWORD key, void (*dtor) (void *))
53 __mingwthr_key_t *new_key;
55 new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
62 EnterCriticalSection (&__mingwthr_cs);
64 new_key->next = key_dtor_list;
65 key_dtor_list = new_key;
67 LeaveCriticalSection (&__mingwthr_cs);
70 printf ("%s: allocating: (%ld, %x)\n",
71 __FUNCTION__, key, dtor);
78 ___mingwthr_remove_key_dtor ( DWORD key )
80 __mingwthr_key_t *prev_key;
81 __mingwthr_key_t *cur_key;
83 EnterCriticalSection (&__mingwthr_cs);
86 cur_key = key_dtor_list;
88 while( cur_key != NULL )
90 if( cur_key->key == key )
92 // take key/dtor out of list
93 if( prev_key == NULL )
95 key_dtor_list = cur_key->next;
99 prev_key->next = cur_key->next;
103 printf ("%s: removing: (%ld)\n",
112 cur_key = cur_key->next;
115 LeaveCriticalSection (&__mingwthr_cs);
121 * __mingwthr_run_key_dtors (void):
123 * Callback from DllMain when thread detaches to clean up the key
126 * Note that this does not delete the key itself, but just runs
127 * the dtor if the current value are both non-NULL. Note that the
128 * keys with NULL dtors are not added by __mingwthr_key_dtor, the
129 * only public interface, so we don't need to check.
134 __mingwthr_run_key_dtors (void)
136 __mingwthr_key_t *keyp;
139 printf ("%s: Entering Thread id %ld\n", __FUNCTION__, GetCurrentThreadId() );
142 EnterCriticalSection (&__mingwthr_cs);
144 for (keyp = key_dtor_list; keyp; )
146 LPVOID value = TlsGetValue (keyp->key);
147 if (GetLastError () == ERROR_SUCCESS)
150 printf (" (%ld, %x)\n", keyp->key, keyp->dtor);
153 (*keyp->dtor) (value);
158 printf (" TlsGetValue FAILED (%ld, %x)\n",
159 keyp->key, keyp->dtor);
165 LeaveCriticalSection (&__mingwthr_cs);
168 printf ("%s: Exiting Thread id %ld\n", __FUNCTION__, GetCurrentThreadId() );
173 * __mingwthr_register_key_dtor (DWORD key, void (*dtor) (void *))
175 * Public interface called by C++ exception handling mechanism in
176 * libgcc (cf: __gthread_key_create).
180 __declspec(dllexport)
182 __mingwthr_key_dtor (DWORD key, void (*dtor) (void *))
186 return ___mingwthr_add_key_dtor (key, dtor);
192 __declspec(dllexport)
194 __mingwthr_remove_key_dtor (DWORD key )
196 return ___mingwthr_remove_key_dtor ( key );