xref: /reactos/sdk/lib/crt/startup/tlsthrd.c (revision b09b5584)
1 /**
2  * This file has no copyright assigned and is placed in the Public Domain.
3  * This file is part of the w64 mingw-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 #include <stdarg.h>
20 #include <windef.h>
21 #include <winbase.h>
22 
23 WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
24 int ___w64_mingwthr_remove_key_dtor (DWORD key);
25 int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
26 
27 /* To protect the thread/key association data structure modifications. */
28 static CRITICAL_SECTION __mingwthr_cs;
29 static volatile int __mingwthr_cs_init = 0;
30 
31 typedef struct __mingwthr_key __mingwthr_key_t;
32 
33 /* The list of threads active with key/dtor pairs. */
34 struct __mingwthr_key {
35   DWORD key;
36   void (*dtor)(void *);
37   __mingwthr_key_t volatile *next;
38 };
39 
40 
41 static __mingwthr_key_t volatile *key_dtor_list;
42 
43 int
44 ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *))
45 {
46   __mingwthr_key_t *new_key;
47 
48   if (__mingwthr_cs_init == 0)
49     return 0;
50   new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
51   if (new_key == NULL)
52     return -1;
53 
54   new_key->key = key;
55   new_key->dtor = dtor;
56 
57   EnterCriticalSection (&__mingwthr_cs);
58 
59   new_key->next = key_dtor_list;
60   key_dtor_list = new_key;
61 
62   LeaveCriticalSection (&__mingwthr_cs);
63   return 0;
64 }
65 
66 int
67 ___w64_mingwthr_remove_key_dtor (DWORD key)
68 {
69   __mingwthr_key_t volatile *prev_key;
70   __mingwthr_key_t volatile *cur_key;
71 
72   if (__mingwthr_cs_init == 0)
73     return 0;
74 
75   EnterCriticalSection (&__mingwthr_cs);
76 
77   prev_key = NULL;
78   cur_key = key_dtor_list;
79 
80   while (cur_key != NULL)
81     {
82       if ( cur_key->key == key)
83         {
84           if (prev_key == NULL)
85             key_dtor_list = cur_key->next;
86           else
87             prev_key->next = cur_key->next;
88 
89           free ((void*)cur_key);
90           break;
91         }
92       prev_key = cur_key;
93       cur_key = cur_key->next;
94     }
95 
96   LeaveCriticalSection (&__mingwthr_cs);
97   return 0;
98 }
99 
100 static void
101 __mingwthr_run_key_dtors (void)
102 {
103   __mingwthr_key_t volatile *keyp;
104 
105   if (__mingwthr_cs_init == 0)
106     return;
107   EnterCriticalSection (&__mingwthr_cs);
108 
109   for (keyp = key_dtor_list; keyp; )
110     {
111       LPVOID value = TlsGetValue (keyp->key);
112       if (GetLastError () == ERROR_SUCCESS)
113         {
114           if (value)
115             (*keyp->dtor) (value);
116         }
117       keyp = keyp->next;
118     }
119 
120   LeaveCriticalSection (&__mingwthr_cs);
121 }
122 
123 WINBOOL
124 __mingw_TLScallback (HANDLE __UNUSED_PARAM(hDllHandle),
125 		     DWORD reason,
126 		     LPVOID __UNUSED_PARAM(reserved))
127 {
128   switch (reason)
129     {
130     case DLL_PROCESS_ATTACH:
131       if (__mingwthr_cs_init == 0)
132         InitializeCriticalSection (&__mingwthr_cs);
133       __mingwthr_cs_init = 1;
134       break;
135     case DLL_PROCESS_DETACH:
136       __mingwthr_run_key_dtors();
137       if (__mingwthr_cs_init == 1)
138         {
139           __mingwthr_cs_init = 0;
140           DeleteCriticalSection (&__mingwthr_cs);
141         }
142       break;
143     case DLL_THREAD_ATTACH:
144       break;
145     case DLL_THREAD_DETACH:
146       __mingwthr_run_key_dtors();
147       break;
148     }
149   return TRUE;
150 }
151 
152