OSDN Git Service

Insert removed author attribution.
[mingw/mingw-org-wsl.git] / src / libcrt / crt / mthr.c
1 /**
2  * @file mthr.c
3  * @copy 2012 MinGW.org project
4  *
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:
11  * 
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
14  * Software.
15  * 
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.
23  */
24
25 /* @FIXME - Is this used by current GCC? */
26
27 /*
28  * Created by Mumit Khan  <khan@nanotech.wisc.edu>
29  *
30  * Implement Mingw thread-support DLL .
31  *
32  * This file is used iff the following conditions are met:
33  *  - gcc uses -mthreads option 
34  *  - user code uses C++ exceptions
35  *
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(). 
42  */
43
44 #define WIN32_LEAN_AND_MEAN
45 #include <windows.h>
46 #undef WIN32_LEAN_AND_MEAN
47 #include <stdlib.h>
48
49 /* To protect the thread/key association data structure modifications. */
50 CRITICAL_SECTION __mingwthr_cs;
51
52 typedef struct __mingwthr_key __mingwthr_key_t;
53
54 /* The list of threads active with key/dtor pairs. */
55 struct __mingwthr_key {
56   DWORD key;
57   void (*dtor) (void *);
58   __mingwthr_key_t *next;
59 };
60
61
62 static __mingwthr_key_t *key_dtor_list;
63
64 /*
65  * __mingwthr_key_add:
66  *
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. 
70  *
71  */
72
73 static int
74 ___mingwthr_add_key_dtor ( DWORD key, void (*dtor) (void *))
75 {
76   __mingwthr_key_t *new_key;
77
78   new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
79   if (new_key == NULL)
80     return -1;
81   
82   new_key->key = key;
83   new_key->dtor = dtor;
84
85   EnterCriticalSection (&__mingwthr_cs);
86
87   new_key->next = key_dtor_list;
88   key_dtor_list = new_key;
89
90   LeaveCriticalSection (&__mingwthr_cs);
91
92 #ifdef DEBUG
93   printf ("%s: allocating: (%ld, %x)\n", 
94           __FUNCTION__, key, dtor);
95 #endif
96
97   return 0;
98 }
99
100 static int
101 ___mingwthr_remove_key_dtor ( DWORD key )
102 {
103   __mingwthr_key_t *prev_key;
104   __mingwthr_key_t *cur_key;
105
106   EnterCriticalSection (&__mingwthr_cs);
107
108   prev_key = NULL;
109   cur_key = key_dtor_list;
110
111   while( cur_key != NULL )
112   {
113      if( cur_key->key == key )
114      {
115 // take key/dtor out of list
116         if( prev_key == NULL )
117         {
118            key_dtor_list = cur_key->next;
119         }
120         else
121         {
122            prev_key->next = cur_key->next;
123         }
124
125 #ifdef DEBUG
126         printf ("%s: removing: (%ld)\n", 
127                 __FUNCTION__, key );
128 #endif
129
130         free( cur_key );
131         break;
132      }
133
134      prev_key = cur_key;
135      cur_key = cur_key->next;
136   }
137
138   LeaveCriticalSection (&__mingwthr_cs);
139
140   return 0;
141 }
142
143 /*
144  * __mingwthr_run_key_dtors (void):
145  *
146  * Callback from DllMain when thread detaches to clean up the key
147  * storage. 
148  *
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. 
153  *
154  */
155
156 void
157 __mingwthr_run_key_dtors (void)
158 {
159   __mingwthr_key_t *keyp;
160
161 #ifdef DEBUG
162   printf ("%s: Entering Thread id %ld\n", __FUNCTION__, GetCurrentThreadId() );
163 #endif
164
165   EnterCriticalSection (&__mingwthr_cs);
166
167   for (keyp = key_dtor_list; keyp; )
168   {
169      LPVOID value = TlsGetValue (keyp->key);
170      if (GetLastError () == ERROR_SUCCESS)
171      {
172 #ifdef DEBUG
173         printf ("   (%ld, %x)\n", keyp->key, keyp->dtor);
174 #endif
175         if (value)
176            (*keyp->dtor) (value);
177      }
178 #ifdef DEBUG
179      else
180      {
181         printf ("   TlsGetValue FAILED  (%ld, %x)\n", 
182                 keyp->key, keyp->dtor);
183      }
184 #endif
185      keyp = keyp->next;
186   }
187   
188   LeaveCriticalSection (&__mingwthr_cs);
189
190 #ifdef DEBUG
191   printf ("%s: Exiting Thread id %ld\n", __FUNCTION__, GetCurrentThreadId() );
192 #endif
193 }
194   
195 /*
196  * __mingwthr_register_key_dtor (DWORD key, void (*dtor) (void *))
197  *
198  * Public interface called by C++ exception handling mechanism in
199  * libgcc (cf: __gthread_key_create).
200  *
201  */
202
203 __declspec(dllexport)
204 int
205 __mingwthr_key_dtor (DWORD key, void (*dtor) (void *))
206 {
207   if (dtor)
208     {
209       return ___mingwthr_add_key_dtor (key, dtor);
210     }
211
212   return 0;
213 }
214
215 __declspec(dllexport)
216 int
217 __mingwthr_remove_key_dtor (DWORD key )
218 {
219    return ___mingwthr_remove_key_dtor ( key );
220 }