OSDN Git Service

Insert removed author attribution.
[mingw/mingw-org-wsl.git] / src / libcrt / crt / tlsthrd.c
1 /**
2  * @file tlsthrd.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 /*
26  * This file is used by if gcc is built with --enable-threads=win32.
27  *
28  * Written by Kai Tietz  <kai.tietz@onevision.com>
29  * Based on version created by Mumit Khan  <khan@nanotech.wisc.edu>
30  */
31
32 #ifndef WIN32_LEAN_AND_MEAN
33 #define WIN32_LEAN_AND_MEAN
34 #endif
35 #include <windows.h>
36 #include <stdlib.h>
37
38 WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
39 int ___w64_mingwthr_remove_key_dtor (DWORD key);
40 int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
41
42 /* To protect the thread/key association data structure modifications. */
43 static CRITICAL_SECTION __mingwthr_cs;
44 static volatile int __mingwthr_cs_init = 0;
45
46 typedef struct __mingwthr_key __mingwthr_key_t;
47
48 /* The list of threads active with key/dtor pairs. */
49 struct __mingwthr_key {
50   DWORD key;
51   void (*dtor)(void *);
52   __mingwthr_key_t volatile *next;
53 };
54
55
56 static __mingwthr_key_t volatile *key_dtor_list;
57
58 int
59 ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *))
60 {
61   __mingwthr_key_t *new_key;
62
63   if (__mingwthr_cs_init == 0)
64     return 0;
65   new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
66   if (new_key == NULL)
67     return -1;
68
69   new_key->key = key;
70   new_key->dtor = dtor;
71
72   EnterCriticalSection (&__mingwthr_cs);
73
74   new_key->next = key_dtor_list;
75   key_dtor_list = new_key;
76
77   LeaveCriticalSection (&__mingwthr_cs);
78   return 0;
79 }
80
81 int
82 ___w64_mingwthr_remove_key_dtor (DWORD key)
83 {
84   __mingwthr_key_t volatile *prev_key;
85   __mingwthr_key_t volatile *cur_key;
86
87   if (__mingwthr_cs_init == 0)
88     return 0;
89
90   EnterCriticalSection (&__mingwthr_cs);
91
92   prev_key = NULL;
93   cur_key = key_dtor_list;
94
95   while (cur_key != NULL)
96     {
97       if ( cur_key->key == key)
98         {
99           if (prev_key == NULL)
100             key_dtor_list = cur_key->next;
101           else
102             prev_key->next = cur_key->next;
103
104           free ((void*)cur_key);
105           break;
106         }
107       prev_key = cur_key;
108       cur_key = cur_key->next;
109     }
110
111   LeaveCriticalSection (&__mingwthr_cs);
112   return 0;
113 }
114
115 static void
116 __mingwthr_run_key_dtors (void)
117 {
118   __mingwthr_key_t volatile *keyp;
119
120   if (__mingwthr_cs_init == 0)
121     return;
122   EnterCriticalSection (&__mingwthr_cs);
123
124   for (keyp = key_dtor_list; keyp; )
125     {
126       LPVOID value = TlsGetValue (keyp->key);
127       if (GetLastError () == ERROR_SUCCESS)
128         {
129           if (value)
130             (*keyp->dtor) (value);
131         }
132       keyp = keyp->next;
133     }
134
135   LeaveCriticalSection (&__mingwthr_cs);
136 }
137
138 WINBOOL
139 __mingw_TLScallback (HANDLE hDllHandle __attribute__ ((__unused__)),
140                      DWORD reason,
141                      LPVOID reserved __attribute__ ((__unused__)))
142 {
143   switch (reason)
144     {
145     case DLL_PROCESS_ATTACH:
146       if (__mingwthr_cs_init == 0)
147         InitializeCriticalSection (&__mingwthr_cs);
148       __mingwthr_cs_init = 1;
149       break;
150     case DLL_PROCESS_DETACH:
151       __mingwthr_run_key_dtors();
152       if (__mingwthr_cs_init == 1)
153         {
154           __mingwthr_cs_init = 0;
155           DeleteCriticalSection (&__mingwthr_cs);
156         }
157       break;
158     case DLL_THREAD_ATTACH:
159       break;
160     case DLL_THREAD_DETACH:
161       __mingwthr_run_key_dtors();
162       break;
163     }
164   return TRUE;
165 }