pocxxeci 0.30.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pocxxeci might be problematic. Click here for more details.

Files changed (160) hide show
  1. package/LICENSE +19 -0
  2. package/Makefile +18 -0
  3. package/README.md +52 -0
  4. package/binding.gyp +81 -0
  5. package/index.d.ts +273 -0
  6. package/index.js +45 -0
  7. package/lib/bindings.js +1 -0
  8. package/lib/document.js +122 -0
  9. package/lib/element.js +82 -0
  10. package/lib/sax_parser.js +38 -0
  11. package/package.json +70 -0
  12. package/src/html_document.cc +7 -0
  13. package/src/html_document.h +18 -0
  14. package/src/libxmljs.cc +252 -0
  15. package/src/libxmljs.h +53 -0
  16. package/src/xml_attribute.cc +173 -0
  17. package/src/xml_attribute.h +40 -0
  18. package/src/xml_comment.cc +117 -0
  19. package/src/xml_comment.h +30 -0
  20. package/src/xml_document.cc +810 -0
  21. package/src/xml_document.h +67 -0
  22. package/src/xml_element.cc +565 -0
  23. package/src/xml_element.h +61 -0
  24. package/src/xml_namespace.cc +158 -0
  25. package/src/xml_namespace.h +39 -0
  26. package/src/xml_node.cc +761 -0
  27. package/src/xml_node.h +73 -0
  28. package/src/xml_pi.cc +161 -0
  29. package/src/xml_pi.h +34 -0
  30. package/src/xml_sax_parser.cc +424 -0
  31. package/src/xml_sax_parser.h +73 -0
  32. package/src/xml_syntax_error.cc +66 -0
  33. package/src/xml_syntax_error.h +25 -0
  34. package/src/xml_text.cc +320 -0
  35. package/src/xml_text.h +48 -0
  36. package/src/xml_textwriter.cc +315 -0
  37. package/src/xml_textwriter.h +62 -0
  38. package/src/xml_xpath_context.cc +70 -0
  39. package/src/xml_xpath_context.h +23 -0
  40. package/vendor/libxml/Copyright +23 -0
  41. package/vendor/libxml/DOCBparser.c +305 -0
  42. package/vendor/libxml/HTMLparser.c +7287 -0
  43. package/vendor/libxml/HTMLtree.c +1200 -0
  44. package/vendor/libxml/Makefile +2983 -0
  45. package/vendor/libxml/SAX.c +180 -0
  46. package/vendor/libxml/SAX2.c +3036 -0
  47. package/vendor/libxml/buf.c +1351 -0
  48. package/vendor/libxml/buf.h +72 -0
  49. package/vendor/libxml/c14n.c +2234 -0
  50. package/vendor/libxml/catalog.c +3828 -0
  51. package/vendor/libxml/chvalid.c +336 -0
  52. package/vendor/libxml/config.h +294 -0
  53. package/vendor/libxml/config.h.gch +0 -0
  54. package/vendor/libxml/debugXML.c +3423 -0
  55. package/vendor/libxml/dict.c +1298 -0
  56. package/vendor/libxml/elfgcchack.h +17818 -0
  57. package/vendor/libxml/enc.h +32 -0
  58. package/vendor/libxml/encoding.c +3975 -0
  59. package/vendor/libxml/entities.c +1163 -0
  60. package/vendor/libxml/error.c +998 -0
  61. package/vendor/libxml/globals.c +1126 -0
  62. package/vendor/libxml/hash.c +1146 -0
  63. package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
  64. package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
  65. package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
  66. package/vendor/libxml/include/libxml/Makefile +725 -0
  67. package/vendor/libxml/include/libxml/Makefile.am +54 -0
  68. package/vendor/libxml/include/libxml/Makefile.in +725 -0
  69. package/vendor/libxml/include/libxml/SAX.h +173 -0
  70. package/vendor/libxml/include/libxml/SAX2.h +178 -0
  71. package/vendor/libxml/include/libxml/c14n.h +128 -0
  72. package/vendor/libxml/include/libxml/catalog.h +182 -0
  73. package/vendor/libxml/include/libxml/chvalid.h +230 -0
  74. package/vendor/libxml/include/libxml/debugXML.h +217 -0
  75. package/vendor/libxml/include/libxml/dict.h +79 -0
  76. package/vendor/libxml/include/libxml/encoding.h +245 -0
  77. package/vendor/libxml/include/libxml/entities.h +151 -0
  78. package/vendor/libxml/include/libxml/globals.h +508 -0
  79. package/vendor/libxml/include/libxml/hash.h +236 -0
  80. package/vendor/libxml/include/libxml/list.h +137 -0
  81. package/vendor/libxml/include/libxml/nanoftp.h +163 -0
  82. package/vendor/libxml/include/libxml/nanohttp.h +81 -0
  83. package/vendor/libxml/include/libxml/parser.h +1243 -0
  84. package/vendor/libxml/include/libxml/parserInternals.h +644 -0
  85. package/vendor/libxml/include/libxml/pattern.h +100 -0
  86. package/vendor/libxml/include/libxml/relaxng.h +217 -0
  87. package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
  88. package/vendor/libxml/include/libxml/schematron.h +142 -0
  89. package/vendor/libxml/include/libxml/threads.h +89 -0
  90. package/vendor/libxml/include/libxml/tree.h +1311 -0
  91. package/vendor/libxml/include/libxml/uri.h +94 -0
  92. package/vendor/libxml/include/libxml/valid.h +458 -0
  93. package/vendor/libxml/include/libxml/xinclude.h +129 -0
  94. package/vendor/libxml/include/libxml/xlink.h +189 -0
  95. package/vendor/libxml/include/libxml/xmlIO.h +368 -0
  96. package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
  97. package/vendor/libxml/include/libxml/xmlerror.h +945 -0
  98. package/vendor/libxml/include/libxml/xmlexports.h +77 -0
  99. package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
  100. package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
  101. package/vendor/libxml/include/libxml/xmlreader.h +428 -0
  102. package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
  103. package/vendor/libxml/include/libxml/xmlsave.h +88 -0
  104. package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
  105. package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
  106. package/vendor/libxml/include/libxml/xmlstring.h +140 -0
  107. package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
  108. package/vendor/libxml/include/libxml/xmlversion.h +484 -0
  109. package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
  110. package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
  111. package/vendor/libxml/include/libxml/xpath.h +564 -0
  112. package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
  113. package/vendor/libxml/include/libxml/xpointer.h +114 -0
  114. package/vendor/libxml/include/win32config.h +122 -0
  115. package/vendor/libxml/include/wsockcompat.h +54 -0
  116. package/vendor/libxml/legacy.c +1343 -0
  117. package/vendor/libxml/libxml.h +134 -0
  118. package/vendor/libxml/list.c +779 -0
  119. package/vendor/libxml/nanoftp.c +2118 -0
  120. package/vendor/libxml/nanohttp.c +1899 -0
  121. package/vendor/libxml/parser.c +15553 -0
  122. package/vendor/libxml/parserInternals.c +2164 -0
  123. package/vendor/libxml/pattern.c +2621 -0
  124. package/vendor/libxml/relaxng.c +11101 -0
  125. package/vendor/libxml/rngparser.c +1595 -0
  126. package/vendor/libxml/runsuite.c +1157 -0
  127. package/vendor/libxml/save.h +36 -0
  128. package/vendor/libxml/schematron.c +1787 -0
  129. package/vendor/libxml/threads.c +1049 -0
  130. package/vendor/libxml/timsort.h +601 -0
  131. package/vendor/libxml/tree.c +10183 -0
  132. package/vendor/libxml/trio.c +6895 -0
  133. package/vendor/libxml/trio.h +230 -0
  134. package/vendor/libxml/triodef.h +228 -0
  135. package/vendor/libxml/trionan.c +914 -0
  136. package/vendor/libxml/trionan.h +84 -0
  137. package/vendor/libxml/triop.h +150 -0
  138. package/vendor/libxml/triostr.c +2112 -0
  139. package/vendor/libxml/triostr.h +144 -0
  140. package/vendor/libxml/uri.c +2561 -0
  141. package/vendor/libxml/valid.c +7138 -0
  142. package/vendor/libxml/xinclude.c +2657 -0
  143. package/vendor/libxml/xlink.c +183 -0
  144. package/vendor/libxml/xmlIO.c +4135 -0
  145. package/vendor/libxml/xmlcatalog.c +624 -0
  146. package/vendor/libxml/xmllint.c +3796 -0
  147. package/vendor/libxml/xmlmemory.c +1163 -0
  148. package/vendor/libxml/xmlmodule.c +468 -0
  149. package/vendor/libxml/xmlreader.c +6033 -0
  150. package/vendor/libxml/xmlregexp.c +8271 -0
  151. package/vendor/libxml/xmlsave.c +2735 -0
  152. package/vendor/libxml/xmlschemas.c +29173 -0
  153. package/vendor/libxml/xmlschemastypes.c +6276 -0
  154. package/vendor/libxml/xmlstring.c +1050 -0
  155. package/vendor/libxml/xmlunicode.c +3179 -0
  156. package/vendor/libxml/xmlwriter.c +4738 -0
  157. package/vendor/libxml/xpath.c +14734 -0
  158. package/vendor/libxml/xpointer.c +2969 -0
  159. package/vendor/libxml/xzlib.c +815 -0
  160. package/vendor/libxml/xzlib.h +19 -0
@@ -0,0 +1,1049 @@
1
+ /**
2
+ * threads.c: set of generic threading related routines
3
+ *
4
+ * See Copyright for the status of this software.
5
+ *
6
+ * Gary Pennington <Gary.Pennington@uk.sun.com>
7
+ * daniel@veillard.com
8
+ */
9
+
10
+ #define IN_LIBXML
11
+ #include "libxml.h"
12
+
13
+ #include <string.h>
14
+
15
+ #include <libxml/threads.h>
16
+ #include <libxml/globals.h>
17
+
18
+ #ifdef HAVE_SYS_TYPES_H
19
+ #include <sys/types.h>
20
+ #endif
21
+ #ifdef HAVE_UNISTD_H
22
+ #include <unistd.h>
23
+ #endif
24
+ #ifdef HAVE_STDLIB_H
25
+ #include <stdlib.h>
26
+ #endif
27
+ #ifdef HAVE_PTHREAD_H
28
+ #include <pthread.h>
29
+ #elif defined HAVE_WIN32_THREADS
30
+ #define WIN32_LEAN_AND_MEAN
31
+ #include <windows.h>
32
+ #ifndef HAVE_COMPILER_TLS
33
+ #include <process.h>
34
+ #endif
35
+ #endif
36
+
37
+ #ifdef HAVE_BEOS_THREADS
38
+ #include <OS.h>
39
+ #include <TLS.h>
40
+ #endif
41
+
42
+ #if defined(SOLARIS)
43
+ #include <note.h>
44
+ #endif
45
+
46
+ /* #define DEBUG_THREADS */
47
+
48
+ #ifdef HAVE_PTHREAD_H
49
+
50
+ #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 303) && \
51
+ defined(__GLIBC__) && defined(__linux__)
52
+
53
+ static int libxml_is_threaded = -1;
54
+
55
+ #define XML_PTHREAD_WEAK
56
+
57
+ #pragma weak pthread_once
58
+ #pragma weak pthread_getspecific
59
+ #pragma weak pthread_setspecific
60
+ #pragma weak pthread_key_create
61
+ #pragma weak pthread_key_delete
62
+ #pragma weak pthread_mutex_init
63
+ #pragma weak pthread_mutex_destroy
64
+ #pragma weak pthread_mutex_lock
65
+ #pragma weak pthread_mutex_unlock
66
+ #pragma weak pthread_cond_init
67
+ #pragma weak pthread_cond_destroy
68
+ #pragma weak pthread_cond_wait
69
+ #pragma weak pthread_equal
70
+ #pragma weak pthread_self
71
+ #pragma weak pthread_key_create
72
+ #pragma weak pthread_key_delete
73
+ #pragma weak pthread_cond_signal
74
+
75
+ #else /* __GNUC__, __GLIBC__, __linux__ */
76
+
77
+ static int libxml_is_threaded = 1;
78
+
79
+ #endif /* __GNUC__, __GLIBC__, __linux__ */
80
+
81
+ #endif /* HAVE_PTHREAD_H */
82
+
83
+ /*
84
+ * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree
85
+ * to avoid some craziness since xmlMalloc/xmlFree may actually
86
+ * be hosted on allocated blocks needing them for the allocation ...
87
+ */
88
+
89
+ /*
90
+ * xmlMutex are a simple mutual exception locks
91
+ */
92
+ struct _xmlMutex {
93
+ #ifdef HAVE_PTHREAD_H
94
+ pthread_mutex_t lock;
95
+ #elif defined HAVE_WIN32_THREADS
96
+ HANDLE mutex;
97
+ #elif defined HAVE_BEOS_THREADS
98
+ sem_id sem;
99
+ thread_id tid;
100
+ #else
101
+ int empty;
102
+ #endif
103
+ };
104
+
105
+ /*
106
+ * xmlRMutex are reentrant mutual exception locks
107
+ */
108
+ struct _xmlRMutex {
109
+ #ifdef HAVE_PTHREAD_H
110
+ pthread_mutex_t lock;
111
+ unsigned int held;
112
+ unsigned int waiters;
113
+ pthread_t tid;
114
+ pthread_cond_t cv;
115
+ #elif defined HAVE_WIN32_THREADS
116
+ CRITICAL_SECTION cs;
117
+ unsigned int count;
118
+ #elif defined HAVE_BEOS_THREADS
119
+ xmlMutexPtr lock;
120
+ thread_id tid;
121
+ int32 count;
122
+ #else
123
+ int empty;
124
+ #endif
125
+ };
126
+
127
+ /*
128
+ * This module still has some internal static data.
129
+ * - xmlLibraryLock a global lock
130
+ * - globalkey used for per-thread data
131
+ */
132
+
133
+ #ifdef HAVE_PTHREAD_H
134
+ static pthread_key_t globalkey;
135
+ static pthread_t mainthread;
136
+ static pthread_once_t once_control = PTHREAD_ONCE_INIT;
137
+ static pthread_once_t once_control_init = PTHREAD_ONCE_INIT;
138
+ static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
139
+ #elif defined HAVE_WIN32_THREADS
140
+ #if defined(HAVE_COMPILER_TLS)
141
+ static __declspec(thread) xmlGlobalState tlstate;
142
+ static __declspec(thread) int tlstate_inited = 0;
143
+ #else /* HAVE_COMPILER_TLS */
144
+ static DWORD globalkey = TLS_OUT_OF_INDEXES;
145
+ #endif /* HAVE_COMPILER_TLS */
146
+ static DWORD mainthread;
147
+ static struct {
148
+ DWORD done;
149
+ LONG control;
150
+ } run_once = { 0, 0};
151
+ static volatile LPCRITICAL_SECTION global_init_lock = NULL;
152
+
153
+ /* endif HAVE_WIN32_THREADS */
154
+ #elif defined HAVE_BEOS_THREADS
155
+ int32 globalkey = 0;
156
+ thread_id mainthread = 0;
157
+ int32 run_once_init = 0;
158
+ static int32 global_init_lock = -1;
159
+ static vint32 global_init_count = 0;
160
+ #endif
161
+
162
+ static xmlRMutexPtr xmlLibraryLock = NULL;
163
+
164
+ #ifdef LIBXML_THREAD_ENABLED
165
+ static void xmlOnceInit(void);
166
+ #endif
167
+
168
+ /**
169
+ * xmlNewMutex:
170
+ *
171
+ * xmlNewMutex() is used to allocate a libxml2 token struct for use in
172
+ * synchronizing access to data.
173
+ *
174
+ * Returns a new simple mutex pointer or NULL in case of error
175
+ */
176
+ xmlMutexPtr
177
+ xmlNewMutex(void)
178
+ {
179
+ xmlMutexPtr tok;
180
+
181
+ if ((tok = malloc(sizeof(xmlMutex))) == NULL)
182
+ return (NULL);
183
+ #ifdef HAVE_PTHREAD_H
184
+ if (libxml_is_threaded != 0)
185
+ pthread_mutex_init(&tok->lock, NULL);
186
+ #elif defined HAVE_WIN32_THREADS
187
+ tok->mutex = CreateMutex(NULL, FALSE, NULL);
188
+ #elif defined HAVE_BEOS_THREADS
189
+ if ((tok->sem = create_sem(1, "xmlMutex")) < B_OK) {
190
+ free(tok);
191
+ return NULL;
192
+ }
193
+ tok->tid = -1;
194
+ #endif
195
+ return (tok);
196
+ }
197
+
198
+ /**
199
+ * xmlFreeMutex:
200
+ * @tok: the simple mutex
201
+ *
202
+ * xmlFreeMutex() is used to reclaim resources associated with a libxml2 token
203
+ * struct.
204
+ */
205
+ void
206
+ xmlFreeMutex(xmlMutexPtr tok)
207
+ {
208
+ if (tok == NULL)
209
+ return;
210
+
211
+ #ifdef HAVE_PTHREAD_H
212
+ if (libxml_is_threaded != 0)
213
+ pthread_mutex_destroy(&tok->lock);
214
+ #elif defined HAVE_WIN32_THREADS
215
+ CloseHandle(tok->mutex);
216
+ #elif defined HAVE_BEOS_THREADS
217
+ delete_sem(tok->sem);
218
+ #endif
219
+ free(tok);
220
+ }
221
+
222
+ /**
223
+ * xmlMutexLock:
224
+ * @tok: the simple mutex
225
+ *
226
+ * xmlMutexLock() is used to lock a libxml2 token.
227
+ */
228
+ void
229
+ xmlMutexLock(xmlMutexPtr tok)
230
+ {
231
+ if (tok == NULL)
232
+ return;
233
+ #ifdef HAVE_PTHREAD_H
234
+ if (libxml_is_threaded != 0)
235
+ pthread_mutex_lock(&tok->lock);
236
+ #elif defined HAVE_WIN32_THREADS
237
+ WaitForSingleObject(tok->mutex, INFINITE);
238
+ #elif defined HAVE_BEOS_THREADS
239
+ if (acquire_sem(tok->sem) != B_NO_ERROR) {
240
+ #ifdef DEBUG_THREADS
241
+ xmlGenericError(xmlGenericErrorContext,
242
+ "xmlMutexLock():BeOS:Couldn't acquire semaphore\n");
243
+ #endif
244
+ }
245
+ tok->tid = find_thread(NULL);
246
+ #endif
247
+
248
+ }
249
+
250
+ /**
251
+ * xmlMutexUnlock:
252
+ * @tok: the simple mutex
253
+ *
254
+ * xmlMutexUnlock() is used to unlock a libxml2 token.
255
+ */
256
+ void
257
+ xmlMutexUnlock(xmlMutexPtr tok)
258
+ {
259
+ if (tok == NULL)
260
+ return;
261
+ #ifdef HAVE_PTHREAD_H
262
+ if (libxml_is_threaded != 0)
263
+ pthread_mutex_unlock(&tok->lock);
264
+ #elif defined HAVE_WIN32_THREADS
265
+ ReleaseMutex(tok->mutex);
266
+ #elif defined HAVE_BEOS_THREADS
267
+ if (tok->tid == find_thread(NULL)) {
268
+ tok->tid = -1;
269
+ release_sem(tok->sem);
270
+ }
271
+ #endif
272
+ }
273
+
274
+ /**
275
+ * xmlNewRMutex:
276
+ *
277
+ * xmlRNewMutex() is used to allocate a reentrant mutex for use in
278
+ * synchronizing access to data. token_r is a re-entrant lock and thus useful
279
+ * for synchronizing access to data structures that may be manipulated in a
280
+ * recursive fashion.
281
+ *
282
+ * Returns the new reentrant mutex pointer or NULL in case of error
283
+ */
284
+ xmlRMutexPtr
285
+ xmlNewRMutex(void)
286
+ {
287
+ xmlRMutexPtr tok;
288
+
289
+ if ((tok = malloc(sizeof(xmlRMutex))) == NULL)
290
+ return (NULL);
291
+ #ifdef HAVE_PTHREAD_H
292
+ if (libxml_is_threaded != 0) {
293
+ pthread_mutex_init(&tok->lock, NULL);
294
+ tok->held = 0;
295
+ tok->waiters = 0;
296
+ pthread_cond_init(&tok->cv, NULL);
297
+ }
298
+ #elif defined HAVE_WIN32_THREADS
299
+ InitializeCriticalSection(&tok->cs);
300
+ tok->count = 0;
301
+ #elif defined HAVE_BEOS_THREADS
302
+ if ((tok->lock = xmlNewMutex()) == NULL) {
303
+ free(tok);
304
+ return NULL;
305
+ }
306
+ tok->count = 0;
307
+ #endif
308
+ return (tok);
309
+ }
310
+
311
+ /**
312
+ * xmlFreeRMutex:
313
+ * @tok: the reentrant mutex
314
+ *
315
+ * xmlRFreeMutex() is used to reclaim resources associated with a
316
+ * reentrant mutex.
317
+ */
318
+ void
319
+ xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
320
+ {
321
+ if (tok == NULL)
322
+ return;
323
+ #ifdef HAVE_PTHREAD_H
324
+ if (libxml_is_threaded != 0) {
325
+ pthread_mutex_destroy(&tok->lock);
326
+ pthread_cond_destroy(&tok->cv);
327
+ }
328
+ #elif defined HAVE_WIN32_THREADS
329
+ DeleteCriticalSection(&tok->cs);
330
+ #elif defined HAVE_BEOS_THREADS
331
+ xmlFreeMutex(tok->lock);
332
+ #endif
333
+ free(tok);
334
+ }
335
+
336
+ /**
337
+ * xmlRMutexLock:
338
+ * @tok: the reentrant mutex
339
+ *
340
+ * xmlRMutexLock() is used to lock a libxml2 token_r.
341
+ */
342
+ void
343
+ xmlRMutexLock(xmlRMutexPtr tok)
344
+ {
345
+ if (tok == NULL)
346
+ return;
347
+ #ifdef HAVE_PTHREAD_H
348
+ if (libxml_is_threaded == 0)
349
+ return;
350
+
351
+ pthread_mutex_lock(&tok->lock);
352
+ if (tok->held) {
353
+ if (pthread_equal(tok->tid, pthread_self())) {
354
+ tok->held++;
355
+ pthread_mutex_unlock(&tok->lock);
356
+ return;
357
+ } else {
358
+ tok->waiters++;
359
+ while (tok->held)
360
+ pthread_cond_wait(&tok->cv, &tok->lock);
361
+ tok->waiters--;
362
+ }
363
+ }
364
+ tok->tid = pthread_self();
365
+ tok->held = 1;
366
+ pthread_mutex_unlock(&tok->lock);
367
+ #elif defined HAVE_WIN32_THREADS
368
+ EnterCriticalSection(&tok->cs);
369
+ tok->count++;
370
+ #elif defined HAVE_BEOS_THREADS
371
+ if (tok->lock->tid == find_thread(NULL)) {
372
+ tok->count++;
373
+ return;
374
+ } else {
375
+ xmlMutexLock(tok->lock);
376
+ tok->count = 1;
377
+ }
378
+ #endif
379
+ }
380
+
381
+ /**
382
+ * xmlRMutexUnlock:
383
+ * @tok: the reentrant mutex
384
+ *
385
+ * xmlRMutexUnlock() is used to unlock a libxml2 token_r.
386
+ */
387
+ void
388
+ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
389
+ {
390
+ if (tok == NULL)
391
+ return;
392
+ #ifdef HAVE_PTHREAD_H
393
+ if (libxml_is_threaded == 0)
394
+ return;
395
+
396
+ pthread_mutex_lock(&tok->lock);
397
+ tok->held--;
398
+ if (tok->held == 0) {
399
+ if (tok->waiters)
400
+ pthread_cond_signal(&tok->cv);
401
+ memset(&tok->tid, 0, sizeof(tok->tid));
402
+ }
403
+ pthread_mutex_unlock(&tok->lock);
404
+ #elif defined HAVE_WIN32_THREADS
405
+ if (tok->count > 0) {
406
+ tok->count--;
407
+ LeaveCriticalSection(&tok->cs);
408
+ }
409
+ #elif defined HAVE_BEOS_THREADS
410
+ if (tok->lock->tid == find_thread(NULL)) {
411
+ tok->count--;
412
+ if (tok->count == 0) {
413
+ xmlMutexUnlock(tok->lock);
414
+ }
415
+ return;
416
+ }
417
+ #endif
418
+ }
419
+
420
+ /**
421
+ * xmlGlobalInitMutexLock
422
+ *
423
+ * Makes sure that the global initialization mutex is initialized and
424
+ * locks it.
425
+ */
426
+ void
427
+ __xmlGlobalInitMutexLock(void)
428
+ {
429
+ /* Make sure the global init lock is initialized and then lock it. */
430
+ #ifdef HAVE_PTHREAD_H
431
+ /* The mutex is statically initialized, so we just lock it. */
432
+ #ifdef XML_PTHREAD_WEAK
433
+ if (pthread_mutex_lock == NULL)
434
+ return;
435
+ #endif /* XML_PTHREAD_WEAK */
436
+ pthread_mutex_lock(&global_init_lock);
437
+ #elif defined HAVE_WIN32_THREADS
438
+ LPCRITICAL_SECTION cs;
439
+
440
+ /* Create a new critical section */
441
+ if (global_init_lock == NULL) {
442
+ cs = malloc(sizeof(CRITICAL_SECTION));
443
+ if (cs == NULL) {
444
+ xmlGenericError(xmlGenericErrorContext,
445
+ "xmlGlobalInitMutexLock: out of memory\n");
446
+ return;
447
+ }
448
+ InitializeCriticalSection(cs);
449
+
450
+ /* Swap it into the global_init_lock */
451
+ #ifdef InterlockedCompareExchangePointer
452
+ InterlockedCompareExchangePointer((void **) &global_init_lock,
453
+ cs, NULL);
454
+ #else /* Use older void* version */
455
+ InterlockedCompareExchange((void **) &global_init_lock,
456
+ (void *) cs, NULL);
457
+ #endif /* InterlockedCompareExchangePointer */
458
+
459
+ /* If another thread successfully recorded its critical
460
+ * section in the global_init_lock then discard the one
461
+ * allocated by this thread. */
462
+ if (global_init_lock != cs) {
463
+ DeleteCriticalSection(cs);
464
+ free(cs);
465
+ }
466
+ }
467
+
468
+ /* Lock the chosen critical section */
469
+ EnterCriticalSection(global_init_lock);
470
+ #elif defined HAVE_BEOS_THREADS
471
+ int32 sem;
472
+
473
+ /* Allocate a new semaphore */
474
+ sem = create_sem(1, "xmlGlobalinitMutex");
475
+
476
+ while (global_init_lock == -1) {
477
+ if (atomic_add(&global_init_count, 1) == 0) {
478
+ global_init_lock = sem;
479
+ } else {
480
+ snooze(1);
481
+ atomic_add(&global_init_count, -1);
482
+ }
483
+ }
484
+
485
+ /* If another thread successfully recorded its critical
486
+ * section in the global_init_lock then discard the one
487
+ * allocated by this thread. */
488
+ if (global_init_lock != sem)
489
+ delete_sem(sem);
490
+
491
+ /* Acquire the chosen semaphore */
492
+ if (acquire_sem(global_init_lock) != B_NO_ERROR) {
493
+ #ifdef DEBUG_THREADS
494
+ xmlGenericError(xmlGenericErrorContext,
495
+ "xmlGlobalInitMutexLock():BeOS:Couldn't acquire semaphore\n");
496
+ #endif
497
+ }
498
+ #endif
499
+ }
500
+
501
+ void
502
+ __xmlGlobalInitMutexUnlock(void)
503
+ {
504
+ #ifdef HAVE_PTHREAD_H
505
+ #ifdef XML_PTHREAD_WEAK
506
+ if (pthread_mutex_unlock == NULL)
507
+ return;
508
+ #endif /* XML_PTHREAD_WEAK */
509
+ pthread_mutex_unlock(&global_init_lock);
510
+ #elif defined HAVE_WIN32_THREADS
511
+ if (global_init_lock != NULL) {
512
+ LeaveCriticalSection(global_init_lock);
513
+ }
514
+ #elif defined HAVE_BEOS_THREADS
515
+ release_sem(global_init_lock);
516
+ #endif
517
+ }
518
+
519
+ /**
520
+ * xmlGlobalInitMutexDestroy
521
+ *
522
+ * Makes sure that the global initialization mutex is destroyed before
523
+ * application termination.
524
+ */
525
+ void
526
+ __xmlGlobalInitMutexDestroy(void)
527
+ {
528
+ #ifdef HAVE_PTHREAD_H
529
+ #elif defined HAVE_WIN32_THREADS
530
+ if (global_init_lock != NULL) {
531
+ DeleteCriticalSection(global_init_lock);
532
+ free(global_init_lock);
533
+ global_init_lock = NULL;
534
+ }
535
+ #endif
536
+ }
537
+
538
+ /************************************************************************
539
+ * *
540
+ * Per thread global state handling *
541
+ * *
542
+ ************************************************************************/
543
+
544
+ #ifdef LIBXML_THREAD_ENABLED
545
+ #ifdef xmlLastError
546
+ #undef xmlLastError
547
+ #endif
548
+
549
+ /**
550
+ * xmlFreeGlobalState:
551
+ * @state: a thread global state
552
+ *
553
+ * xmlFreeGlobalState() is called when a thread terminates with a non-NULL
554
+ * global state. It is is used here to reclaim memory resources.
555
+ */
556
+ static void
557
+ xmlFreeGlobalState(void *state)
558
+ {
559
+ xmlGlobalState *gs = (xmlGlobalState *) state;
560
+
561
+ /* free any memory allocated in the thread's xmlLastError */
562
+ xmlResetError(&(gs->xmlLastError));
563
+ free(state);
564
+ }
565
+
566
+ /**
567
+ * xmlNewGlobalState:
568
+ *
569
+ * xmlNewGlobalState() allocates a global state. This structure is used to
570
+ * hold all data for use by a thread when supporting backwards compatibility
571
+ * of libxml2 to pre-thread-safe behaviour.
572
+ *
573
+ * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
574
+ */
575
+ static xmlGlobalStatePtr
576
+ xmlNewGlobalState(void)
577
+ {
578
+ xmlGlobalState *gs;
579
+
580
+ gs = malloc(sizeof(xmlGlobalState));
581
+ if (gs == NULL) {
582
+ xmlGenericError(xmlGenericErrorContext,
583
+ "xmlGetGlobalState: out of memory\n");
584
+ return (NULL);
585
+ }
586
+
587
+ memset(gs, 0, sizeof(xmlGlobalState));
588
+ xmlInitializeGlobalState(gs);
589
+ return (gs);
590
+ }
591
+ #endif /* LIBXML_THREAD_ENABLED */
592
+
593
+ #ifdef HAVE_PTHREAD_H
594
+ #elif defined HAVE_WIN32_THREADS
595
+ #if !defined(HAVE_COMPILER_TLS)
596
+ #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
597
+ typedef struct _xmlGlobalStateCleanupHelperParams {
598
+ HANDLE thread;
599
+ void *memory;
600
+ } xmlGlobalStateCleanupHelperParams;
601
+
602
+ static void XMLCDECL
603
+ xmlGlobalStateCleanupHelper(void *p)
604
+ {
605
+ xmlGlobalStateCleanupHelperParams *params =
606
+ (xmlGlobalStateCleanupHelperParams *) p;
607
+ WaitForSingleObject(params->thread, INFINITE);
608
+ CloseHandle(params->thread);
609
+ xmlFreeGlobalState(params->memory);
610
+ free(params);
611
+ _endthread();
612
+ }
613
+ #else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */
614
+
615
+ typedef struct _xmlGlobalStateCleanupHelperParams {
616
+ void *memory;
617
+ struct _xmlGlobalStateCleanupHelperParams *prev;
618
+ struct _xmlGlobalStateCleanupHelperParams *next;
619
+ } xmlGlobalStateCleanupHelperParams;
620
+
621
+ static xmlGlobalStateCleanupHelperParams *cleanup_helpers_head = NULL;
622
+ static CRITICAL_SECTION cleanup_helpers_cs;
623
+
624
+ #endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */
625
+ #endif /* HAVE_COMPILER_TLS */
626
+ #endif /* HAVE_WIN32_THREADS */
627
+
628
+ #if defined HAVE_BEOS_THREADS
629
+
630
+ /**
631
+ * xmlGlobalStateCleanup:
632
+ * @data: unused parameter
633
+ *
634
+ * Used for Beos only
635
+ */
636
+ void
637
+ xmlGlobalStateCleanup(void *data)
638
+ {
639
+ void *globalval = tls_get(globalkey);
640
+
641
+ if (globalval != NULL)
642
+ xmlFreeGlobalState(globalval);
643
+ }
644
+ #endif
645
+
646
+ /**
647
+ * xmlGetGlobalState:
648
+ *
649
+ * xmlGetGlobalState() is called to retrieve the global state for a thread.
650
+ *
651
+ * Returns the thread global state or NULL in case of error
652
+ */
653
+ xmlGlobalStatePtr
654
+ xmlGetGlobalState(void)
655
+ {
656
+ #ifdef HAVE_PTHREAD_H
657
+ xmlGlobalState *globalval;
658
+
659
+ if (libxml_is_threaded == 0)
660
+ return (NULL);
661
+
662
+ pthread_once(&once_control, xmlOnceInit);
663
+
664
+ if ((globalval = (xmlGlobalState *)
665
+ pthread_getspecific(globalkey)) == NULL) {
666
+ xmlGlobalState *tsd = xmlNewGlobalState();
667
+ if (tsd == NULL)
668
+ return(NULL);
669
+
670
+ pthread_setspecific(globalkey, tsd);
671
+ return (tsd);
672
+ }
673
+ return (globalval);
674
+ #elif defined HAVE_WIN32_THREADS
675
+ #if defined(HAVE_COMPILER_TLS)
676
+ if (!tlstate_inited) {
677
+ tlstate_inited = 1;
678
+ xmlInitializeGlobalState(&tlstate);
679
+ }
680
+ return &tlstate;
681
+ #else /* HAVE_COMPILER_TLS */
682
+ xmlGlobalState *globalval;
683
+ xmlGlobalStateCleanupHelperParams *p;
684
+
685
+ xmlOnceInit();
686
+ #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
687
+ globalval = (xmlGlobalState *) TlsGetValue(globalkey);
688
+ #else
689
+ p = (xmlGlobalStateCleanupHelperParams *) TlsGetValue(globalkey);
690
+ globalval = (xmlGlobalState *) (p ? p->memory : NULL);
691
+ #endif
692
+ if (globalval == NULL) {
693
+ xmlGlobalState *tsd = xmlNewGlobalState();
694
+
695
+ if (tsd == NULL)
696
+ return(NULL);
697
+ p = (xmlGlobalStateCleanupHelperParams *)
698
+ malloc(sizeof(xmlGlobalStateCleanupHelperParams));
699
+ if (p == NULL) {
700
+ xmlGenericError(xmlGenericErrorContext,
701
+ "xmlGetGlobalState: out of memory\n");
702
+ xmlFreeGlobalState(tsd);
703
+ return(NULL);
704
+ }
705
+ p->memory = tsd;
706
+ #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
707
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
708
+ GetCurrentProcess(), &p->thread, 0, TRUE,
709
+ DUPLICATE_SAME_ACCESS);
710
+ TlsSetValue(globalkey, tsd);
711
+ _beginthread(xmlGlobalStateCleanupHelper, 0, p);
712
+ #else
713
+ EnterCriticalSection(&cleanup_helpers_cs);
714
+ if (cleanup_helpers_head != NULL) {
715
+ cleanup_helpers_head->prev = p;
716
+ }
717
+ p->next = cleanup_helpers_head;
718
+ p->prev = NULL;
719
+ cleanup_helpers_head = p;
720
+ TlsSetValue(globalkey, p);
721
+ LeaveCriticalSection(&cleanup_helpers_cs);
722
+ #endif
723
+
724
+ return (tsd);
725
+ }
726
+ return (globalval);
727
+ #endif /* HAVE_COMPILER_TLS */
728
+ #elif defined HAVE_BEOS_THREADS
729
+ xmlGlobalState *globalval;
730
+
731
+ xmlOnceInit();
732
+
733
+ if ((globalval = (xmlGlobalState *) tls_get(globalkey)) == NULL) {
734
+ xmlGlobalState *tsd = xmlNewGlobalState();
735
+ if (tsd == NULL)
736
+ return (NULL);
737
+
738
+ tls_set(globalkey, tsd);
739
+ on_exit_thread(xmlGlobalStateCleanup, NULL);
740
+ return (tsd);
741
+ }
742
+ return (globalval);
743
+ #else
744
+ return (NULL);
745
+ #endif
746
+ }
747
+
748
+ /************************************************************************
749
+ * *
750
+ * Library wide thread interfaces *
751
+ * *
752
+ ************************************************************************/
753
+
754
+ /**
755
+ * xmlGetThreadId:
756
+ *
757
+ * xmlGetThreadId() find the current thread ID number
758
+ * Note that this is likely to be broken on some platforms using pthreads
759
+ * as the specification doesn't mandate pthread_t to be an integer type
760
+ *
761
+ * Returns the current thread ID number
762
+ */
763
+ int
764
+ xmlGetThreadId(void)
765
+ {
766
+ #ifdef HAVE_PTHREAD_H
767
+ pthread_t id;
768
+ int ret;
769
+
770
+ if (libxml_is_threaded == 0)
771
+ return (0);
772
+ id = pthread_self();
773
+ /* horrible but preserves compat, see warning above */
774
+ memcpy(&ret, &id, sizeof(ret));
775
+ return (ret);
776
+ #elif defined HAVE_WIN32_THREADS
777
+ return GetCurrentThreadId();
778
+ #elif defined HAVE_BEOS_THREADS
779
+ return find_thread(NULL);
780
+ #else
781
+ return ((int) 0);
782
+ #endif
783
+ }
784
+
785
+ /**
786
+ * xmlIsMainThread:
787
+ *
788
+ * xmlIsMainThread() check whether the current thread is the main thread.
789
+ *
790
+ * Returns 1 if the current thread is the main thread, 0 otherwise
791
+ */
792
+ int
793
+ xmlIsMainThread(void)
794
+ {
795
+ #ifdef HAVE_PTHREAD_H
796
+ if (libxml_is_threaded == -1)
797
+ xmlInitThreads();
798
+ if (libxml_is_threaded == 0)
799
+ return (1);
800
+ pthread_once(&once_control, xmlOnceInit);
801
+ #elif defined HAVE_WIN32_THREADS
802
+ xmlOnceInit();
803
+ #elif defined HAVE_BEOS_THREADS
804
+ xmlOnceInit();
805
+ #endif
806
+
807
+ #ifdef DEBUG_THREADS
808
+ xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n");
809
+ #endif
810
+ #ifdef HAVE_PTHREAD_H
811
+ return (pthread_equal(mainthread,pthread_self()));
812
+ #elif defined HAVE_WIN32_THREADS
813
+ return (mainthread == GetCurrentThreadId());
814
+ #elif defined HAVE_BEOS_THREADS
815
+ return (mainthread == find_thread(NULL));
816
+ #else
817
+ return (1);
818
+ #endif
819
+ }
820
+
821
+ /**
822
+ * xmlLockLibrary:
823
+ *
824
+ * xmlLockLibrary() is used to take out a re-entrant lock on the libxml2
825
+ * library.
826
+ */
827
+ void
828
+ xmlLockLibrary(void)
829
+ {
830
+ #ifdef DEBUG_THREADS
831
+ xmlGenericError(xmlGenericErrorContext, "xmlLockLibrary()\n");
832
+ #endif
833
+ xmlRMutexLock(xmlLibraryLock);
834
+ }
835
+
836
+ /**
837
+ * xmlUnlockLibrary:
838
+ *
839
+ * xmlUnlockLibrary() is used to release a re-entrant lock on the libxml2
840
+ * library.
841
+ */
842
+ void
843
+ xmlUnlockLibrary(void)
844
+ {
845
+ #ifdef DEBUG_THREADS
846
+ xmlGenericError(xmlGenericErrorContext, "xmlUnlockLibrary()\n");
847
+ #endif
848
+ xmlRMutexUnlock(xmlLibraryLock);
849
+ }
850
+
851
+ /**
852
+ * xmlInitThreads:
853
+ *
854
+ * xmlInitThreads() is used to to initialize all the thread related
855
+ * data of the libxml2 library.
856
+ */
857
+ void
858
+ xmlInitThreads(void)
859
+ {
860
+ #ifdef HAVE_PTHREAD_H
861
+ #ifdef XML_PTHREAD_WEAK
862
+ if (libxml_is_threaded == -1) {
863
+ if ((pthread_once != NULL) &&
864
+ (pthread_getspecific != NULL) &&
865
+ (pthread_setspecific != NULL) &&
866
+ (pthread_key_create != NULL) &&
867
+ (pthread_key_delete != NULL) &&
868
+ (pthread_mutex_init != NULL) &&
869
+ (pthread_mutex_destroy != NULL) &&
870
+ (pthread_mutex_lock != NULL) &&
871
+ (pthread_mutex_unlock != NULL) &&
872
+ (pthread_cond_init != NULL) &&
873
+ (pthread_cond_destroy != NULL) &&
874
+ (pthread_cond_wait != NULL) &&
875
+ (pthread_equal != NULL) &&
876
+ (pthread_self != NULL) &&
877
+ (pthread_cond_signal != NULL)) {
878
+ libxml_is_threaded = 1;
879
+
880
+ /* fprintf(stderr, "Running multithreaded\n"); */
881
+ } else {
882
+
883
+ /* fprintf(stderr, "Running without multithread\n"); */
884
+ libxml_is_threaded = 0;
885
+ }
886
+ }
887
+ #endif /* XML_PTHREAD_WEAK */
888
+ #endif
889
+ }
890
+
891
+ /**
892
+ * xmlCleanupThreads:
893
+ *
894
+ * xmlCleanupThreads() is used to to cleanup all the thread related
895
+ * data of the libxml2 library once processing has ended.
896
+ *
897
+ * WARNING: if your application is multithreaded or has plugin support
898
+ * calling this may crash the application if another thread or
899
+ * a plugin is still using libxml2. It's sometimes very hard to
900
+ * guess if libxml2 is in use in the application, some libraries
901
+ * or plugins may use it without notice. In case of doubt abstain
902
+ * from calling this function or do it just before calling exit()
903
+ * to avoid leak reports from valgrind !
904
+ */
905
+ void
906
+ xmlCleanupThreads(void)
907
+ {
908
+ #ifdef DEBUG_THREADS
909
+ xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n");
910
+ #endif
911
+ #ifdef HAVE_PTHREAD_H
912
+ if (libxml_is_threaded != 0)
913
+ pthread_key_delete(globalkey);
914
+ once_control = once_control_init;
915
+ #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
916
+ if (globalkey != TLS_OUT_OF_INDEXES) {
917
+ xmlGlobalStateCleanupHelperParams *p;
918
+
919
+ EnterCriticalSection(&cleanup_helpers_cs);
920
+ p = cleanup_helpers_head;
921
+ while (p != NULL) {
922
+ xmlGlobalStateCleanupHelperParams *temp = p;
923
+
924
+ p = p->next;
925
+ xmlFreeGlobalState(temp->memory);
926
+ free(temp);
927
+ }
928
+ cleanup_helpers_head = 0;
929
+ LeaveCriticalSection(&cleanup_helpers_cs);
930
+ TlsFree(globalkey);
931
+ globalkey = TLS_OUT_OF_INDEXES;
932
+ }
933
+ DeleteCriticalSection(&cleanup_helpers_cs);
934
+ #endif
935
+ }
936
+
937
+ #ifdef LIBXML_THREAD_ENABLED
938
+
939
+ /**
940
+ * xmlOnceInit
941
+ *
942
+ * xmlOnceInit() is used to initialize the value of mainthread for use
943
+ * in other routines. This function should only be called using
944
+ * pthread_once() in association with the once_control variable to ensure
945
+ * that the function is only called once. See man pthread_once for more
946
+ * details.
947
+ */
948
+ static void
949
+ xmlOnceInit(void)
950
+ {
951
+ #ifdef HAVE_PTHREAD_H
952
+ (void) pthread_key_create(&globalkey, xmlFreeGlobalState);
953
+ mainthread = pthread_self();
954
+ __xmlInitializeDict();
955
+ #elif defined(HAVE_WIN32_THREADS)
956
+ if (!run_once.done) {
957
+ if (InterlockedIncrement(&run_once.control) == 1) {
958
+ #if !defined(HAVE_COMPILER_TLS)
959
+ #if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
960
+ InitializeCriticalSection(&cleanup_helpers_cs);
961
+ #endif
962
+ globalkey = TlsAlloc();
963
+ #endif
964
+ mainthread = GetCurrentThreadId();
965
+ __xmlInitializeDict();
966
+ run_once.done = 1;
967
+ } else {
968
+ /* Another thread is working; give up our slice and
969
+ * wait until they're done. */
970
+ while (!run_once.done)
971
+ Sleep(0);
972
+ }
973
+ }
974
+ #elif defined HAVE_BEOS_THREADS
975
+ if (atomic_add(&run_once_init, 1) == 0) {
976
+ globalkey = tls_allocate();
977
+ tls_set(globalkey, NULL);
978
+ mainthread = find_thread(NULL);
979
+ __xmlInitializeDict();
980
+ } else
981
+ atomic_add(&run_once_init, -1);
982
+ #endif
983
+ }
984
+ #endif
985
+
986
+ /**
987
+ * DllMain:
988
+ * @hinstDLL: handle to DLL instance
989
+ * @fdwReason: Reason code for entry
990
+ * @lpvReserved: generic pointer (depends upon reason code)
991
+ *
992
+ * Entry point for Windows library. It is being used to free thread-specific
993
+ * storage.
994
+ *
995
+ * Returns TRUE always
996
+ */
997
+ #ifdef HAVE_PTHREAD_H
998
+ #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
999
+ #if defined(LIBXML_STATIC_FOR_DLL)
1000
+ int XMLCALL
1001
+ xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
1002
+ ATTRIBUTE_UNUSED void *lpvReserved)
1003
+ #else
1004
+ /* declare to avoid "no previous prototype for 'DllMain'" warning */
1005
+ /* Note that we do NOT want to include this function declaration in
1006
+ a public header because it's meant to be called by Windows itself,
1007
+ not a program that uses this library. This also has to be exported. */
1008
+
1009
+ XMLPUBFUN BOOL WINAPI
1010
+ DllMain (HINSTANCE hinstDLL,
1011
+ DWORD fdwReason,
1012
+ LPVOID lpvReserved);
1013
+
1014
+ BOOL WINAPI
1015
+ DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
1016
+ ATTRIBUTE_UNUSED LPVOID lpvReserved)
1017
+ #endif
1018
+ {
1019
+ switch (fdwReason) {
1020
+ case DLL_THREAD_DETACH:
1021
+ if (globalkey != TLS_OUT_OF_INDEXES) {
1022
+ xmlGlobalState *globalval = NULL;
1023
+ xmlGlobalStateCleanupHelperParams *p =
1024
+ (xmlGlobalStateCleanupHelperParams *)
1025
+ TlsGetValue(globalkey);
1026
+ globalval = (xmlGlobalState *) (p ? p->memory : NULL);
1027
+ if (globalval) {
1028
+ xmlFreeGlobalState(globalval);
1029
+ TlsSetValue(globalkey, NULL);
1030
+ }
1031
+ if (p) {
1032
+ EnterCriticalSection(&cleanup_helpers_cs);
1033
+ if (p == cleanup_helpers_head)
1034
+ cleanup_helpers_head = p->next;
1035
+ else
1036
+ p->prev->next = p->next;
1037
+ if (p->next != NULL)
1038
+ p->next->prev = p->prev;
1039
+ LeaveCriticalSection(&cleanup_helpers_cs);
1040
+ free(p);
1041
+ }
1042
+ }
1043
+ break;
1044
+ }
1045
+ return TRUE;
1046
+ }
1047
+ #endif
1048
+ #define bottom_threads
1049
+ #include "elfgcchack.h"