master
  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
 20extern void __cdecl __MINGW_NOTHROW _fpreset (void);
 21WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
 22int ___w64_mingwthr_remove_key_dtor (DWORD key);
 23int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));
 24
 25/* To protect the thread/key association data structure modifications. */
 26static CRITICAL_SECTION __mingwthr_cs;
 27static volatile int __mingwthr_cs_init = 0;
 28
 29typedef struct __mingwthr_key __mingwthr_key_t;
 30
 31/* The list of threads active with key/dtor pairs. */
 32struct __mingwthr_key {
 33  DWORD key;
 34  void (*dtor)(void *);
 35  __mingwthr_key_t volatile *next;
 36};
 37
 38
 39static __mingwthr_key_t volatile *key_dtor_list;
 40
 41int
 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
 64int
 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
 98static 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
121WINBOOL
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