This source file includes following definitions.
- glwthread_tls_get
- glwthread_tls_set
- dtor_table_initialize
- dtor_table_ensure_initialized
- dtor_table_shrink_used
- glwthread_tls_process_destructors
- glwthread_tls_key_create
- glwthread_tls_key_delete
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21
22 #include "windows-tls.h"
23
24 #include <errno.h>
25 #include <limits.h>
26 #include <stdlib.h>
27
28 #include "windows-once.h"
29
30 void *
31 glwthread_tls_get (glwthread_tls_key_t key)
32 {
33 return TlsGetValue (key);
34 }
35
36 int
37 glwthread_tls_set (glwthread_tls_key_t key, void *value)
38 {
39 if (!TlsSetValue (key, value))
40 return EINVAL;
41 return 0;
42 }
43
44
45
46 static glwthread_once_t dtor_table_init_once = GLWTHREAD_ONCE_INIT;
47
48 static CRITICAL_SECTION dtor_table_lock;
49
50 struct dtor { glwthread_tls_key_t key; void (*destructor) (void *); };
51
52
53 static struct dtor *dtor_table;
54
55 static unsigned int dtors_count;
56
57 static unsigned int dtors_used;
58
59 static unsigned int dtors_allocated;
60
61
62
63 static unsigned int dtor_processing_threads;
64
65 static void
66 dtor_table_initialize (void)
67 {
68 InitializeCriticalSection (&dtor_table_lock);
69
70 }
71
72 static void
73 dtor_table_ensure_initialized (void)
74 {
75 glwthread_once (&dtor_table_init_once, dtor_table_initialize);
76 }
77
78
79
80 static void
81 dtor_table_shrink_used (void)
82 {
83 unsigned int i = 0;
84 unsigned int j = dtors_used;
85
86 for (;;)
87 {
88 BOOL i_found = FALSE;
89 BOOL j_found = FALSE;
90
91 for (; i < dtors_count;)
92 {
93 if (dtor_table[i].destructor == NULL)
94 {
95 i_found = TRUE;
96 break;
97 }
98 i++;
99 }
100
101
102 for (; j > dtors_count;)
103 {
104 j--;
105 if (dtor_table[j].destructor != NULL)
106 {
107 j_found = TRUE;
108 break;
109 }
110 }
111
112 if (i_found != j_found)
113
114 abort ();
115
116 if (!i_found)
117 break;
118
119
120 dtor_table[i] = dtor_table[j];
121
122 i++;
123 }
124
125 dtors_used = dtors_count;
126 }
127
128 void
129 glwthread_tls_process_destructors (void)
130 {
131 unsigned int repeat;
132
133 dtor_table_ensure_initialized ();
134
135 EnterCriticalSection (&dtor_table_lock);
136 if (dtor_processing_threads == 0)
137 {
138
139 if (dtors_used > dtors_count)
140 dtor_table_shrink_used ();
141 }
142 dtor_processing_threads++;
143
144 for (repeat = GLWTHREAD_DESTRUCTOR_ITERATIONS; repeat > 0; repeat--)
145 {
146 unsigned int destructors_run = 0;
147
148
149
150
151
152
153
154
155
156
157
158
159 unsigned int i_limit = dtors_used;
160 unsigned int i;
161
162 for (i = 0; i < i_limit; i++)
163 {
164 struct dtor current = dtor_table[i];
165 if (current.destructor != NULL)
166 {
167
168 void *current_value = glwthread_tls_get (current.key);
169 if (current_value != NULL)
170 {
171
172 glwthread_tls_set (current.key, NULL);
173 LeaveCriticalSection (&dtor_table_lock);
174 current.destructor (current_value);
175 EnterCriticalSection (&dtor_table_lock);
176 destructors_run++;
177 }
178 }
179 }
180
181
182
183 if (destructors_run == 0)
184 break;
185 }
186
187 dtor_processing_threads--;
188 LeaveCriticalSection (&dtor_table_lock);
189 }
190
191 int
192 glwthread_tls_key_create (glwthread_tls_key_t *keyp, void (*destructor) (void *))
193 {
194 if (destructor != NULL)
195 {
196 dtor_table_ensure_initialized ();
197
198 EnterCriticalSection (&dtor_table_lock);
199 if (dtor_processing_threads == 0)
200 {
201
202 if (dtors_used > dtors_count)
203 dtor_table_shrink_used ();
204 }
205
206 while (dtors_used == dtors_allocated)
207 {
208
209 unsigned int new_allocated = 2 * dtors_allocated + 1;
210 if (new_allocated < 7)
211 new_allocated = 7;
212 if (new_allocated <= dtors_allocated)
213 new_allocated = UINT_MAX;
214
215 LeaveCriticalSection (&dtor_table_lock);
216 {
217 struct dtor *new_table =
218 (struct dtor *) malloc (new_allocated * sizeof (struct dtor));
219 if (new_table == NULL)
220 return ENOMEM;
221 EnterCriticalSection (&dtor_table_lock);
222
223 if (dtors_used < new_allocated)
224 {
225 if (dtors_allocated < new_allocated)
226 {
227
228 memcpy (new_table, dtor_table,
229 dtors_used * sizeof (struct dtor));
230 dtor_table = new_table;
231 dtors_allocated = new_allocated;
232 }
233 else
234 {
235
236
237
238 free (new_table);
239 }
240 break;
241 }
242
243
244 free (new_table);
245 }
246 }
247
248 {
249
250 glwthread_tls_key_t key = TlsAlloc ();
251 if (key == (DWORD)-1)
252 {
253 LeaveCriticalSection (&dtor_table_lock);
254 return EAGAIN;
255 }
256
257
258
259
260 dtor_table[dtors_used].key = key;
261 dtor_table[dtors_used].destructor = destructor;
262 dtors_used++;
263 dtors_count++;
264 LeaveCriticalSection (&dtor_table_lock);
265 *keyp = key;
266 }
267 }
268 else
269 {
270
271 glwthread_tls_key_t key = TlsAlloc ();
272 if (key == (DWORD)-1)
273 return EAGAIN;
274 *keyp = key;
275 }
276 return 0;
277 }
278
279 int
280 glwthread_tls_key_delete (glwthread_tls_key_t key)
281 {
282
283
284
285
286
287
288
289 dtor_table_ensure_initialized ();
290
291 EnterCriticalSection (&dtor_table_lock);
292 if (dtor_processing_threads == 0)
293 {
294
295 if (dtors_used > dtors_count)
296 dtor_table_shrink_used ();
297
298
299
300 {
301 unsigned int i_limit = dtors_used;
302 unsigned int i;
303
304 for (i = 0; i < i_limit; i++)
305 if (dtor_table[i].key == key)
306 {
307 if (i < dtors_used - 1)
308
309 dtor_table[i] = dtor_table[dtors_used - 1];
310 dtors_count = dtors_used = dtors_used - 1;
311 break;
312 }
313 }
314 }
315 else
316 {
317
318
319 unsigned int i_limit = dtors_used;
320 unsigned int i;
321
322 for (i = 0; i < i_limit; i++)
323 if (dtor_table[i].destructor != NULL
324 && dtor_table[i].key == key)
325 {
326
327 dtor_table[i].destructor = NULL;
328 dtors_count = dtors_count - 1;
329 break;
330 }
331 }
332 LeaveCriticalSection (&dtor_table_lock);
333
334
335
336 if (!TlsFree (key))
337 return EINVAL;
338 return 0;
339 }