xref: /aosp_15_r20/external/libxml2/threads.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1*7c568831SAndroid Build Coastguard Worker /**
2*7c568831SAndroid Build Coastguard Worker  * threads.c: set of generic threading related routines
3*7c568831SAndroid Build Coastguard Worker  *
4*7c568831SAndroid Build Coastguard Worker  * See Copyright for the status of this software.
5*7c568831SAndroid Build Coastguard Worker  *
6*7c568831SAndroid Build Coastguard Worker  * Gary Pennington <[email protected]>
7*7c568831SAndroid Build Coastguard Worker  * [email protected]
8*7c568831SAndroid Build Coastguard Worker  */
9*7c568831SAndroid Build Coastguard Worker 
10*7c568831SAndroid Build Coastguard Worker #define IN_LIBXML
11*7c568831SAndroid Build Coastguard Worker #include "libxml.h"
12*7c568831SAndroid Build Coastguard Worker 
13*7c568831SAndroid Build Coastguard Worker #include <string.h>
14*7c568831SAndroid Build Coastguard Worker #include <stdarg.h>
15*7c568831SAndroid Build Coastguard Worker #include <stdlib.h>
16*7c568831SAndroid Build Coastguard Worker 
17*7c568831SAndroid Build Coastguard Worker #include <libxml/threads.h>
18*7c568831SAndroid Build Coastguard Worker #include <libxml/parser.h>
19*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_CATALOG_ENABLED
20*7c568831SAndroid Build Coastguard Worker #include <libxml/catalog.h>
21*7c568831SAndroid Build Coastguard Worker #endif
22*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_SCHEMAS_ENABLED
23*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlschemastypes.h>
24*7c568831SAndroid Build Coastguard Worker #include <libxml/relaxng.h>
25*7c568831SAndroid Build Coastguard Worker #endif
26*7c568831SAndroid Build Coastguard Worker 
27*7c568831SAndroid Build Coastguard Worker #if defined(SOLARIS)
28*7c568831SAndroid Build Coastguard Worker #include <note.h>
29*7c568831SAndroid Build Coastguard Worker #endif
30*7c568831SAndroid Build Coastguard Worker 
31*7c568831SAndroid Build Coastguard Worker #include "private/cata.h"
32*7c568831SAndroid Build Coastguard Worker #include "private/dict.h"
33*7c568831SAndroid Build Coastguard Worker #include "private/enc.h"
34*7c568831SAndroid Build Coastguard Worker #include "private/error.h"
35*7c568831SAndroid Build Coastguard Worker #include "private/globals.h"
36*7c568831SAndroid Build Coastguard Worker #include "private/io.h"
37*7c568831SAndroid Build Coastguard Worker #include "private/memory.h"
38*7c568831SAndroid Build Coastguard Worker #include "private/threads.h"
39*7c568831SAndroid Build Coastguard Worker #include "private/xpath.h"
40*7c568831SAndroid Build Coastguard Worker 
41*7c568831SAndroid Build Coastguard Worker /*
42*7c568831SAndroid Build Coastguard Worker  * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree
43*7c568831SAndroid Build Coastguard Worker  *       to avoid some craziness since xmlMalloc/xmlFree may actually
44*7c568831SAndroid Build Coastguard Worker  *       be hosted on allocated blocks needing them for the allocation ...
45*7c568831SAndroid Build Coastguard Worker  */
46*7c568831SAndroid Build Coastguard Worker 
47*7c568831SAndroid Build Coastguard Worker static xmlRMutex xmlLibraryLock;
48*7c568831SAndroid Build Coastguard Worker 
49*7c568831SAndroid Build Coastguard Worker /**
50*7c568831SAndroid Build Coastguard Worker  * xmlInitMutex:
51*7c568831SAndroid Build Coastguard Worker  * @mutex:  the mutex
52*7c568831SAndroid Build Coastguard Worker  *
53*7c568831SAndroid Build Coastguard Worker  * Initialize a mutex.
54*7c568831SAndroid Build Coastguard Worker  */
55*7c568831SAndroid Build Coastguard Worker void
xmlInitMutex(xmlMutexPtr mutex)56*7c568831SAndroid Build Coastguard Worker xmlInitMutex(xmlMutexPtr mutex)
57*7c568831SAndroid Build Coastguard Worker {
58*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
59*7c568831SAndroid Build Coastguard Worker     pthread_mutex_init(&mutex->lock, NULL);
60*7c568831SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
61*7c568831SAndroid Build Coastguard Worker     InitializeCriticalSection(&mutex->cs);
62*7c568831SAndroid Build Coastguard Worker #else
63*7c568831SAndroid Build Coastguard Worker     (void) mutex;
64*7c568831SAndroid Build Coastguard Worker #endif
65*7c568831SAndroid Build Coastguard Worker }
66*7c568831SAndroid Build Coastguard Worker 
67*7c568831SAndroid Build Coastguard Worker /**
68*7c568831SAndroid Build Coastguard Worker  * xmlNewMutex:
69*7c568831SAndroid Build Coastguard Worker  *
70*7c568831SAndroid Build Coastguard Worker  * xmlNewMutex() is used to allocate a libxml2 token struct for use in
71*7c568831SAndroid Build Coastguard Worker  * synchronizing access to data.
72*7c568831SAndroid Build Coastguard Worker  *
73*7c568831SAndroid Build Coastguard Worker  * Returns a new simple mutex pointer or NULL in case of error
74*7c568831SAndroid Build Coastguard Worker  */
75*7c568831SAndroid Build Coastguard Worker xmlMutexPtr
xmlNewMutex(void)76*7c568831SAndroid Build Coastguard Worker xmlNewMutex(void)
77*7c568831SAndroid Build Coastguard Worker {
78*7c568831SAndroid Build Coastguard Worker     xmlMutexPtr tok;
79*7c568831SAndroid Build Coastguard Worker 
80*7c568831SAndroid Build Coastguard Worker     tok = malloc(sizeof(xmlMutex));
81*7c568831SAndroid Build Coastguard Worker     if (tok == NULL)
82*7c568831SAndroid Build Coastguard Worker         return (NULL);
83*7c568831SAndroid Build Coastguard Worker     xmlInitMutex(tok);
84*7c568831SAndroid Build Coastguard Worker     return (tok);
85*7c568831SAndroid Build Coastguard Worker }
86*7c568831SAndroid Build Coastguard Worker 
87*7c568831SAndroid Build Coastguard Worker /**
88*7c568831SAndroid Build Coastguard Worker  * xmlCleanupMutex:
89*7c568831SAndroid Build Coastguard Worker  * @mutex:  the simple mutex
90*7c568831SAndroid Build Coastguard Worker  *
91*7c568831SAndroid Build Coastguard Worker  * Reclaim resources associated with a mutex.
92*7c568831SAndroid Build Coastguard Worker  */
93*7c568831SAndroid Build Coastguard Worker void
xmlCleanupMutex(xmlMutexPtr mutex)94*7c568831SAndroid Build Coastguard Worker xmlCleanupMutex(xmlMutexPtr mutex)
95*7c568831SAndroid Build Coastguard Worker {
96*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
97*7c568831SAndroid Build Coastguard Worker     pthread_mutex_destroy(&mutex->lock);
98*7c568831SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
99*7c568831SAndroid Build Coastguard Worker     DeleteCriticalSection(&mutex->cs);
100*7c568831SAndroid Build Coastguard Worker #else
101*7c568831SAndroid Build Coastguard Worker     (void) mutex;
102*7c568831SAndroid Build Coastguard Worker #endif
103*7c568831SAndroid Build Coastguard Worker }
104*7c568831SAndroid Build Coastguard Worker 
105*7c568831SAndroid Build Coastguard Worker /**
106*7c568831SAndroid Build Coastguard Worker  * xmlFreeMutex:
107*7c568831SAndroid Build Coastguard Worker  * @tok:  the simple mutex
108*7c568831SAndroid Build Coastguard Worker  *
109*7c568831SAndroid Build Coastguard Worker  * Free a mutex.
110*7c568831SAndroid Build Coastguard Worker  */
111*7c568831SAndroid Build Coastguard Worker void
xmlFreeMutex(xmlMutexPtr tok)112*7c568831SAndroid Build Coastguard Worker xmlFreeMutex(xmlMutexPtr tok)
113*7c568831SAndroid Build Coastguard Worker {
114*7c568831SAndroid Build Coastguard Worker     if (tok == NULL)
115*7c568831SAndroid Build Coastguard Worker         return;
116*7c568831SAndroid Build Coastguard Worker 
117*7c568831SAndroid Build Coastguard Worker     xmlCleanupMutex(tok);
118*7c568831SAndroid Build Coastguard Worker     free(tok);
119*7c568831SAndroid Build Coastguard Worker }
120*7c568831SAndroid Build Coastguard Worker 
121*7c568831SAndroid Build Coastguard Worker /**
122*7c568831SAndroid Build Coastguard Worker  * xmlMutexLock:
123*7c568831SAndroid Build Coastguard Worker  * @tok:  the simple mutex
124*7c568831SAndroid Build Coastguard Worker  *
125*7c568831SAndroid Build Coastguard Worker  * xmlMutexLock() is used to lock a libxml2 token.
126*7c568831SAndroid Build Coastguard Worker  */
127*7c568831SAndroid Build Coastguard Worker void
xmlMutexLock(xmlMutexPtr tok)128*7c568831SAndroid Build Coastguard Worker xmlMutexLock(xmlMutexPtr tok)
129*7c568831SAndroid Build Coastguard Worker {
130*7c568831SAndroid Build Coastguard Worker     if (tok == NULL)
131*7c568831SAndroid Build Coastguard Worker         return;
132*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
133*7c568831SAndroid Build Coastguard Worker     /*
134*7c568831SAndroid Build Coastguard Worker      * This assumes that __libc_single_threaded won't change while the
135*7c568831SAndroid Build Coastguard Worker      * lock is held.
136*7c568831SAndroid Build Coastguard Worker      */
137*7c568831SAndroid Build Coastguard Worker     pthread_mutex_lock(&tok->lock);
138*7c568831SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
139*7c568831SAndroid Build Coastguard Worker     EnterCriticalSection(&tok->cs);
140*7c568831SAndroid Build Coastguard Worker #endif
141*7c568831SAndroid Build Coastguard Worker 
142*7c568831SAndroid Build Coastguard Worker }
143*7c568831SAndroid Build Coastguard Worker 
144*7c568831SAndroid Build Coastguard Worker /**
145*7c568831SAndroid Build Coastguard Worker  * xmlMutexUnlock:
146*7c568831SAndroid Build Coastguard Worker  * @tok:  the simple mutex
147*7c568831SAndroid Build Coastguard Worker  *
148*7c568831SAndroid Build Coastguard Worker  * xmlMutexUnlock() is used to unlock a libxml2 token.
149*7c568831SAndroid Build Coastguard Worker  */
150*7c568831SAndroid Build Coastguard Worker void
xmlMutexUnlock(xmlMutexPtr tok)151*7c568831SAndroid Build Coastguard Worker xmlMutexUnlock(xmlMutexPtr tok)
152*7c568831SAndroid Build Coastguard Worker {
153*7c568831SAndroid Build Coastguard Worker     if (tok == NULL)
154*7c568831SAndroid Build Coastguard Worker         return;
155*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
156*7c568831SAndroid Build Coastguard Worker     pthread_mutex_unlock(&tok->lock);
157*7c568831SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
158*7c568831SAndroid Build Coastguard Worker     LeaveCriticalSection(&tok->cs);
159*7c568831SAndroid Build Coastguard Worker #endif
160*7c568831SAndroid Build Coastguard Worker }
161*7c568831SAndroid Build Coastguard Worker 
162*7c568831SAndroid Build Coastguard Worker void
xmlInitRMutex(xmlRMutexPtr tok)163*7c568831SAndroid Build Coastguard Worker xmlInitRMutex(xmlRMutexPtr tok) {
164*7c568831SAndroid Build Coastguard Worker     (void) tok;
165*7c568831SAndroid Build Coastguard Worker 
166*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
167*7c568831SAndroid Build Coastguard Worker     pthread_mutex_init(&tok->lock, NULL);
168*7c568831SAndroid Build Coastguard Worker     tok->held = 0;
169*7c568831SAndroid Build Coastguard Worker     tok->waiters = 0;
170*7c568831SAndroid Build Coastguard Worker     pthread_cond_init(&tok->cv, NULL);
171*7c568831SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
172*7c568831SAndroid Build Coastguard Worker     InitializeCriticalSection(&tok->cs);
173*7c568831SAndroid Build Coastguard Worker #endif
174*7c568831SAndroid Build Coastguard Worker }
175*7c568831SAndroid Build Coastguard Worker 
176*7c568831SAndroid Build Coastguard Worker /**
177*7c568831SAndroid Build Coastguard Worker  * xmlNewRMutex:
178*7c568831SAndroid Build Coastguard Worker  *
179*7c568831SAndroid Build Coastguard Worker  * xmlRNewMutex() is used to allocate a reentrant mutex for use in
180*7c568831SAndroid Build Coastguard Worker  * synchronizing access to data. token_r is a re-entrant lock and thus useful
181*7c568831SAndroid Build Coastguard Worker  * for synchronizing access to data structures that may be manipulated in a
182*7c568831SAndroid Build Coastguard Worker  * recursive fashion.
183*7c568831SAndroid Build Coastguard Worker  *
184*7c568831SAndroid Build Coastguard Worker  * Returns the new reentrant mutex pointer or NULL in case of error
185*7c568831SAndroid Build Coastguard Worker  */
186*7c568831SAndroid Build Coastguard Worker xmlRMutexPtr
xmlNewRMutex(void)187*7c568831SAndroid Build Coastguard Worker xmlNewRMutex(void)
188*7c568831SAndroid Build Coastguard Worker {
189*7c568831SAndroid Build Coastguard Worker     xmlRMutexPtr tok;
190*7c568831SAndroid Build Coastguard Worker 
191*7c568831SAndroid Build Coastguard Worker     tok = malloc(sizeof(xmlRMutex));
192*7c568831SAndroid Build Coastguard Worker     if (tok == NULL)
193*7c568831SAndroid Build Coastguard Worker         return (NULL);
194*7c568831SAndroid Build Coastguard Worker     xmlInitRMutex(tok);
195*7c568831SAndroid Build Coastguard Worker     return (tok);
196*7c568831SAndroid Build Coastguard Worker }
197*7c568831SAndroid Build Coastguard Worker 
198*7c568831SAndroid Build Coastguard Worker void
xmlCleanupRMutex(xmlRMutexPtr tok)199*7c568831SAndroid Build Coastguard Worker xmlCleanupRMutex(xmlRMutexPtr tok) {
200*7c568831SAndroid Build Coastguard Worker     (void) tok;
201*7c568831SAndroid Build Coastguard Worker 
202*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
203*7c568831SAndroid Build Coastguard Worker     pthread_mutex_destroy(&tok->lock);
204*7c568831SAndroid Build Coastguard Worker     pthread_cond_destroy(&tok->cv);
205*7c568831SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
206*7c568831SAndroid Build Coastguard Worker     DeleteCriticalSection(&tok->cs);
207*7c568831SAndroid Build Coastguard Worker #endif
208*7c568831SAndroid Build Coastguard Worker }
209*7c568831SAndroid Build Coastguard Worker 
210*7c568831SAndroid Build Coastguard Worker /**
211*7c568831SAndroid Build Coastguard Worker  * xmlFreeRMutex:
212*7c568831SAndroid Build Coastguard Worker  * @tok:  the reentrant mutex
213*7c568831SAndroid Build Coastguard Worker  *
214*7c568831SAndroid Build Coastguard Worker  * xmlRFreeMutex() is used to reclaim resources associated with a
215*7c568831SAndroid Build Coastguard Worker  * reentrant mutex.
216*7c568831SAndroid Build Coastguard Worker  */
217*7c568831SAndroid Build Coastguard Worker void
xmlFreeRMutex(xmlRMutexPtr tok)218*7c568831SAndroid Build Coastguard Worker xmlFreeRMutex(xmlRMutexPtr tok)
219*7c568831SAndroid Build Coastguard Worker {
220*7c568831SAndroid Build Coastguard Worker     if (tok == NULL)
221*7c568831SAndroid Build Coastguard Worker         return;
222*7c568831SAndroid Build Coastguard Worker     xmlCleanupRMutex(tok);
223*7c568831SAndroid Build Coastguard Worker     free(tok);
224*7c568831SAndroid Build Coastguard Worker }
225*7c568831SAndroid Build Coastguard Worker 
226*7c568831SAndroid Build Coastguard Worker /**
227*7c568831SAndroid Build Coastguard Worker  * xmlRMutexLock:
228*7c568831SAndroid Build Coastguard Worker  * @tok:  the reentrant mutex
229*7c568831SAndroid Build Coastguard Worker  *
230*7c568831SAndroid Build Coastguard Worker  * xmlRMutexLock() is used to lock a libxml2 token_r.
231*7c568831SAndroid Build Coastguard Worker  */
232*7c568831SAndroid Build Coastguard Worker void
xmlRMutexLock(xmlRMutexPtr tok)233*7c568831SAndroid Build Coastguard Worker xmlRMutexLock(xmlRMutexPtr tok)
234*7c568831SAndroid Build Coastguard Worker {
235*7c568831SAndroid Build Coastguard Worker     if (tok == NULL)
236*7c568831SAndroid Build Coastguard Worker         return;
237*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
238*7c568831SAndroid Build Coastguard Worker     pthread_mutex_lock(&tok->lock);
239*7c568831SAndroid Build Coastguard Worker     if (tok->held) {
240*7c568831SAndroid Build Coastguard Worker         if (pthread_equal(tok->tid, pthread_self())) {
241*7c568831SAndroid Build Coastguard Worker             tok->held++;
242*7c568831SAndroid Build Coastguard Worker             pthread_mutex_unlock(&tok->lock);
243*7c568831SAndroid Build Coastguard Worker             return;
244*7c568831SAndroid Build Coastguard Worker         } else {
245*7c568831SAndroid Build Coastguard Worker             tok->waiters++;
246*7c568831SAndroid Build Coastguard Worker             while (tok->held)
247*7c568831SAndroid Build Coastguard Worker                 pthread_cond_wait(&tok->cv, &tok->lock);
248*7c568831SAndroid Build Coastguard Worker             tok->waiters--;
249*7c568831SAndroid Build Coastguard Worker         }
250*7c568831SAndroid Build Coastguard Worker     }
251*7c568831SAndroid Build Coastguard Worker     tok->tid = pthread_self();
252*7c568831SAndroid Build Coastguard Worker     tok->held = 1;
253*7c568831SAndroid Build Coastguard Worker     pthread_mutex_unlock(&tok->lock);
254*7c568831SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
255*7c568831SAndroid Build Coastguard Worker     EnterCriticalSection(&tok->cs);
256*7c568831SAndroid Build Coastguard Worker #endif
257*7c568831SAndroid Build Coastguard Worker }
258*7c568831SAndroid Build Coastguard Worker 
259*7c568831SAndroid Build Coastguard Worker /**
260*7c568831SAndroid Build Coastguard Worker  * xmlRMutexUnlock:
261*7c568831SAndroid Build Coastguard Worker  * @tok:  the reentrant mutex
262*7c568831SAndroid Build Coastguard Worker  *
263*7c568831SAndroid Build Coastguard Worker  * xmlRMutexUnlock() is used to unlock a libxml2 token_r.
264*7c568831SAndroid Build Coastguard Worker  */
265*7c568831SAndroid Build Coastguard Worker void
xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)266*7c568831SAndroid Build Coastguard Worker xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
267*7c568831SAndroid Build Coastguard Worker {
268*7c568831SAndroid Build Coastguard Worker     if (tok == NULL)
269*7c568831SAndroid Build Coastguard Worker         return;
270*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
271*7c568831SAndroid Build Coastguard Worker     pthread_mutex_lock(&tok->lock);
272*7c568831SAndroid Build Coastguard Worker     tok->held--;
273*7c568831SAndroid Build Coastguard Worker     if (tok->held == 0) {
274*7c568831SAndroid Build Coastguard Worker         if (tok->waiters)
275*7c568831SAndroid Build Coastguard Worker             pthread_cond_signal(&tok->cv);
276*7c568831SAndroid Build Coastguard Worker         memset(&tok->tid, 0, sizeof(tok->tid));
277*7c568831SAndroid Build Coastguard Worker     }
278*7c568831SAndroid Build Coastguard Worker     pthread_mutex_unlock(&tok->lock);
279*7c568831SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
280*7c568831SAndroid Build Coastguard Worker     LeaveCriticalSection(&tok->cs);
281*7c568831SAndroid Build Coastguard Worker #endif
282*7c568831SAndroid Build Coastguard Worker }
283*7c568831SAndroid Build Coastguard Worker 
284*7c568831SAndroid Build Coastguard Worker /************************************************************************
285*7c568831SAndroid Build Coastguard Worker  *									*
286*7c568831SAndroid Build Coastguard Worker  *			Library wide thread interfaces			*
287*7c568831SAndroid Build Coastguard Worker  *									*
288*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
289*7c568831SAndroid Build Coastguard Worker 
290*7c568831SAndroid Build Coastguard Worker /**
291*7c568831SAndroid Build Coastguard Worker  * xmlGetThreadId:
292*7c568831SAndroid Build Coastguard Worker  *
293*7c568831SAndroid Build Coastguard Worker  * DEPRECATED: Internal function, do not use.
294*7c568831SAndroid Build Coastguard Worker  *
295*7c568831SAndroid Build Coastguard Worker  * xmlGetThreadId() find the current thread ID number
296*7c568831SAndroid Build Coastguard Worker  * Note that this is likely to be broken on some platforms using pthreads
297*7c568831SAndroid Build Coastguard Worker  * as the specification doesn't mandate pthread_t to be an integer type
298*7c568831SAndroid Build Coastguard Worker  *
299*7c568831SAndroid Build Coastguard Worker  * Returns the current thread ID number
300*7c568831SAndroid Build Coastguard Worker  */
301*7c568831SAndroid Build Coastguard Worker int
xmlGetThreadId(void)302*7c568831SAndroid Build Coastguard Worker xmlGetThreadId(void)
303*7c568831SAndroid Build Coastguard Worker {
304*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
305*7c568831SAndroid Build Coastguard Worker     pthread_t id;
306*7c568831SAndroid Build Coastguard Worker     int ret;
307*7c568831SAndroid Build Coastguard Worker 
308*7c568831SAndroid Build Coastguard Worker     id = pthread_self();
309*7c568831SAndroid Build Coastguard Worker     /* horrible but preserves compat, see warning above */
310*7c568831SAndroid Build Coastguard Worker     memcpy(&ret, &id, sizeof(ret));
311*7c568831SAndroid Build Coastguard Worker     return (ret);
312*7c568831SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
313*7c568831SAndroid Build Coastguard Worker     return GetCurrentThreadId();
314*7c568831SAndroid Build Coastguard Worker #else
315*7c568831SAndroid Build Coastguard Worker     return ((int) 0);
316*7c568831SAndroid Build Coastguard Worker #endif
317*7c568831SAndroid Build Coastguard Worker }
318*7c568831SAndroid Build Coastguard Worker 
319*7c568831SAndroid Build Coastguard Worker /**
320*7c568831SAndroid Build Coastguard Worker  * xmlLockLibrary:
321*7c568831SAndroid Build Coastguard Worker  *
322*7c568831SAndroid Build Coastguard Worker  * xmlLockLibrary() is used to take out a re-entrant lock on the libxml2
323*7c568831SAndroid Build Coastguard Worker  * library.
324*7c568831SAndroid Build Coastguard Worker  */
325*7c568831SAndroid Build Coastguard Worker void
xmlLockLibrary(void)326*7c568831SAndroid Build Coastguard Worker xmlLockLibrary(void)
327*7c568831SAndroid Build Coastguard Worker {
328*7c568831SAndroid Build Coastguard Worker     xmlRMutexLock(&xmlLibraryLock);
329*7c568831SAndroid Build Coastguard Worker }
330*7c568831SAndroid Build Coastguard Worker 
331*7c568831SAndroid Build Coastguard Worker /**
332*7c568831SAndroid Build Coastguard Worker  * xmlUnlockLibrary:
333*7c568831SAndroid Build Coastguard Worker  *
334*7c568831SAndroid Build Coastguard Worker  * xmlUnlockLibrary() is used to release a re-entrant lock on the libxml2
335*7c568831SAndroid Build Coastguard Worker  * library.
336*7c568831SAndroid Build Coastguard Worker  */
337*7c568831SAndroid Build Coastguard Worker void
xmlUnlockLibrary(void)338*7c568831SAndroid Build Coastguard Worker xmlUnlockLibrary(void)
339*7c568831SAndroid Build Coastguard Worker {
340*7c568831SAndroid Build Coastguard Worker     xmlRMutexUnlock(&xmlLibraryLock);
341*7c568831SAndroid Build Coastguard Worker }
342*7c568831SAndroid Build Coastguard Worker 
343*7c568831SAndroid Build Coastguard Worker /**
344*7c568831SAndroid Build Coastguard Worker  * xmlInitThreads:
345*7c568831SAndroid Build Coastguard Worker  *
346*7c568831SAndroid Build Coastguard Worker  * DEPRECATED: Alias for xmlInitParser.
347*7c568831SAndroid Build Coastguard Worker  */
348*7c568831SAndroid Build Coastguard Worker void
xmlInitThreads(void)349*7c568831SAndroid Build Coastguard Worker xmlInitThreads(void)
350*7c568831SAndroid Build Coastguard Worker {
351*7c568831SAndroid Build Coastguard Worker     xmlInitParser();
352*7c568831SAndroid Build Coastguard Worker }
353*7c568831SAndroid Build Coastguard Worker 
354*7c568831SAndroid Build Coastguard Worker /**
355*7c568831SAndroid Build Coastguard Worker  * xmlCleanupThreads:
356*7c568831SAndroid Build Coastguard Worker  *
357*7c568831SAndroid Build Coastguard Worker  * DEPRECATED: This function is a no-op. Call xmlCleanupParser
358*7c568831SAndroid Build Coastguard Worker  * to free global state but see the warnings there. xmlCleanupParser
359*7c568831SAndroid Build Coastguard Worker  * should be only called once at program exit. In most cases, you don't
360*7c568831SAndroid Build Coastguard Worker  * have call cleanup functions at all.
361*7c568831SAndroid Build Coastguard Worker  */
362*7c568831SAndroid Build Coastguard Worker void
xmlCleanupThreads(void)363*7c568831SAndroid Build Coastguard Worker xmlCleanupThreads(void)
364*7c568831SAndroid Build Coastguard Worker {
365*7c568831SAndroid Build Coastguard Worker }
366*7c568831SAndroid Build Coastguard Worker 
367*7c568831SAndroid Build Coastguard Worker static void
xmlInitThreadsInternal(void)368*7c568831SAndroid Build Coastguard Worker xmlInitThreadsInternal(void) {
369*7c568831SAndroid Build Coastguard Worker     xmlInitRMutex(&xmlLibraryLock);
370*7c568831SAndroid Build Coastguard Worker }
371*7c568831SAndroid Build Coastguard Worker 
372*7c568831SAndroid Build Coastguard Worker static void
xmlCleanupThreadsInternal(void)373*7c568831SAndroid Build Coastguard Worker xmlCleanupThreadsInternal(void) {
374*7c568831SAndroid Build Coastguard Worker     xmlCleanupRMutex(&xmlLibraryLock);
375*7c568831SAndroid Build Coastguard Worker }
376*7c568831SAndroid Build Coastguard Worker 
377*7c568831SAndroid Build Coastguard Worker /************************************************************************
378*7c568831SAndroid Build Coastguard Worker  *									*
379*7c568831SAndroid Build Coastguard Worker  *			Library wide initialization			*
380*7c568831SAndroid Build Coastguard Worker  *									*
381*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
382*7c568831SAndroid Build Coastguard Worker 
383*7c568831SAndroid Build Coastguard Worker static int xmlParserInitialized = 0;
384*7c568831SAndroid Build Coastguard Worker 
385*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
386*7c568831SAndroid Build Coastguard Worker static pthread_once_t onceControl = PTHREAD_ONCE_INIT;
387*7c568831SAndroid Build Coastguard Worker #elif defined HAVE_WIN32_THREADS
388*7c568831SAndroid Build Coastguard Worker static INIT_ONCE onceControl = INIT_ONCE_STATIC_INIT;
389*7c568831SAndroid Build Coastguard Worker #else
390*7c568831SAndroid Build Coastguard Worker static int onceControl = 0;
391*7c568831SAndroid Build Coastguard Worker #endif
392*7c568831SAndroid Build Coastguard Worker 
393*7c568831SAndroid Build Coastguard Worker static void
xmlInitParserInternal(void)394*7c568831SAndroid Build Coastguard Worker xmlInitParserInternal(void) {
395*7c568831SAndroid Build Coastguard Worker     /*
396*7c568831SAndroid Build Coastguard Worker      * Note that the initialization code must not make memory allocations.
397*7c568831SAndroid Build Coastguard Worker      */
398*7c568831SAndroid Build Coastguard Worker     xmlInitRandom(); /* Required by xmlInitGlobalsInternal */
399*7c568831SAndroid Build Coastguard Worker     xmlInitMemoryInternal();
400*7c568831SAndroid Build Coastguard Worker     xmlInitThreadsInternal();
401*7c568831SAndroid Build Coastguard Worker     xmlInitGlobalsInternal();
402*7c568831SAndroid Build Coastguard Worker     xmlInitDictInternal();
403*7c568831SAndroid Build Coastguard Worker     xmlInitEncodingInternal();
404*7c568831SAndroid Build Coastguard Worker #if defined(LIBXML_XPATH_ENABLED)
405*7c568831SAndroid Build Coastguard Worker     xmlInitXPathInternal();
406*7c568831SAndroid Build Coastguard Worker #endif
407*7c568831SAndroid Build Coastguard Worker     xmlInitIOCallbacks();
408*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_CATALOG_ENABLED
409*7c568831SAndroid Build Coastguard Worker     xmlInitCatalogInternal();
410*7c568831SAndroid Build Coastguard Worker #endif
411*7c568831SAndroid Build Coastguard Worker 
412*7c568831SAndroid Build Coastguard Worker     xmlParserInitialized = 1;
413*7c568831SAndroid Build Coastguard Worker }
414*7c568831SAndroid Build Coastguard Worker 
415*7c568831SAndroid Build Coastguard Worker #if defined(HAVE_WIN32_THREADS)
416*7c568831SAndroid Build Coastguard Worker static BOOL WINAPI
xmlInitParserWinWrapper(INIT_ONCE * initOnce ATTRIBUTE_UNUSED,void * parameter ATTRIBUTE_UNUSED,void ** context ATTRIBUTE_UNUSED)417*7c568831SAndroid Build Coastguard Worker xmlInitParserWinWrapper(INIT_ONCE *initOnce ATTRIBUTE_UNUSED,
418*7c568831SAndroid Build Coastguard Worker                         void *parameter ATTRIBUTE_UNUSED,
419*7c568831SAndroid Build Coastguard Worker                         void **context ATTRIBUTE_UNUSED) {
420*7c568831SAndroid Build Coastguard Worker     xmlInitParserInternal();
421*7c568831SAndroid Build Coastguard Worker     return(TRUE);
422*7c568831SAndroid Build Coastguard Worker }
423*7c568831SAndroid Build Coastguard Worker #endif
424*7c568831SAndroid Build Coastguard Worker 
425*7c568831SAndroid Build Coastguard Worker /**
426*7c568831SAndroid Build Coastguard Worker  * xmlInitParser:
427*7c568831SAndroid Build Coastguard Worker  *
428*7c568831SAndroid Build Coastguard Worker  * Initialization function for the XML parser.
429*7c568831SAndroid Build Coastguard Worker  *
430*7c568831SAndroid Build Coastguard Worker  * For older versions, it's recommended to call this function once
431*7c568831SAndroid Build Coastguard Worker  * from the main thread before using the library in multithreaded
432*7c568831SAndroid Build Coastguard Worker  * programs.
433*7c568831SAndroid Build Coastguard Worker  *
434*7c568831SAndroid Build Coastguard Worker  * Since 2.14.0, there's no distinction between threads. It should
435*7c568831SAndroid Build Coastguard Worker  * be unnecessary to call this function.
436*7c568831SAndroid Build Coastguard Worker  */
437*7c568831SAndroid Build Coastguard Worker void
xmlInitParser(void)438*7c568831SAndroid Build Coastguard Worker xmlInitParser(void) {
439*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
440*7c568831SAndroid Build Coastguard Worker     pthread_once(&onceControl, xmlInitParserInternal);
441*7c568831SAndroid Build Coastguard Worker #elif defined(HAVE_WIN32_THREADS)
442*7c568831SAndroid Build Coastguard Worker     InitOnceExecuteOnce(&onceControl, xmlInitParserWinWrapper, NULL, NULL);
443*7c568831SAndroid Build Coastguard Worker #else
444*7c568831SAndroid Build Coastguard Worker     if (onceControl == 0) {
445*7c568831SAndroid Build Coastguard Worker         xmlInitParserInternal();
446*7c568831SAndroid Build Coastguard Worker         onceControl = 1;
447*7c568831SAndroid Build Coastguard Worker     }
448*7c568831SAndroid Build Coastguard Worker #endif
449*7c568831SAndroid Build Coastguard Worker }
450*7c568831SAndroid Build Coastguard Worker 
451*7c568831SAndroid Build Coastguard Worker /**
452*7c568831SAndroid Build Coastguard Worker  * xmlCleanupParser:
453*7c568831SAndroid Build Coastguard Worker  *
454*7c568831SAndroid Build Coastguard Worker  * This function is named somewhat misleadingly. It does not clean up
455*7c568831SAndroid Build Coastguard Worker  * parser state but global memory allocated by the library itself.
456*7c568831SAndroid Build Coastguard Worker  *
457*7c568831SAndroid Build Coastguard Worker  * Since 2.9.11, cleanup is performed automatically if a shared or
458*7c568831SAndroid Build Coastguard Worker  * dynamic libxml2 library is unloaded. This function should only
459*7c568831SAndroid Build Coastguard Worker  * be used to avoid false positives from memory leak checkers in
460*7c568831SAndroid Build Coastguard Worker  * static builds.
461*7c568831SAndroid Build Coastguard Worker  *
462*7c568831SAndroid Build Coastguard Worker  * WARNING: xmlCleanupParser assumes that all other threads that called
463*7c568831SAndroid Build Coastguard Worker  * libxml2 functions have terminated. No library calls must be made
464*7c568831SAndroid Build Coastguard Worker  * after calling this function. In general, THIS FUNCTION SHOULD ONLY
465*7c568831SAndroid Build Coastguard Worker  * BE CALLED RIGHT BEFORE THE WHOLE PROCESS EXITS.
466*7c568831SAndroid Build Coastguard Worker  */
467*7c568831SAndroid Build Coastguard Worker void
xmlCleanupParser(void)468*7c568831SAndroid Build Coastguard Worker xmlCleanupParser(void) {
469*7c568831SAndroid Build Coastguard Worker     /*
470*7c568831SAndroid Build Coastguard Worker      * Unfortunately, some users call this function to fix memory
471*7c568831SAndroid Build Coastguard Worker      * leaks on unload with versions before 2.9.11. This can result
472*7c568831SAndroid Build Coastguard Worker      * in the library being reinitialized, so this use case must
473*7c568831SAndroid Build Coastguard Worker      * be supported.
474*7c568831SAndroid Build Coastguard Worker      */
475*7c568831SAndroid Build Coastguard Worker     if (!xmlParserInitialized)
476*7c568831SAndroid Build Coastguard Worker         return;
477*7c568831SAndroid Build Coastguard Worker 
478*7c568831SAndroid Build Coastguard Worker     xmlCleanupCharEncodingHandlers();
479*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_CATALOG_ENABLED
480*7c568831SAndroid Build Coastguard Worker     xmlCatalogCleanup();
481*7c568831SAndroid Build Coastguard Worker     xmlCleanupCatalogInternal();
482*7c568831SAndroid Build Coastguard Worker #endif
483*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_SCHEMAS_ENABLED
484*7c568831SAndroid Build Coastguard Worker     xmlSchemaCleanupTypes();
485*7c568831SAndroid Build Coastguard Worker     xmlRelaxNGCleanupTypes();
486*7c568831SAndroid Build Coastguard Worker #endif
487*7c568831SAndroid Build Coastguard Worker 
488*7c568831SAndroid Build Coastguard Worker     xmlCleanupDictInternal();
489*7c568831SAndroid Build Coastguard Worker     xmlCleanupRandom();
490*7c568831SAndroid Build Coastguard Worker     xmlCleanupGlobalsInternal();
491*7c568831SAndroid Build Coastguard Worker     xmlCleanupThreadsInternal();
492*7c568831SAndroid Build Coastguard Worker 
493*7c568831SAndroid Build Coastguard Worker     /*
494*7c568831SAndroid Build Coastguard Worker      * Must come after all cleanup functions that call xmlFree which
495*7c568831SAndroid Build Coastguard Worker      * uses xmlMemMutex in debug mode.
496*7c568831SAndroid Build Coastguard Worker      */
497*7c568831SAndroid Build Coastguard Worker     xmlCleanupMemoryInternal();
498*7c568831SAndroid Build Coastguard Worker 
499*7c568831SAndroid Build Coastguard Worker     xmlParserInitialized = 0;
500*7c568831SAndroid Build Coastguard Worker 
501*7c568831SAndroid Build Coastguard Worker     /*
502*7c568831SAndroid Build Coastguard Worker      * This is a bit sketchy but should make reinitialization work.
503*7c568831SAndroid Build Coastguard Worker      */
504*7c568831SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_THREADS
505*7c568831SAndroid Build Coastguard Worker     {
506*7c568831SAndroid Build Coastguard Worker         pthread_once_t tmp = PTHREAD_ONCE_INIT;
507*7c568831SAndroid Build Coastguard Worker         memcpy(&onceControl, &tmp, sizeof(tmp));
508*7c568831SAndroid Build Coastguard Worker     }
509*7c568831SAndroid Build Coastguard Worker #elif defined(HAVE_WIN32_THREADS)
510*7c568831SAndroid Build Coastguard Worker     {
511*7c568831SAndroid Build Coastguard Worker         INIT_ONCE tmp = INIT_ONCE_STATIC_INIT;
512*7c568831SAndroid Build Coastguard Worker         memcpy(&onceControl, &tmp, sizeof(tmp));
513*7c568831SAndroid Build Coastguard Worker     }
514*7c568831SAndroid Build Coastguard Worker #else
515*7c568831SAndroid Build Coastguard Worker     onceControl = 0;
516*7c568831SAndroid Build Coastguard Worker #endif
517*7c568831SAndroid Build Coastguard Worker }
518*7c568831SAndroid Build Coastguard Worker 
519*7c568831SAndroid Build Coastguard Worker #if defined(HAVE_FUNC_ATTRIBUTE_DESTRUCTOR) && \
520*7c568831SAndroid Build Coastguard Worker     !defined(LIBXML_THREAD_ALLOC_ENABLED) && \
521*7c568831SAndroid Build Coastguard Worker     !defined(LIBXML_STATIC) && \
522*7c568831SAndroid Build Coastguard Worker     !defined(_WIN32)
523*7c568831SAndroid Build Coastguard Worker static void
524*7c568831SAndroid Build Coastguard Worker ATTRIBUTE_DESTRUCTOR
xmlDestructor(void)525*7c568831SAndroid Build Coastguard Worker xmlDestructor(void) {
526*7c568831SAndroid Build Coastguard Worker     /*
527*7c568831SAndroid Build Coastguard Worker      * Calling custom deallocation functions in a destructor can cause
528*7c568831SAndroid Build Coastguard Worker      * problems, for example with Nokogiri.
529*7c568831SAndroid Build Coastguard Worker      */
530*7c568831SAndroid Build Coastguard Worker     if (xmlFree == free)
531*7c568831SAndroid Build Coastguard Worker         xmlCleanupParser();
532*7c568831SAndroid Build Coastguard Worker }
533*7c568831SAndroid Build Coastguard Worker #endif
534