xref: /aosp_15_r20/external/cronet/third_party/libxml/src/threads.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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