OSDN Git Service

2009-05-30 Kai Tietz <kai.tietz@onevision.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / mingw-tls.c
1 /* Catch and clean up data allocated in TLS.
2    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3    2009 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20
21 /* This part is based on the implementation of Mumit Khan  <khan@nanotech.wisc.edu>
22  * provided to mingw under public domain and ported for libgcc by Kai Tietz.
23  */
24
25 #define WIN32_LEAN_AND_MEAN
26 #include <windows.h>
27 #undef WIN32_LEAN_AND_MEAN
28 #include <stdlib.h>
29
30 /* The list of threads active with key/dtor pairs. */
31 typedef struct __mingwthr_key {
32   DWORD key;
33   void (*dtor) (void *);
34   struct __mingwthr_key *next;
35 } __mingwthr_key_t;
36
37 #if defined(_WIN32) && !defined(__CYGWIN__)
38
39 /* Possibly we could define this here for none MT too and avoid use of
40    mingwthrd.a at all, but well ...  */
41 #ifdef SHARED
42 __declspec(dllexport)
43 int _CRT_MT = 1;
44 #else
45 #if 0
46 int _CRT_MT = 0;
47 #endif
48 #endif
49
50 /* Static functions for libgcc.  */
51 #ifndef SHARED
52
53 int __mingwthr_key_dtor (DWORD,void (*dtor)(void *));
54 int __mingwthr_remove_key_dtor (DWORD);
55
56
57 int
58 __mingwthr_key_dtor (DWORD key __attribute__ ((__unused__)),
59                      void (*dtor) (void *) __attribute__ ((__unused__)))
60 {
61   return 0;
62 }
63
64 int
65 __mingwthr_remove_key_dtor (DWORD key __attribute__ ((__unused__)))
66 {
67   return 0;
68 }
69
70 #else
71 /* Shared functions for libgcc.  */
72
73 /* Prototypes.  */
74 __declspec(dllexport) int __mingwthr_key_dtor (DWORD key, void (*) (void *));
75 __declspec(dllexport) int __mingwthr_remove_key_dtor (DWORD);
76 BOOL APIENTRY DllMain (HANDLE, DWORD, LPVOID);
77
78
79 /* To protect the thread/key association data structure modifications. */
80 static CRITICAL_SECTION __mingwthr_cs;
81 static __mingwthr_key_t *key_dtor_list;
82
83 /*
84  * __mingwthr_key_add:
85  *
86  * Add key/dtor association for this thread. If the thread entry does not
87  * exist, create a new one and add to the head of the threads list; add
88  * the new assoc at the head of the keys list. 
89  *
90  */
91
92 static int
93 ___mingwthr_add_key_dtor (DWORD key, void (*dtor) (void *))
94 {
95   __mingwthr_key_t *new_key;
96
97   new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
98   if (new_key == NULL)
99     return -1;
100   
101   new_key->key = key;
102   new_key->dtor = dtor;
103
104   EnterCriticalSection (&__mingwthr_cs);
105
106   new_key->next = key_dtor_list;
107   key_dtor_list = new_key;
108
109   LeaveCriticalSection (&__mingwthr_cs);
110
111   return 0;
112 }
113
114 static int
115 ___mingwthr_remove_key_dtor (DWORD key)
116 {
117   __mingwthr_key_t *prev_key;
118   __mingwthr_key_t *cur_key;
119
120   EnterCriticalSection (&__mingwthr_cs);
121
122   prev_key = NULL;
123   cur_key = key_dtor_list;
124
125   while (cur_key != NULL)
126     {
127        if( cur_key->key == key )
128          {
129             /* take key/dtor out of list */
130             if (prev_key == NULL)
131               key_dtor_list = cur_key->next;
132             else
133               prev_key->next = cur_key->next;
134
135             free (cur_key);
136             break;
137          }
138
139        prev_key = cur_key;
140        cur_key = cur_key->next;
141     }
142
143   LeaveCriticalSection (&__mingwthr_cs);
144
145   return 0;
146 }
147
148 /*
149  * __mingwthr_run_key_dtors (void):
150  *
151  * Callback from DllMain when thread detaches to clean up the key
152  * storage. 
153  *
154  * Note that this does not delete the key itself, but just runs
155  * the dtor if the current value are both non-NULL. Note that the
156  * keys with NULL dtors are not added by __mingwthr_key_dtor, the
157  * only public interface, so we don't need to check. 
158  *
159  */
160
161 static void
162 __mingwthr_run_key_dtors (void)
163 {
164   __mingwthr_key_t *keyp;
165
166   EnterCriticalSection (&__mingwthr_cs);
167
168   for (keyp = key_dtor_list; keyp; )
169     {
170        LPVOID value = TlsGetValue (keyp->key);
171        if (GetLastError () == ERROR_SUCCESS)
172          {
173             if (value)
174                (*keyp->dtor) (value);
175          }
176        keyp = keyp->next;
177     }
178   
179   LeaveCriticalSection (&__mingwthr_cs);
180 }
181
182 /*
183  * __mingwthr_register_key_dtor (DWORD key, void (*dtor) (void *))
184  *
185  * Public interface called by C++ exception handling mechanism in
186  * libgcc (cf: __gthread_key_create).
187  *
188  */
189
190 __declspec(dllexport)
191 int
192 __mingwthr_key_dtor (DWORD key, void (*dtor) (void *))
193 {
194   if (dtor)
195     return ___mingwthr_add_key_dtor (key, dtor);
196
197   return 0;
198 }
199
200 __declspec(dllexport)
201 int
202 __mingwthr_remove_key_dtor (DWORD key)
203 {
204    return ___mingwthr_remove_key_dtor (key);
205 }
206
207 BOOL APIENTRY
208 DllMain (HANDLE hDllHandle __attribute__ ((__unused__)),
209          DWORD reason /* Reason this function is being called. */,
210          LPVOID reserved __attribute__ ((__unused__)))
211 {
212   switch (reason)
213     {
214     case DLL_PROCESS_ATTACH:
215        InitializeCriticalSection (&__mingwthr_cs);
216        break;
217
218     case DLL_PROCESS_DETACH:
219       __mingwthr_run_key_dtors ();
220        DeleteCriticalSection (&__mingwthr_cs);
221       break;
222
223     case DLL_THREAD_ATTACH:
224       break;
225
226     case DLL_THREAD_DETACH:
227       __mingwthr_run_key_dtors ();
228       break;
229     }
230   return TRUE;
231 }
232 #endif
233 #endif