• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * This file has no copyright assigned and is placed in the Public Domain.
3  * This file is part of the mingw-w64 runtime package.
4  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5  *
6  * Written by Kai Tietz  <kai.tietz@onevision.com>
7  *
8  * This file is used by if gcc is built with --enable-threads=win32.
9  *
10  * Based on version created by Mumit Khan  <khan@nanotech.wisc.edu>
11  *
12  */
13 
14 #ifndef WIN32_LEAN_AND_MEAN
15 #define WIN32_LEAN_AND_MEAN
16 #endif
17 #include <windows.h>
18 #include <stdlib.h>
19 
20 extern void __cdecl __MINGW_NOTHROW _fpreset (void);
21 WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
22 int ___w64_mingwthr_remove_key_dtor (DWORD key);
23 int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
24 
25 /* To protect the thread/key association data structure modifications. */
26 static CRITICAL_SECTION __mingwthr_cs;
27 static volatile int __mingwthr_cs_init = 0;
28 
29 typedef struct __mingwthr_key __mingwthr_key_t;
30 
31 /* The list of threads active with key/dtor pairs. */
32 struct __mingwthr_key {
33   DWORD key;
34   void (*dtor)(void *);
35   __mingwthr_key_t volatile *next;
36 };
37 
38 
39 static __mingwthr_key_t volatile *key_dtor_list;
40 
41 int
___w64_mingwthr_add_key_dtor(DWORD key,void (* dtor)(void *))42 ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *))
43 {
44   __mingwthr_key_t *new_key;
45 
46   if (__mingwthr_cs_init == 0)
47     return 0;
48   new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
49   if (new_key == NULL)
50     return -1;
51 
52   new_key->key = key;
53   new_key->dtor = dtor;
54 
55   EnterCriticalSection (&__mingwthr_cs);
56 
57   new_key->next = key_dtor_list;
58   key_dtor_list = new_key;
59 
60   LeaveCriticalSection (&__mingwthr_cs);
61   return 0;
62 }
63 
64 int
___w64_mingwthr_remove_key_dtor(DWORD key)65 ___w64_mingwthr_remove_key_dtor (DWORD key)
66 {
67   __mingwthr_key_t volatile *prev_key;
68   __mingwthr_key_t volatile *cur_key;
69 
70   if (__mingwthr_cs_init == 0)
71     return 0;
72 
73   EnterCriticalSection (&__mingwthr_cs);
74 
75   prev_key = NULL;
76   cur_key = key_dtor_list;
77 
78   while (cur_key != NULL)
79     {
80       if ( cur_key->key == key)
81         {
82           if (prev_key == NULL)
83             key_dtor_list = cur_key->next;
84           else
85             prev_key->next = cur_key->next;
86 
87           free ((void*)cur_key);
88           break;
89         }
90       prev_key = cur_key;
91       cur_key = cur_key->next;
92     }
93 
94   LeaveCriticalSection (&__mingwthr_cs);
95   return 0;
96 }
97 
98 static void
__mingwthr_run_key_dtors(void)99 __mingwthr_run_key_dtors (void)
100 {
101   __mingwthr_key_t volatile *keyp;
102 
103   if (__mingwthr_cs_init == 0)
104     return;
105   EnterCriticalSection (&__mingwthr_cs);
106 
107   for (keyp = key_dtor_list; keyp; )
108     {
109       LPVOID value = TlsGetValue (keyp->key);
110       if (GetLastError () == ERROR_SUCCESS)
111         {
112           if (value)
113             (*keyp->dtor) (value);
114         }
115       keyp = keyp->next;
116     }
117 
118   LeaveCriticalSection (&__mingwthr_cs);
119 }
120 
121 WINBOOL
__mingw_TLScallback(HANDLE __UNUSED_PARAM (hDllHandle),DWORD reason,LPVOID __UNUSED_PARAM (reserved))122 __mingw_TLScallback (HANDLE __UNUSED_PARAM(hDllHandle),
123 		     DWORD reason,
124 		     LPVOID __UNUSED_PARAM(reserved))
125 {
126   switch (reason)
127     {
128     case DLL_PROCESS_ATTACH:
129       if (__mingwthr_cs_init == 0)
130         InitializeCriticalSection (&__mingwthr_cs);
131       __mingwthr_cs_init = 1;
132       break;
133     case DLL_PROCESS_DETACH:
134       __mingwthr_run_key_dtors();
135       if (__mingwthr_cs_init == 1)
136         {
137           __mingwthr_key_t volatile *keyp, *t;
138           for (keyp = key_dtor_list; keyp; )
139           {
140             t = keyp->next;
141             free((void *)keyp);
142             keyp = t;
143           }
144           key_dtor_list = NULL;
145           __mingwthr_cs_init = 0;
146           DeleteCriticalSection (&__mingwthr_cs);
147         }
148       break;
149     case DLL_THREAD_ATTACH:
150       _fpreset();
151       break;
152     case DLL_THREAD_DETACH:
153       __mingwthr_run_key_dtors();
154       break;
155     }
156   return TRUE;
157 }
158 
159