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