Welcome to mirror list, hosted at ThFree Co, Russian Federation.

tlsthrd.c « mingw « winsup - cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: a3758076d147997a9a7c014c0d18091ae47cd59a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
 * This file has no copyright assigned and is placed in the Public Domain.
 * This file is part of the w64 mingw-runtime package.
 * No warranty is given; refer to the file DISCLAIMER within this package.
 *
 * Written by Kai Tietz  <kai.tietz@onevision.com>
 *
 * This file is used by if gcc is built with --enable-threads=win32.
 *
 * Based on version created by Mumit Khan  <khan@nanotech.wisc.edu>
 *
 */

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <stdlib.h>

WINBOOL __mingw_TLScallback (HANDLE hDllHandle, DWORD reason, LPVOID reserved);
int ___w64_mingwthr_remove_key_dtor (DWORD key);
int ___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *));

/* To protect the thread/key association data structure modifications. */
static CRITICAL_SECTION __mingwthr_cs;
static volatile int __mingwthr_cs_init = 0;

typedef struct __mingwthr_key __mingwthr_key_t;

/* The list of threads active with key/dtor pairs. */
struct __mingwthr_key {
  DWORD key;
  void (*dtor)(void *);
  __mingwthr_key_t volatile *next;
};


static __mingwthr_key_t volatile *key_dtor_list;

int
___w64_mingwthr_add_key_dtor (DWORD key, void (*dtor)(void *))
{
  __mingwthr_key_t *new_key;

  if (__mingwthr_cs_init == 0)
    return 0;
  new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
  if (new_key == NULL)
    return -1;

  new_key->key = key;
  new_key->dtor = dtor;

  EnterCriticalSection (&__mingwthr_cs);

  new_key->next = key_dtor_list;
  key_dtor_list = new_key;

  LeaveCriticalSection (&__mingwthr_cs);
  return 0;
}

int
___w64_mingwthr_remove_key_dtor (DWORD key)
{
  __mingwthr_key_t volatile *prev_key;
  __mingwthr_key_t volatile *cur_key;

  if (__mingwthr_cs_init == 0)
    return 0;

  EnterCriticalSection (&__mingwthr_cs);

  prev_key = NULL;
  cur_key = key_dtor_list;

  while (cur_key != NULL)
    {
      if ( cur_key->key == key)
        {
          if (prev_key == NULL)
            key_dtor_list = cur_key->next;
          else
            prev_key->next = cur_key->next;

          free ((void*)cur_key);
          break;
        }
      prev_key = cur_key;
      cur_key = cur_key->next;
    }

  LeaveCriticalSection (&__mingwthr_cs);
  return 0;
}

static void
__mingwthr_run_key_dtors (void)
{
  __mingwthr_key_t volatile *keyp;

  if (__mingwthr_cs_init == 0)
    return;
  EnterCriticalSection (&__mingwthr_cs);

  for (keyp = key_dtor_list; keyp; )
    {
      LPVOID value = TlsGetValue (keyp->key);
      if (GetLastError () == ERROR_SUCCESS)
        {
          if (value)
            (*keyp->dtor) (value);
        }
      keyp = keyp->next;
    }

  LeaveCriticalSection (&__mingwthr_cs);
}

WINBOOL
__mingw_TLScallback (HANDLE hDllHandle __attribute__ ((__unused__)),
		     DWORD reason,
		     LPVOID reserved __attribute__ ((__unused__)))
{
  switch (reason)
    {
    case DLL_PROCESS_ATTACH:
      if (__mingwthr_cs_init == 0)
        InitializeCriticalSection (&__mingwthr_cs);
      __mingwthr_cs_init = 1;
      break;
    case DLL_PROCESS_DETACH:
      __mingwthr_run_key_dtors();
      if (__mingwthr_cs_init == 1)
        {
          __mingwthr_cs_init = 0;
          DeleteCriticalSection (&__mingwthr_cs);
        }
      break;
    case DLL_THREAD_ATTACH:
      break;
    case DLL_THREAD_DETACH:
      __mingwthr_run_key_dtors();
      break;
    }
  return TRUE;
}