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.
- package/LICENSE +19 -0
- package/Makefile +18 -0
- package/README.md +52 -0
- package/binding.gyp +81 -0
- package/index.d.ts +273 -0
- package/index.js +45 -0
- package/lib/bindings.js +1 -0
- package/lib/document.js +122 -0
- package/lib/element.js +82 -0
- package/lib/sax_parser.js +38 -0
- package/package.json +70 -0
- package/src/html_document.cc +7 -0
- package/src/html_document.h +18 -0
- package/src/libxmljs.cc +252 -0
- package/src/libxmljs.h +53 -0
- package/src/xml_attribute.cc +173 -0
- package/src/xml_attribute.h +40 -0
- package/src/xml_comment.cc +117 -0
- package/src/xml_comment.h +30 -0
- package/src/xml_document.cc +810 -0
- package/src/xml_document.h +67 -0
- package/src/xml_element.cc +565 -0
- package/src/xml_element.h +61 -0
- package/src/xml_namespace.cc +158 -0
- package/src/xml_namespace.h +39 -0
- package/src/xml_node.cc +761 -0
- package/src/xml_node.h +73 -0
- package/src/xml_pi.cc +161 -0
- package/src/xml_pi.h +34 -0
- package/src/xml_sax_parser.cc +424 -0
- package/src/xml_sax_parser.h +73 -0
- package/src/xml_syntax_error.cc +66 -0
- package/src/xml_syntax_error.h +25 -0
- package/src/xml_text.cc +320 -0
- package/src/xml_text.h +48 -0
- package/src/xml_textwriter.cc +315 -0
- package/src/xml_textwriter.h +62 -0
- package/src/xml_xpath_context.cc +70 -0
- package/src/xml_xpath_context.h +23 -0
- package/vendor/libxml/Copyright +23 -0
- package/vendor/libxml/DOCBparser.c +305 -0
- package/vendor/libxml/HTMLparser.c +7287 -0
- package/vendor/libxml/HTMLtree.c +1200 -0
- package/vendor/libxml/Makefile +2983 -0
- package/vendor/libxml/SAX.c +180 -0
- package/vendor/libxml/SAX2.c +3036 -0
- package/vendor/libxml/buf.c +1351 -0
- package/vendor/libxml/buf.h +72 -0
- package/vendor/libxml/c14n.c +2234 -0
- package/vendor/libxml/catalog.c +3828 -0
- package/vendor/libxml/chvalid.c +336 -0
- package/vendor/libxml/config.h +294 -0
- package/vendor/libxml/config.h.gch +0 -0
- package/vendor/libxml/debugXML.c +3423 -0
- package/vendor/libxml/dict.c +1298 -0
- package/vendor/libxml/elfgcchack.h +17818 -0
- package/vendor/libxml/enc.h +32 -0
- package/vendor/libxml/encoding.c +3975 -0
- package/vendor/libxml/entities.c +1163 -0
- package/vendor/libxml/error.c +998 -0
- package/vendor/libxml/globals.c +1126 -0
- package/vendor/libxml/hash.c +1146 -0
- package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
- package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
- package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
- package/vendor/libxml/include/libxml/Makefile +725 -0
- package/vendor/libxml/include/libxml/Makefile.am +54 -0
- package/vendor/libxml/include/libxml/Makefile.in +725 -0
- package/vendor/libxml/include/libxml/SAX.h +173 -0
- package/vendor/libxml/include/libxml/SAX2.h +178 -0
- package/vendor/libxml/include/libxml/c14n.h +128 -0
- package/vendor/libxml/include/libxml/catalog.h +182 -0
- package/vendor/libxml/include/libxml/chvalid.h +230 -0
- package/vendor/libxml/include/libxml/debugXML.h +217 -0
- package/vendor/libxml/include/libxml/dict.h +79 -0
- package/vendor/libxml/include/libxml/encoding.h +245 -0
- package/vendor/libxml/include/libxml/entities.h +151 -0
- package/vendor/libxml/include/libxml/globals.h +508 -0
- package/vendor/libxml/include/libxml/hash.h +236 -0
- package/vendor/libxml/include/libxml/list.h +137 -0
- package/vendor/libxml/include/libxml/nanoftp.h +163 -0
- package/vendor/libxml/include/libxml/nanohttp.h +81 -0
- package/vendor/libxml/include/libxml/parser.h +1243 -0
- package/vendor/libxml/include/libxml/parserInternals.h +644 -0
- package/vendor/libxml/include/libxml/pattern.h +100 -0
- package/vendor/libxml/include/libxml/relaxng.h +217 -0
- package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
- package/vendor/libxml/include/libxml/schematron.h +142 -0
- package/vendor/libxml/include/libxml/threads.h +89 -0
- package/vendor/libxml/include/libxml/tree.h +1311 -0
- package/vendor/libxml/include/libxml/uri.h +94 -0
- package/vendor/libxml/include/libxml/valid.h +458 -0
- package/vendor/libxml/include/libxml/xinclude.h +129 -0
- package/vendor/libxml/include/libxml/xlink.h +189 -0
- package/vendor/libxml/include/libxml/xmlIO.h +368 -0
- package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
- package/vendor/libxml/include/libxml/xmlerror.h +945 -0
- package/vendor/libxml/include/libxml/xmlexports.h +77 -0
- package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
- package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
- package/vendor/libxml/include/libxml/xmlreader.h +428 -0
- package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
- package/vendor/libxml/include/libxml/xmlsave.h +88 -0
- package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
- package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
- package/vendor/libxml/include/libxml/xmlstring.h +140 -0
- package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
- package/vendor/libxml/include/libxml/xmlversion.h +484 -0
- package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
- package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
- package/vendor/libxml/include/libxml/xpath.h +564 -0
- package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
- package/vendor/libxml/include/libxml/xpointer.h +114 -0
- package/vendor/libxml/include/win32config.h +122 -0
- package/vendor/libxml/include/wsockcompat.h +54 -0
- package/vendor/libxml/legacy.c +1343 -0
- package/vendor/libxml/libxml.h +134 -0
- package/vendor/libxml/list.c +779 -0
- package/vendor/libxml/nanoftp.c +2118 -0
- package/vendor/libxml/nanohttp.c +1899 -0
- package/vendor/libxml/parser.c +15553 -0
- package/vendor/libxml/parserInternals.c +2164 -0
- package/vendor/libxml/pattern.c +2621 -0
- package/vendor/libxml/relaxng.c +11101 -0
- package/vendor/libxml/rngparser.c +1595 -0
- package/vendor/libxml/runsuite.c +1157 -0
- package/vendor/libxml/save.h +36 -0
- package/vendor/libxml/schematron.c +1787 -0
- package/vendor/libxml/threads.c +1049 -0
- package/vendor/libxml/timsort.h +601 -0
- package/vendor/libxml/tree.c +10183 -0
- package/vendor/libxml/trio.c +6895 -0
- package/vendor/libxml/trio.h +230 -0
- package/vendor/libxml/triodef.h +228 -0
- package/vendor/libxml/trionan.c +914 -0
- package/vendor/libxml/trionan.h +84 -0
- package/vendor/libxml/triop.h +150 -0
- package/vendor/libxml/triostr.c +2112 -0
- package/vendor/libxml/triostr.h +144 -0
- package/vendor/libxml/uri.c +2561 -0
- package/vendor/libxml/valid.c +7138 -0
- package/vendor/libxml/xinclude.c +2657 -0
- package/vendor/libxml/xlink.c +183 -0
- package/vendor/libxml/xmlIO.c +4135 -0
- package/vendor/libxml/xmlcatalog.c +624 -0
- package/vendor/libxml/xmllint.c +3796 -0
- package/vendor/libxml/xmlmemory.c +1163 -0
- package/vendor/libxml/xmlmodule.c +468 -0
- package/vendor/libxml/xmlreader.c +6033 -0
- package/vendor/libxml/xmlregexp.c +8271 -0
- package/vendor/libxml/xmlsave.c +2735 -0
- package/vendor/libxml/xmlschemas.c +29173 -0
- package/vendor/libxml/xmlschemastypes.c +6276 -0
- package/vendor/libxml/xmlstring.c +1050 -0
- package/vendor/libxml/xmlunicode.c +3179 -0
- package/vendor/libxml/xmlwriter.c +4738 -0
- package/vendor/libxml/xpath.c +14734 -0
- package/vendor/libxml/xpointer.c +2969 -0
- package/vendor/libxml/xzlib.c +815 -0
- 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"
|