1*6777b538SAndroid Build Coastguard Worker /**
2*6777b538SAndroid Build Coastguard Worker * threads.c: set of generic threading related routines
3*6777b538SAndroid Build Coastguard Worker *
4*6777b538SAndroid Build Coastguard Worker * See Copyright for the status of this software.
5*6777b538SAndroid Build Coastguard Worker *
6*6777b538SAndroid Build Coastguard Worker * Gary Pennington <[email protected]>
7*6777b538SAndroid Build Coastguard Worker * [email protected]
8*6777b538SAndroid Build Coastguard Worker */
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #define IN_LIBXML
11*6777b538SAndroid Build Coastguard Worker #include "libxml.h"
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include <string.h>
14*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker #include <libxml/threads.h>
17*6777b538SAndroid Build Coastguard Worker #include <libxml/parser.h>
18*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_CATALOG_ENABLED
19*6777b538SAndroid Build Coastguard Worker #include <libxml/catalog.h>
20*6777b538SAndroid Build Coastguard Worker #endif
21*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_SCHEMAS_ENABLED
22*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlschemastypes.h>
23*6777b538SAndroid Build Coastguard Worker #include <libxml/relaxng.h>
24*6777b538SAndroid Build Coastguard Worker #endif
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Worker #if defined(SOLARIS)
27*6777b538SAndroid Build Coastguard Worker #include <note.h>
28*6777b538SAndroid Build Coastguard Worker #endif
29*6777b538SAndroid Build Coastguard Worker
30*6777b538SAndroid Build Coastguard Worker #include "private/dict.h"
31*6777b538SAndroid Build Coastguard Worker #include "private/enc.h"
32*6777b538SAndroid Build Coastguard Worker #include "private/globals.h"
33*6777b538SAndroid Build Coastguard Worker #include "private/io.h"
34*6777b538SAndroid Build Coastguard Worker #include "private/memory.h"
35*6777b538SAndroid Build Coastguard Worker #include "private/threads.h"
36*6777b538SAndroid Build Coastguard Worker #include "private/xpath.h"
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker #if defined(HAVE_POSIX_THREADS) && \
39*6777b538SAndroid Build Coastguard Worker defined(__GLIBC__) && \
40*6777b538SAndroid Build Coastguard Worker __GLIBC__ * 100 + __GLIBC_MINOR__ >= 234
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker /*
43*6777b538SAndroid Build Coastguard Worker * The modern way available since glibc 2.32.
44*6777b538SAndroid Build Coastguard Worker *
45*6777b538SAndroid Build Coastguard Worker * The check above is for glibc 2.34 which merged the pthread symbols into
46*6777b538SAndroid Build Coastguard Worker * libc. Since we still allow linking without pthread symbols (see below),
47*6777b538SAndroid Build Coastguard Worker * this only works if pthread symbols are guaranteed to be available.
48*6777b538SAndroid Build Coastguard Worker */
49*6777b538SAndroid Build Coastguard Worker
50*6777b538SAndroid Build Coastguard Worker #include <sys/single_threaded.h>
51*6777b538SAndroid Build Coastguard Worker
52*6777b538SAndroid Build Coastguard Worker #define XML_IS_THREADED() (!__libc_single_threaded)
53*6777b538SAndroid Build Coastguard Worker #define XML_IS_NEVER_THREADED() 0
54*6777b538SAndroid Build Coastguard Worker
55*6777b538SAndroid Build Coastguard Worker #elif defined(HAVE_POSIX_THREADS) && \
56*6777b538SAndroid Build Coastguard Worker defined(__GLIBC__) && \
57*6777b538SAndroid Build Coastguard Worker defined(__GNUC__)
58*6777b538SAndroid Build Coastguard Worker
59*6777b538SAndroid Build Coastguard Worker /*
60*6777b538SAndroid Build Coastguard Worker * The traditional way to check for single-threaded applications with
61*6777b538SAndroid Build Coastguard Worker * glibc was to check whether the separate libpthread library is
62*6777b538SAndroid Build Coastguard Worker * linked in. This works by not linking libxml2 with libpthread (see
63*6777b538SAndroid Build Coastguard Worker * BASE_THREAD_LIBS in configure.ac and Makefile.am) and declaring
64*6777b538SAndroid Build Coastguard Worker * pthread functions as weak symbols.
65*6777b538SAndroid Build Coastguard Worker *
66*6777b538SAndroid Build Coastguard Worker * In glibc 2.34, the pthread symbols were moved from libpthread to libc,
67*6777b538SAndroid Build Coastguard Worker * so this doesn't work anymore.
68*6777b538SAndroid Build Coastguard Worker *
69*6777b538SAndroid Build Coastguard Worker * At some point, this legacy code and the BASE_THREAD_LIBS hack in
70*6777b538SAndroid Build Coastguard Worker * configure.ac can probably be removed.
71*6777b538SAndroid Build Coastguard Worker */
72*6777b538SAndroid Build Coastguard Worker
73*6777b538SAndroid Build Coastguard Worker #pragma weak pthread_mutex_init
74*6777b538SAndroid Build Coastguard Worker #pragma weak pthread_mutex_destroy
75*6777b538SAndroid Build Coastguard Worker #pragma weak pthread_mutex_lock
76*6777b538SAndroid Build Coastguard Worker #pragma weak pthread_mutex_unlock
77*6777b538SAndroid Build Coastguard Worker #pragma weak pthread_cond_init
78*6777b538SAndroid Build Coastguard Worker #pragma weak pthread_cond_destroy
79*6777b538SAndroid Build Coastguard Worker #pragma weak pthread_cond_wait
80*6777b538SAndroid Build Coastguard Worker #pragma weak pthread_equal
81*6777b538SAndroid Build Coastguard Worker #pragma weak pthread_self
82*6777b538SAndroid Build Coastguard Worker #pragma weak pthread_cond_signal
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker #define XML_PTHREAD_WEAK
85*6777b538SAndroid Build Coastguard Worker #define XML_IS_THREADED() libxml_is_threaded
86*6777b538SAndroid Build Coastguard Worker #define XML_IS_NEVER_THREADED() (!libxml_is_threaded)
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker static int libxml_is_threaded = -1;
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Worker #else /* other POSIX platforms */
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker #define XML_IS_THREADED() 1
93*6777b538SAndroid Build Coastguard Worker #define XML_IS_NEVER_THREADED() 0
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker #endif
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker /*
98*6777b538SAndroid Build Coastguard Worker * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree
99*6777b538SAndroid Build Coastguard Worker * to avoid some craziness since xmlMalloc/xmlFree may actually
100*6777b538SAndroid Build Coastguard Worker * be hosted on allocated blocks needing them for the allocation ...
101*6777b538SAndroid Build Coastguard Worker */
102*6777b538SAndroid Build Coastguard Worker
103*6777b538SAndroid Build Coastguard Worker /*
104*6777b538SAndroid Build Coastguard Worker * xmlRMutex are reentrant mutual exception locks
105*6777b538SAndroid Build Coastguard Worker */
106*6777b538SAndroid Build Coastguard Worker struct _xmlRMutex {
107*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
108*6777b538SAndroid Build Coastguard Worker pthread_mutex_t lock;
109*6777b538SAndroid Build Coastguard Worker unsigned int held;
110*6777b538SAndroid Build Coastguard Worker unsigned int waiters;
111*6777b538SAndroid Build Coastguard Worker pthread_t tid;
112*6777b538SAndroid Build Coastguard Worker pthread_cond_t cv;
113*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
114*6777b538SAndroid Build Coastguard Worker CRITICAL_SECTION cs;
115*6777b538SAndroid Build Coastguard Worker #else
116*6777b538SAndroid Build Coastguard Worker int empty;
117*6777b538SAndroid Build Coastguard Worker #endif
118*6777b538SAndroid Build Coastguard Worker };
119*6777b538SAndroid Build Coastguard Worker
120*6777b538SAndroid Build Coastguard Worker static xmlRMutexPtr xmlLibraryLock = NULL;
121*6777b538SAndroid Build Coastguard Worker
122*6777b538SAndroid Build Coastguard Worker /**
123*6777b538SAndroid Build Coastguard Worker * xmlInitMutex:
124*6777b538SAndroid Build Coastguard Worker * @mutex: the mutex
125*6777b538SAndroid Build Coastguard Worker *
126*6777b538SAndroid Build Coastguard Worker * Initialize a mutex.
127*6777b538SAndroid Build Coastguard Worker */
128*6777b538SAndroid Build Coastguard Worker void
xmlInitMutex(xmlMutexPtr mutex)129*6777b538SAndroid Build Coastguard Worker xmlInitMutex(xmlMutexPtr mutex)
130*6777b538SAndroid Build Coastguard Worker {
131*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
132*6777b538SAndroid Build Coastguard Worker if (XML_IS_NEVER_THREADED() == 0)
133*6777b538SAndroid Build Coastguard Worker pthread_mutex_init(&mutex->lock, NULL);
134*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
135*6777b538SAndroid Build Coastguard Worker InitializeCriticalSection(&mutex->cs);
136*6777b538SAndroid Build Coastguard Worker #else
137*6777b538SAndroid Build Coastguard Worker (void) mutex;
138*6777b538SAndroid Build Coastguard Worker #endif
139*6777b538SAndroid Build Coastguard Worker }
140*6777b538SAndroid Build Coastguard Worker
141*6777b538SAndroid Build Coastguard Worker /**
142*6777b538SAndroid Build Coastguard Worker * xmlNewMutex:
143*6777b538SAndroid Build Coastguard Worker *
144*6777b538SAndroid Build Coastguard Worker * xmlNewMutex() is used to allocate a libxml2 token struct for use in
145*6777b538SAndroid Build Coastguard Worker * synchronizing access to data.
146*6777b538SAndroid Build Coastguard Worker *
147*6777b538SAndroid Build Coastguard Worker * Returns a new simple mutex pointer or NULL in case of error
148*6777b538SAndroid Build Coastguard Worker */
149*6777b538SAndroid Build Coastguard Worker xmlMutexPtr
xmlNewMutex(void)150*6777b538SAndroid Build Coastguard Worker xmlNewMutex(void)
151*6777b538SAndroid Build Coastguard Worker {
152*6777b538SAndroid Build Coastguard Worker xmlMutexPtr tok;
153*6777b538SAndroid Build Coastguard Worker
154*6777b538SAndroid Build Coastguard Worker if ((tok = malloc(sizeof(xmlMutex))) == NULL)
155*6777b538SAndroid Build Coastguard Worker return (NULL);
156*6777b538SAndroid Build Coastguard Worker xmlInitMutex(tok);
157*6777b538SAndroid Build Coastguard Worker return (tok);
158*6777b538SAndroid Build Coastguard Worker }
159*6777b538SAndroid Build Coastguard Worker
160*6777b538SAndroid Build Coastguard Worker /**
161*6777b538SAndroid Build Coastguard Worker * xmlCleanupMutex:
162*6777b538SAndroid Build Coastguard Worker * @mutex: the simple mutex
163*6777b538SAndroid Build Coastguard Worker *
164*6777b538SAndroid Build Coastguard Worker * Reclaim resources associated with a mutex.
165*6777b538SAndroid Build Coastguard Worker */
166*6777b538SAndroid Build Coastguard Worker void
xmlCleanupMutex(xmlMutexPtr mutex)167*6777b538SAndroid Build Coastguard Worker xmlCleanupMutex(xmlMutexPtr mutex)
168*6777b538SAndroid Build Coastguard Worker {
169*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
170*6777b538SAndroid Build Coastguard Worker if (XML_IS_NEVER_THREADED() == 0)
171*6777b538SAndroid Build Coastguard Worker pthread_mutex_destroy(&mutex->lock);
172*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
173*6777b538SAndroid Build Coastguard Worker DeleteCriticalSection(&mutex->cs);
174*6777b538SAndroid Build Coastguard Worker #else
175*6777b538SAndroid Build Coastguard Worker (void) mutex;
176*6777b538SAndroid Build Coastguard Worker #endif
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker
179*6777b538SAndroid Build Coastguard Worker /**
180*6777b538SAndroid Build Coastguard Worker * xmlFreeMutex:
181*6777b538SAndroid Build Coastguard Worker * @tok: the simple mutex
182*6777b538SAndroid Build Coastguard Worker *
183*6777b538SAndroid Build Coastguard Worker * Free a mutex.
184*6777b538SAndroid Build Coastguard Worker */
185*6777b538SAndroid Build Coastguard Worker void
xmlFreeMutex(xmlMutexPtr tok)186*6777b538SAndroid Build Coastguard Worker xmlFreeMutex(xmlMutexPtr tok)
187*6777b538SAndroid Build Coastguard Worker {
188*6777b538SAndroid Build Coastguard Worker if (tok == NULL)
189*6777b538SAndroid Build Coastguard Worker return;
190*6777b538SAndroid Build Coastguard Worker
191*6777b538SAndroid Build Coastguard Worker xmlCleanupMutex(tok);
192*6777b538SAndroid Build Coastguard Worker free(tok);
193*6777b538SAndroid Build Coastguard Worker }
194*6777b538SAndroid Build Coastguard Worker
195*6777b538SAndroid Build Coastguard Worker /**
196*6777b538SAndroid Build Coastguard Worker * xmlMutexLock:
197*6777b538SAndroid Build Coastguard Worker * @tok: the simple mutex
198*6777b538SAndroid Build Coastguard Worker *
199*6777b538SAndroid Build Coastguard Worker * xmlMutexLock() is used to lock a libxml2 token.
200*6777b538SAndroid Build Coastguard Worker */
201*6777b538SAndroid Build Coastguard Worker void
xmlMutexLock(xmlMutexPtr tok)202*6777b538SAndroid Build Coastguard Worker xmlMutexLock(xmlMutexPtr tok)
203*6777b538SAndroid Build Coastguard Worker {
204*6777b538SAndroid Build Coastguard Worker if (tok == NULL)
205*6777b538SAndroid Build Coastguard Worker return;
206*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
207*6777b538SAndroid Build Coastguard Worker /*
208*6777b538SAndroid Build Coastguard Worker * This assumes that __libc_single_threaded won't change while the
209*6777b538SAndroid Build Coastguard Worker * lock is held.
210*6777b538SAndroid Build Coastguard Worker */
211*6777b538SAndroid Build Coastguard Worker if (XML_IS_THREADED() != 0)
212*6777b538SAndroid Build Coastguard Worker pthread_mutex_lock(&tok->lock);
213*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
214*6777b538SAndroid Build Coastguard Worker EnterCriticalSection(&tok->cs);
215*6777b538SAndroid Build Coastguard Worker #endif
216*6777b538SAndroid Build Coastguard Worker
217*6777b538SAndroid Build Coastguard Worker }
218*6777b538SAndroid Build Coastguard Worker
219*6777b538SAndroid Build Coastguard Worker /**
220*6777b538SAndroid Build Coastguard Worker * xmlMutexUnlock:
221*6777b538SAndroid Build Coastguard Worker * @tok: the simple mutex
222*6777b538SAndroid Build Coastguard Worker *
223*6777b538SAndroid Build Coastguard Worker * xmlMutexUnlock() is used to unlock a libxml2 token.
224*6777b538SAndroid Build Coastguard Worker */
225*6777b538SAndroid Build Coastguard Worker void
xmlMutexUnlock(xmlMutexPtr tok)226*6777b538SAndroid Build Coastguard Worker xmlMutexUnlock(xmlMutexPtr tok)
227*6777b538SAndroid Build Coastguard Worker {
228*6777b538SAndroid Build Coastguard Worker if (tok == NULL)
229*6777b538SAndroid Build Coastguard Worker return;
230*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
231*6777b538SAndroid Build Coastguard Worker if (XML_IS_THREADED() != 0)
232*6777b538SAndroid Build Coastguard Worker pthread_mutex_unlock(&tok->lock);
233*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
234*6777b538SAndroid Build Coastguard Worker LeaveCriticalSection(&tok->cs);
235*6777b538SAndroid Build Coastguard Worker #endif
236*6777b538SAndroid Build Coastguard Worker }
237*6777b538SAndroid Build Coastguard Worker
238*6777b538SAndroid Build Coastguard Worker /**
239*6777b538SAndroid Build Coastguard Worker * xmlNewRMutex:
240*6777b538SAndroid Build Coastguard Worker *
241*6777b538SAndroid Build Coastguard Worker * xmlRNewMutex() is used to allocate a reentrant mutex for use in
242*6777b538SAndroid Build Coastguard Worker * synchronizing access to data. token_r is a re-entrant lock and thus useful
243*6777b538SAndroid Build Coastguard Worker * for synchronizing access to data structures that may be manipulated in a
244*6777b538SAndroid Build Coastguard Worker * recursive fashion.
245*6777b538SAndroid Build Coastguard Worker *
246*6777b538SAndroid Build Coastguard Worker * Returns the new reentrant mutex pointer or NULL in case of error
247*6777b538SAndroid Build Coastguard Worker */
248*6777b538SAndroid Build Coastguard Worker xmlRMutexPtr
xmlNewRMutex(void)249*6777b538SAndroid Build Coastguard Worker xmlNewRMutex(void)
250*6777b538SAndroid Build Coastguard Worker {
251*6777b538SAndroid Build Coastguard Worker xmlRMutexPtr tok;
252*6777b538SAndroid Build Coastguard Worker
253*6777b538SAndroid Build Coastguard Worker if ((tok = malloc(sizeof(xmlRMutex))) == NULL)
254*6777b538SAndroid Build Coastguard Worker return (NULL);
255*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
256*6777b538SAndroid Build Coastguard Worker if (XML_IS_NEVER_THREADED() == 0) {
257*6777b538SAndroid Build Coastguard Worker pthread_mutex_init(&tok->lock, NULL);
258*6777b538SAndroid Build Coastguard Worker tok->held = 0;
259*6777b538SAndroid Build Coastguard Worker tok->waiters = 0;
260*6777b538SAndroid Build Coastguard Worker pthread_cond_init(&tok->cv, NULL);
261*6777b538SAndroid Build Coastguard Worker }
262*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
263*6777b538SAndroid Build Coastguard Worker InitializeCriticalSection(&tok->cs);
264*6777b538SAndroid Build Coastguard Worker #endif
265*6777b538SAndroid Build Coastguard Worker return (tok);
266*6777b538SAndroid Build Coastguard Worker }
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Worker /**
269*6777b538SAndroid Build Coastguard Worker * xmlFreeRMutex:
270*6777b538SAndroid Build Coastguard Worker * @tok: the reentrant mutex
271*6777b538SAndroid Build Coastguard Worker *
272*6777b538SAndroid Build Coastguard Worker * xmlRFreeMutex() is used to reclaim resources associated with a
273*6777b538SAndroid Build Coastguard Worker * reentrant mutex.
274*6777b538SAndroid Build Coastguard Worker */
275*6777b538SAndroid Build Coastguard Worker void
xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)276*6777b538SAndroid Build Coastguard Worker xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
277*6777b538SAndroid Build Coastguard Worker {
278*6777b538SAndroid Build Coastguard Worker if (tok == NULL)
279*6777b538SAndroid Build Coastguard Worker return;
280*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
281*6777b538SAndroid Build Coastguard Worker if (XML_IS_NEVER_THREADED() == 0) {
282*6777b538SAndroid Build Coastguard Worker pthread_mutex_destroy(&tok->lock);
283*6777b538SAndroid Build Coastguard Worker pthread_cond_destroy(&tok->cv);
284*6777b538SAndroid Build Coastguard Worker }
285*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
286*6777b538SAndroid Build Coastguard Worker DeleteCriticalSection(&tok->cs);
287*6777b538SAndroid Build Coastguard Worker #endif
288*6777b538SAndroid Build Coastguard Worker free(tok);
289*6777b538SAndroid Build Coastguard Worker }
290*6777b538SAndroid Build Coastguard Worker
291*6777b538SAndroid Build Coastguard Worker /**
292*6777b538SAndroid Build Coastguard Worker * xmlRMutexLock:
293*6777b538SAndroid Build Coastguard Worker * @tok: the reentrant mutex
294*6777b538SAndroid Build Coastguard Worker *
295*6777b538SAndroid Build Coastguard Worker * xmlRMutexLock() is used to lock a libxml2 token_r.
296*6777b538SAndroid Build Coastguard Worker */
297*6777b538SAndroid Build Coastguard Worker void
xmlRMutexLock(xmlRMutexPtr tok)298*6777b538SAndroid Build Coastguard Worker xmlRMutexLock(xmlRMutexPtr tok)
299*6777b538SAndroid Build Coastguard Worker {
300*6777b538SAndroid Build Coastguard Worker if (tok == NULL)
301*6777b538SAndroid Build Coastguard Worker return;
302*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
303*6777b538SAndroid Build Coastguard Worker if (XML_IS_THREADED() == 0)
304*6777b538SAndroid Build Coastguard Worker return;
305*6777b538SAndroid Build Coastguard Worker
306*6777b538SAndroid Build Coastguard Worker pthread_mutex_lock(&tok->lock);
307*6777b538SAndroid Build Coastguard Worker if (tok->held) {
308*6777b538SAndroid Build Coastguard Worker if (pthread_equal(tok->tid, pthread_self())) {
309*6777b538SAndroid Build Coastguard Worker tok->held++;
310*6777b538SAndroid Build Coastguard Worker pthread_mutex_unlock(&tok->lock);
311*6777b538SAndroid Build Coastguard Worker return;
312*6777b538SAndroid Build Coastguard Worker } else {
313*6777b538SAndroid Build Coastguard Worker tok->waiters++;
314*6777b538SAndroid Build Coastguard Worker while (tok->held)
315*6777b538SAndroid Build Coastguard Worker pthread_cond_wait(&tok->cv, &tok->lock);
316*6777b538SAndroid Build Coastguard Worker tok->waiters--;
317*6777b538SAndroid Build Coastguard Worker }
318*6777b538SAndroid Build Coastguard Worker }
319*6777b538SAndroid Build Coastguard Worker tok->tid = pthread_self();
320*6777b538SAndroid Build Coastguard Worker tok->held = 1;
321*6777b538SAndroid Build Coastguard Worker pthread_mutex_unlock(&tok->lock);
322*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
323*6777b538SAndroid Build Coastguard Worker EnterCriticalSection(&tok->cs);
324*6777b538SAndroid Build Coastguard Worker #endif
325*6777b538SAndroid Build Coastguard Worker }
326*6777b538SAndroid Build Coastguard Worker
327*6777b538SAndroid Build Coastguard Worker /**
328*6777b538SAndroid Build Coastguard Worker * xmlRMutexUnlock:
329*6777b538SAndroid Build Coastguard Worker * @tok: the reentrant mutex
330*6777b538SAndroid Build Coastguard Worker *
331*6777b538SAndroid Build Coastguard Worker * xmlRMutexUnlock() is used to unlock a libxml2 token_r.
332*6777b538SAndroid Build Coastguard Worker */
333*6777b538SAndroid Build Coastguard Worker void
xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)334*6777b538SAndroid Build Coastguard Worker xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
335*6777b538SAndroid Build Coastguard Worker {
336*6777b538SAndroid Build Coastguard Worker if (tok == NULL)
337*6777b538SAndroid Build Coastguard Worker return;
338*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
339*6777b538SAndroid Build Coastguard Worker if (XML_IS_THREADED() == 0)
340*6777b538SAndroid Build Coastguard Worker return;
341*6777b538SAndroid Build Coastguard Worker
342*6777b538SAndroid Build Coastguard Worker pthread_mutex_lock(&tok->lock);
343*6777b538SAndroid Build Coastguard Worker tok->held--;
344*6777b538SAndroid Build Coastguard Worker if (tok->held == 0) {
345*6777b538SAndroid Build Coastguard Worker if (tok->waiters)
346*6777b538SAndroid Build Coastguard Worker pthread_cond_signal(&tok->cv);
347*6777b538SAndroid Build Coastguard Worker memset(&tok->tid, 0, sizeof(tok->tid));
348*6777b538SAndroid Build Coastguard Worker }
349*6777b538SAndroid Build Coastguard Worker pthread_mutex_unlock(&tok->lock);
350*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
351*6777b538SAndroid Build Coastguard Worker LeaveCriticalSection(&tok->cs);
352*6777b538SAndroid Build Coastguard Worker #endif
353*6777b538SAndroid Build Coastguard Worker }
354*6777b538SAndroid Build Coastguard Worker
355*6777b538SAndroid Build Coastguard Worker /************************************************************************
356*6777b538SAndroid Build Coastguard Worker * *
357*6777b538SAndroid Build Coastguard Worker * Library wide thread interfaces *
358*6777b538SAndroid Build Coastguard Worker * *
359*6777b538SAndroid Build Coastguard Worker ************************************************************************/
360*6777b538SAndroid Build Coastguard Worker
361*6777b538SAndroid Build Coastguard Worker /**
362*6777b538SAndroid Build Coastguard Worker * xmlGetThreadId:
363*6777b538SAndroid Build Coastguard Worker *
364*6777b538SAndroid Build Coastguard Worker * DEPRECATED: Internal function, do not use.
365*6777b538SAndroid Build Coastguard Worker *
366*6777b538SAndroid Build Coastguard Worker * xmlGetThreadId() find the current thread ID number
367*6777b538SAndroid Build Coastguard Worker * Note that this is likely to be broken on some platforms using pthreads
368*6777b538SAndroid Build Coastguard Worker * as the specification doesn't mandate pthread_t to be an integer type
369*6777b538SAndroid Build Coastguard Worker *
370*6777b538SAndroid Build Coastguard Worker * Returns the current thread ID number
371*6777b538SAndroid Build Coastguard Worker */
372*6777b538SAndroid Build Coastguard Worker int
xmlGetThreadId(void)373*6777b538SAndroid Build Coastguard Worker xmlGetThreadId(void)
374*6777b538SAndroid Build Coastguard Worker {
375*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
376*6777b538SAndroid Build Coastguard Worker pthread_t id;
377*6777b538SAndroid Build Coastguard Worker int ret;
378*6777b538SAndroid Build Coastguard Worker
379*6777b538SAndroid Build Coastguard Worker if (XML_IS_THREADED() == 0)
380*6777b538SAndroid Build Coastguard Worker return (0);
381*6777b538SAndroid Build Coastguard Worker id = pthread_self();
382*6777b538SAndroid Build Coastguard Worker /* horrible but preserves compat, see warning above */
383*6777b538SAndroid Build Coastguard Worker memcpy(&ret, &id, sizeof(ret));
384*6777b538SAndroid Build Coastguard Worker return (ret);
385*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
386*6777b538SAndroid Build Coastguard Worker return GetCurrentThreadId();
387*6777b538SAndroid Build Coastguard Worker #else
388*6777b538SAndroid Build Coastguard Worker return ((int) 0);
389*6777b538SAndroid Build Coastguard Worker #endif
390*6777b538SAndroid Build Coastguard Worker }
391*6777b538SAndroid Build Coastguard Worker
392*6777b538SAndroid Build Coastguard Worker /**
393*6777b538SAndroid Build Coastguard Worker * xmlLockLibrary:
394*6777b538SAndroid Build Coastguard Worker *
395*6777b538SAndroid Build Coastguard Worker * xmlLockLibrary() is used to take out a re-entrant lock on the libxml2
396*6777b538SAndroid Build Coastguard Worker * library.
397*6777b538SAndroid Build Coastguard Worker */
398*6777b538SAndroid Build Coastguard Worker void
xmlLockLibrary(void)399*6777b538SAndroid Build Coastguard Worker xmlLockLibrary(void)
400*6777b538SAndroid Build Coastguard Worker {
401*6777b538SAndroid Build Coastguard Worker xmlRMutexLock(xmlLibraryLock);
402*6777b538SAndroid Build Coastguard Worker }
403*6777b538SAndroid Build Coastguard Worker
404*6777b538SAndroid Build Coastguard Worker /**
405*6777b538SAndroid Build Coastguard Worker * xmlUnlockLibrary:
406*6777b538SAndroid Build Coastguard Worker *
407*6777b538SAndroid Build Coastguard Worker * xmlUnlockLibrary() is used to release a re-entrant lock on the libxml2
408*6777b538SAndroid Build Coastguard Worker * library.
409*6777b538SAndroid Build Coastguard Worker */
410*6777b538SAndroid Build Coastguard Worker void
xmlUnlockLibrary(void)411*6777b538SAndroid Build Coastguard Worker xmlUnlockLibrary(void)
412*6777b538SAndroid Build Coastguard Worker {
413*6777b538SAndroid Build Coastguard Worker xmlRMutexUnlock(xmlLibraryLock);
414*6777b538SAndroid Build Coastguard Worker }
415*6777b538SAndroid Build Coastguard Worker
416*6777b538SAndroid Build Coastguard Worker /**
417*6777b538SAndroid Build Coastguard Worker * xmlInitThreads:
418*6777b538SAndroid Build Coastguard Worker *
419*6777b538SAndroid Build Coastguard Worker * DEPRECATED: Alias for xmlInitParser.
420*6777b538SAndroid Build Coastguard Worker */
421*6777b538SAndroid Build Coastguard Worker void
xmlInitThreads(void)422*6777b538SAndroid Build Coastguard Worker xmlInitThreads(void)
423*6777b538SAndroid Build Coastguard Worker {
424*6777b538SAndroid Build Coastguard Worker xmlInitParser();
425*6777b538SAndroid Build Coastguard Worker }
426*6777b538SAndroid Build Coastguard Worker
427*6777b538SAndroid Build Coastguard Worker /**
428*6777b538SAndroid Build Coastguard Worker * xmlCleanupThreads:
429*6777b538SAndroid Build Coastguard Worker *
430*6777b538SAndroid Build Coastguard Worker * DEPRECATED: This function is a no-op. Call xmlCleanupParser
431*6777b538SAndroid Build Coastguard Worker * to free global state but see the warnings there. xmlCleanupParser
432*6777b538SAndroid Build Coastguard Worker * should be only called once at program exit. In most cases, you don't
433*6777b538SAndroid Build Coastguard Worker * have call cleanup functions at all.
434*6777b538SAndroid Build Coastguard Worker */
435*6777b538SAndroid Build Coastguard Worker void
xmlCleanupThreads(void)436*6777b538SAndroid Build Coastguard Worker xmlCleanupThreads(void)
437*6777b538SAndroid Build Coastguard Worker {
438*6777b538SAndroid Build Coastguard Worker }
439*6777b538SAndroid Build Coastguard Worker
440*6777b538SAndroid Build Coastguard Worker /************************************************************************
441*6777b538SAndroid Build Coastguard Worker * *
442*6777b538SAndroid Build Coastguard Worker * Library wide initialization *
443*6777b538SAndroid Build Coastguard Worker * *
444*6777b538SAndroid Build Coastguard Worker ************************************************************************/
445*6777b538SAndroid Build Coastguard Worker
446*6777b538SAndroid Build Coastguard Worker static int xmlParserInitialized = 0;
447*6777b538SAndroid Build Coastguard Worker static int xmlParserInnerInitialized = 0;
448*6777b538SAndroid Build Coastguard Worker
449*6777b538SAndroid Build Coastguard Worker
450*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
451*6777b538SAndroid Build Coastguard Worker static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
452*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
453*6777b538SAndroid Build Coastguard Worker static volatile LPCRITICAL_SECTION global_init_lock = NULL;
454*6777b538SAndroid Build Coastguard Worker #endif
455*6777b538SAndroid Build Coastguard Worker
456*6777b538SAndroid Build Coastguard Worker /**
457*6777b538SAndroid Build Coastguard Worker * xmlGlobalInitMutexLock
458*6777b538SAndroid Build Coastguard Worker *
459*6777b538SAndroid Build Coastguard Worker * Makes sure that the global initialization mutex is initialized and
460*6777b538SAndroid Build Coastguard Worker * locks it.
461*6777b538SAndroid Build Coastguard Worker */
462*6777b538SAndroid Build Coastguard Worker static void
xmlGlobalInitMutexLock(void)463*6777b538SAndroid Build Coastguard Worker xmlGlobalInitMutexLock(void) {
464*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
465*6777b538SAndroid Build Coastguard Worker
466*6777b538SAndroid Build Coastguard Worker #ifdef XML_PTHREAD_WEAK
467*6777b538SAndroid Build Coastguard Worker /*
468*6777b538SAndroid Build Coastguard Worker * This is somewhat unreliable since libpthread could be loaded
469*6777b538SAndroid Build Coastguard Worker * later with dlopen() and threads could be created. But it's
470*6777b538SAndroid Build Coastguard Worker * long-standing behavior and hard to work around.
471*6777b538SAndroid Build Coastguard Worker */
472*6777b538SAndroid Build Coastguard Worker if (libxml_is_threaded == -1)
473*6777b538SAndroid Build Coastguard Worker libxml_is_threaded =
474*6777b538SAndroid Build Coastguard Worker (pthread_mutex_init != NULL) &&
475*6777b538SAndroid Build Coastguard Worker (pthread_mutex_destroy != NULL) &&
476*6777b538SAndroid Build Coastguard Worker (pthread_mutex_lock != NULL) &&
477*6777b538SAndroid Build Coastguard Worker (pthread_mutex_unlock != NULL) &&
478*6777b538SAndroid Build Coastguard Worker (pthread_cond_init != NULL) &&
479*6777b538SAndroid Build Coastguard Worker (pthread_cond_destroy != NULL) &&
480*6777b538SAndroid Build Coastguard Worker (pthread_cond_wait != NULL) &&
481*6777b538SAndroid Build Coastguard Worker /*
482*6777b538SAndroid Build Coastguard Worker * pthread_equal can be inline, resuting in -Waddress warnings.
483*6777b538SAndroid Build Coastguard Worker * Let's assume it's available if all the other functions are.
484*6777b538SAndroid Build Coastguard Worker */
485*6777b538SAndroid Build Coastguard Worker /* (pthread_equal != NULL) && */
486*6777b538SAndroid Build Coastguard Worker (pthread_self != NULL) &&
487*6777b538SAndroid Build Coastguard Worker (pthread_cond_signal != NULL);
488*6777b538SAndroid Build Coastguard Worker #endif
489*6777b538SAndroid Build Coastguard Worker
490*6777b538SAndroid Build Coastguard Worker /* The mutex is statically initialized, so we just lock it. */
491*6777b538SAndroid Build Coastguard Worker if (XML_IS_THREADED() != 0)
492*6777b538SAndroid Build Coastguard Worker pthread_mutex_lock(&global_init_lock);
493*6777b538SAndroid Build Coastguard Worker
494*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
495*6777b538SAndroid Build Coastguard Worker
496*6777b538SAndroid Build Coastguard Worker LPCRITICAL_SECTION cs;
497*6777b538SAndroid Build Coastguard Worker
498*6777b538SAndroid Build Coastguard Worker /* Create a new critical section */
499*6777b538SAndroid Build Coastguard Worker if (global_init_lock == NULL) {
500*6777b538SAndroid Build Coastguard Worker cs = malloc(sizeof(CRITICAL_SECTION));
501*6777b538SAndroid Build Coastguard Worker if (cs == NULL) {
502*6777b538SAndroid Build Coastguard Worker fprintf(stderr, "libxml2: xmlInitParser: out of memory\n");
503*6777b538SAndroid Build Coastguard Worker abort();
504*6777b538SAndroid Build Coastguard Worker }
505*6777b538SAndroid Build Coastguard Worker InitializeCriticalSection(cs);
506*6777b538SAndroid Build Coastguard Worker
507*6777b538SAndroid Build Coastguard Worker /* Swap it into the global_init_lock */
508*6777b538SAndroid Build Coastguard Worker #ifdef InterlockedCompareExchangePointer
509*6777b538SAndroid Build Coastguard Worker InterlockedCompareExchangePointer((void **) &global_init_lock,
510*6777b538SAndroid Build Coastguard Worker cs, NULL);
511*6777b538SAndroid Build Coastguard Worker #else /* Use older void* version */
512*6777b538SAndroid Build Coastguard Worker InterlockedCompareExchange((void **) &global_init_lock,
513*6777b538SAndroid Build Coastguard Worker (void *) cs, NULL);
514*6777b538SAndroid Build Coastguard Worker #endif /* InterlockedCompareExchangePointer */
515*6777b538SAndroid Build Coastguard Worker
516*6777b538SAndroid Build Coastguard Worker /* If another thread successfully recorded its critical
517*6777b538SAndroid Build Coastguard Worker * section in the global_init_lock then discard the one
518*6777b538SAndroid Build Coastguard Worker * allocated by this thread. */
519*6777b538SAndroid Build Coastguard Worker if (global_init_lock != cs) {
520*6777b538SAndroid Build Coastguard Worker DeleteCriticalSection(cs);
521*6777b538SAndroid Build Coastguard Worker free(cs);
522*6777b538SAndroid Build Coastguard Worker }
523*6777b538SAndroid Build Coastguard Worker }
524*6777b538SAndroid Build Coastguard Worker
525*6777b538SAndroid Build Coastguard Worker /* Lock the chosen critical section */
526*6777b538SAndroid Build Coastguard Worker EnterCriticalSection(global_init_lock);
527*6777b538SAndroid Build Coastguard Worker
528*6777b538SAndroid Build Coastguard Worker #endif
529*6777b538SAndroid Build Coastguard Worker }
530*6777b538SAndroid Build Coastguard Worker
531*6777b538SAndroid Build Coastguard Worker static void
xmlGlobalInitMutexUnlock(void)532*6777b538SAndroid Build Coastguard Worker xmlGlobalInitMutexUnlock(void) {
533*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
534*6777b538SAndroid Build Coastguard Worker if (XML_IS_THREADED() != 0)
535*6777b538SAndroid Build Coastguard Worker pthread_mutex_unlock(&global_init_lock);
536*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
537*6777b538SAndroid Build Coastguard Worker if (global_init_lock != NULL)
538*6777b538SAndroid Build Coastguard Worker LeaveCriticalSection(global_init_lock);
539*6777b538SAndroid Build Coastguard Worker #endif
540*6777b538SAndroid Build Coastguard Worker }
541*6777b538SAndroid Build Coastguard Worker
542*6777b538SAndroid Build Coastguard Worker /**
543*6777b538SAndroid Build Coastguard Worker * xmlGlobalInitMutexDestroy
544*6777b538SAndroid Build Coastguard Worker *
545*6777b538SAndroid Build Coastguard Worker * Makes sure that the global initialization mutex is destroyed before
546*6777b538SAndroid Build Coastguard Worker * application termination.
547*6777b538SAndroid Build Coastguard Worker */
548*6777b538SAndroid Build Coastguard Worker static void
xmlGlobalInitMutexDestroy(void)549*6777b538SAndroid Build Coastguard Worker xmlGlobalInitMutexDestroy(void) {
550*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
551*6777b538SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
552*6777b538SAndroid Build Coastguard Worker if (global_init_lock != NULL) {
553*6777b538SAndroid Build Coastguard Worker DeleteCriticalSection(global_init_lock);
554*6777b538SAndroid Build Coastguard Worker free(global_init_lock);
555*6777b538SAndroid Build Coastguard Worker global_init_lock = NULL;
556*6777b538SAndroid Build Coastguard Worker }
557*6777b538SAndroid Build Coastguard Worker #endif
558*6777b538SAndroid Build Coastguard Worker }
559*6777b538SAndroid Build Coastguard Worker
560*6777b538SAndroid Build Coastguard Worker /**
561*6777b538SAndroid Build Coastguard Worker * xmlInitParser:
562*6777b538SAndroid Build Coastguard Worker *
563*6777b538SAndroid Build Coastguard Worker * Initialization function for the XML parser.
564*6777b538SAndroid Build Coastguard Worker *
565*6777b538SAndroid Build Coastguard Worker * Call once from the main thread before using the library in
566*6777b538SAndroid Build Coastguard Worker * multithreaded programs.
567*6777b538SAndroid Build Coastguard Worker */
568*6777b538SAndroid Build Coastguard Worker void
xmlInitParser(void)569*6777b538SAndroid Build Coastguard Worker xmlInitParser(void) {
570*6777b538SAndroid Build Coastguard Worker /*
571*6777b538SAndroid Build Coastguard Worker * Note that the initialization code must not make memory allocations.
572*6777b538SAndroid Build Coastguard Worker */
573*6777b538SAndroid Build Coastguard Worker if (xmlParserInitialized != 0)
574*6777b538SAndroid Build Coastguard Worker return;
575*6777b538SAndroid Build Coastguard Worker
576*6777b538SAndroid Build Coastguard Worker xmlGlobalInitMutexLock();
577*6777b538SAndroid Build Coastguard Worker
578*6777b538SAndroid Build Coastguard Worker if (xmlParserInnerInitialized == 0) {
579*6777b538SAndroid Build Coastguard Worker #if defined(_WIN32) && \
580*6777b538SAndroid Build Coastguard Worker !defined(LIBXML_THREAD_ALLOC_ENABLED) && \
581*6777b538SAndroid Build Coastguard Worker (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
582*6777b538SAndroid Build Coastguard Worker if (xmlFree == free)
583*6777b538SAndroid Build Coastguard Worker atexit(xmlCleanupParser);
584*6777b538SAndroid Build Coastguard Worker #endif
585*6777b538SAndroid Build Coastguard Worker
586*6777b538SAndroid Build Coastguard Worker xmlInitRandom(); /* Required by xmlInitGlobalsInternal */
587*6777b538SAndroid Build Coastguard Worker xmlInitMemoryInternal();
588*6777b538SAndroid Build Coastguard Worker xmlInitGlobalsInternal();
589*6777b538SAndroid Build Coastguard Worker xmlInitDictInternal();
590*6777b538SAndroid Build Coastguard Worker xmlInitEncodingInternal();
591*6777b538SAndroid Build Coastguard Worker #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
592*6777b538SAndroid Build Coastguard Worker xmlInitXPathInternal();
593*6777b538SAndroid Build Coastguard Worker #endif
594*6777b538SAndroid Build Coastguard Worker xmlInitIOCallbacks();
595*6777b538SAndroid Build Coastguard Worker
596*6777b538SAndroid Build Coastguard Worker xmlParserInnerInitialized = 1;
597*6777b538SAndroid Build Coastguard Worker }
598*6777b538SAndroid Build Coastguard Worker
599*6777b538SAndroid Build Coastguard Worker xmlGlobalInitMutexUnlock();
600*6777b538SAndroid Build Coastguard Worker
601*6777b538SAndroid Build Coastguard Worker xmlParserInitialized = 1;
602*6777b538SAndroid Build Coastguard Worker }
603*6777b538SAndroid Build Coastguard Worker
604*6777b538SAndroid Build Coastguard Worker /**
605*6777b538SAndroid Build Coastguard Worker * xmlCleanupParser:
606*6777b538SAndroid Build Coastguard Worker *
607*6777b538SAndroid Build Coastguard Worker * This function name is somewhat misleading. It does not clean up
608*6777b538SAndroid Build Coastguard Worker * parser state, it cleans up memory allocated by the library itself.
609*6777b538SAndroid Build Coastguard Worker * It is a cleanup function for the XML library. It tries to reclaim all
610*6777b538SAndroid Build Coastguard Worker * related global memory allocated for the library processing.
611*6777b538SAndroid Build Coastguard Worker * It doesn't deallocate any document related memory. One should
612*6777b538SAndroid Build Coastguard Worker * call xmlCleanupParser() only when the process has finished using
613*6777b538SAndroid Build Coastguard Worker * the library and all XML/HTML documents built with it.
614*6777b538SAndroid Build Coastguard Worker * See also xmlInitParser() which has the opposite function of preparing
615*6777b538SAndroid Build Coastguard Worker * the library for operations.
616*6777b538SAndroid Build Coastguard Worker *
617*6777b538SAndroid Build Coastguard Worker * WARNING: if your application is multithreaded or has plugin support
618*6777b538SAndroid Build Coastguard Worker * calling this may crash the application if another thread or
619*6777b538SAndroid Build Coastguard Worker * a plugin is still using libxml2. It's sometimes very hard to
620*6777b538SAndroid Build Coastguard Worker * guess if libxml2 is in use in the application, some libraries
621*6777b538SAndroid Build Coastguard Worker * or plugins may use it without notice. In case of doubt abstain
622*6777b538SAndroid Build Coastguard Worker * from calling this function or do it just before calling exit()
623*6777b538SAndroid Build Coastguard Worker * to avoid leak reports from valgrind !
624*6777b538SAndroid Build Coastguard Worker */
625*6777b538SAndroid Build Coastguard Worker void
xmlCleanupParser(void)626*6777b538SAndroid Build Coastguard Worker xmlCleanupParser(void) {
627*6777b538SAndroid Build Coastguard Worker if (!xmlParserInitialized)
628*6777b538SAndroid Build Coastguard Worker return;
629*6777b538SAndroid Build Coastguard Worker
630*6777b538SAndroid Build Coastguard Worker /* These functions can call xmlFree. */
631*6777b538SAndroid Build Coastguard Worker
632*6777b538SAndroid Build Coastguard Worker xmlCleanupCharEncodingHandlers();
633*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_CATALOG_ENABLED
634*6777b538SAndroid Build Coastguard Worker xmlCatalogCleanup();
635*6777b538SAndroid Build Coastguard Worker #endif
636*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_SCHEMAS_ENABLED
637*6777b538SAndroid Build Coastguard Worker xmlSchemaCleanupTypes();
638*6777b538SAndroid Build Coastguard Worker xmlRelaxNGCleanupTypes();
639*6777b538SAndroid Build Coastguard Worker #endif
640*6777b538SAndroid Build Coastguard Worker
641*6777b538SAndroid Build Coastguard Worker /* These functions should never call xmlFree. */
642*6777b538SAndroid Build Coastguard Worker
643*6777b538SAndroid Build Coastguard Worker xmlCleanupDictInternal();
644*6777b538SAndroid Build Coastguard Worker xmlCleanupRandom();
645*6777b538SAndroid Build Coastguard Worker xmlCleanupGlobalsInternal();
646*6777b538SAndroid Build Coastguard Worker /*
647*6777b538SAndroid Build Coastguard Worker * Must come last. On Windows, xmlCleanupGlobalsInternal can call
648*6777b538SAndroid Build Coastguard Worker * xmlFree which uses xmlMemMutex in debug mode.
649*6777b538SAndroid Build Coastguard Worker */
650*6777b538SAndroid Build Coastguard Worker xmlCleanupMemoryInternal();
651*6777b538SAndroid Build Coastguard Worker
652*6777b538SAndroid Build Coastguard Worker xmlGlobalInitMutexDestroy();
653*6777b538SAndroid Build Coastguard Worker
654*6777b538SAndroid Build Coastguard Worker xmlParserInitialized = 0;
655*6777b538SAndroid Build Coastguard Worker xmlParserInnerInitialized = 0;
656*6777b538SAndroid Build Coastguard Worker }
657*6777b538SAndroid Build Coastguard Worker
658*6777b538SAndroid Build Coastguard Worker #if defined(HAVE_ATTRIBUTE_DESTRUCTOR) && \
659*6777b538SAndroid Build Coastguard Worker !defined(LIBXML_THREAD_ALLOC_ENABLED) && \
660*6777b538SAndroid Build Coastguard Worker !defined(LIBXML_STATIC) && \
661*6777b538SAndroid Build Coastguard Worker !defined(_WIN32)
662*6777b538SAndroid Build Coastguard Worker static void
663*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_DESTRUCTOR
xmlDestructor(void)664*6777b538SAndroid Build Coastguard Worker xmlDestructor(void) {
665*6777b538SAndroid Build Coastguard Worker /*
666*6777b538SAndroid Build Coastguard Worker * Calling custom deallocation functions in a destructor can cause
667*6777b538SAndroid Build Coastguard Worker * problems, for example with Nokogiri.
668*6777b538SAndroid Build Coastguard Worker */
669*6777b538SAndroid Build Coastguard Worker if (xmlFree == free)
670*6777b538SAndroid Build Coastguard Worker xmlCleanupParser();
671*6777b538SAndroid Build Coastguard Worker }
672*6777b538SAndroid Build Coastguard Worker #endif
673*6777b538SAndroid Build Coastguard Worker
674