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