ReactOS 0.4.16-dev-303-g11d5cb8
threads.c
Go to the documentation of this file.
1
10#define IN_LIBXML
11#include "libxml.h"
12
13#include <string.h>
14#include <stdlib.h>
15
16#include <libxml/threads.h>
17#include <libxml/globals.h>
18
19#ifdef HAVE_PTHREAD_H
20#include <pthread.h>
21#elif defined HAVE_WIN32_THREADS
22#define WIN32_LEAN_AND_MEAN
23#include <windows.h>
24#ifndef HAVE_COMPILER_TLS
25#include <process.h>
26#endif
27#endif
28
29#ifdef HAVE_BEOS_THREADS
30#include <OS.h>
31#include <TLS.h>
32#endif
33
34#if defined(SOLARIS)
35#include <note.h>
36#endif
37
38/* #define DEBUG_THREADS */
39
40#ifdef HAVE_PTHREAD_H
41
42#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 303) && \
43 defined(__GLIBC__) && defined(__linux__)
44
45static int libxml_is_threaded = -1;
46
47#define XML_PTHREAD_WEAK
48
49#pragma weak pthread_once
50#pragma weak pthread_getspecific
51#pragma weak pthread_setspecific
52#pragma weak pthread_key_create
53#pragma weak pthread_key_delete
54#pragma weak pthread_mutex_init
55#pragma weak pthread_mutex_destroy
56#pragma weak pthread_mutex_lock
57#pragma weak pthread_mutex_unlock
58#pragma weak pthread_cond_init
59#pragma weak pthread_cond_destroy
60#pragma weak pthread_cond_wait
61#pragma weak pthread_equal
62#pragma weak pthread_self
63#pragma weak pthread_key_create
64#pragma weak pthread_key_delete
65#pragma weak pthread_cond_signal
66
67#else /* __GNUC__, __GLIBC__, __linux__ */
68
69static int libxml_is_threaded = 1;
70
71#endif /* __GNUC__, __GLIBC__, __linux__ */
72
73#endif /* HAVE_PTHREAD_H */
74
75/*
76 * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree
77 * to avoid some craziness since xmlMalloc/xmlFree may actually
78 * be hosted on allocated blocks needing them for the allocation ...
79 */
80
81/*
82 * xmlMutex are a simple mutual exception locks
83 */
84struct _xmlMutex {
85#ifdef HAVE_PTHREAD_H
86 pthread_mutex_t lock;
87#elif defined HAVE_WIN32_THREADS
89#elif defined HAVE_BEOS_THREADS
90 sem_id sem;
92#else
93 int empty;
94#endif
95};
96
97/*
98 * xmlRMutex are reentrant mutual exception locks
99 */
101#ifdef HAVE_PTHREAD_H
102 pthread_mutex_t lock;
103 unsigned int held;
104 unsigned int waiters;
105 pthread_t tid;
106 pthread_cond_t cv;
107#elif defined HAVE_WIN32_THREADS
109#elif defined HAVE_BEOS_THREADS
112 int32 count;
113#else
114 int empty;
115#endif
116};
117
118/*
119 * This module still has some internal static data.
120 * - xmlLibraryLock a global lock
121 * - globalkey used for per-thread data
122 */
123
124#ifdef HAVE_PTHREAD_H
125static pthread_key_t globalkey;
126static pthread_t mainthread;
127static pthread_once_t once_control = PTHREAD_ONCE_INIT;
128static pthread_once_t once_control_init = PTHREAD_ONCE_INIT;
129static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
130#elif defined HAVE_WIN32_THREADS
131#if defined(HAVE_COMPILER_TLS)
132static __declspec(thread) xmlGlobalState tlstate;
133static __declspec(thread) int tlstate_inited = 0;
134#else /* HAVE_COMPILER_TLS */
135static DWORD globalkey = TLS_OUT_OF_INDEXES;
136#endif /* HAVE_COMPILER_TLS */
137static DWORD mainthread;
138static struct {
139 DWORD done;
141} run_once = { 0, 0};
142static volatile LPCRITICAL_SECTION global_init_lock = NULL;
143
144/* endif HAVE_WIN32_THREADS */
145#elif defined HAVE_BEOS_THREADS
146int32 globalkey = 0;
147thread_id mainthread = 0;
148int32 run_once_init = 0;
149static int32 global_init_lock = -1;
150static vint32 global_init_count = 0;
151#endif
152
154
155#ifdef LIBXML_THREAD_ENABLED
156static void xmlOnceInit(void);
157#endif
158
169{
170 xmlMutexPtr tok;
171
172 if ((tok = malloc(sizeof(xmlMutex))) == NULL)
173 return (NULL);
174#ifdef HAVE_PTHREAD_H
175 if (libxml_is_threaded != 0)
176 pthread_mutex_init(&tok->lock, NULL);
177#elif defined HAVE_WIN32_THREADS
179#elif defined HAVE_BEOS_THREADS
180 if ((tok->sem = create_sem(1, "xmlMutex")) < B_OK) {
181 free(tok);
182 return NULL;
183 }
184 tok->tid = -1;
185#endif
186 return (tok);
187}
188
196void
198{
199 if (tok == NULL)
200 return;
201
202#ifdef HAVE_PTHREAD_H
203 if (libxml_is_threaded != 0)
204 pthread_mutex_destroy(&tok->lock);
205#elif defined HAVE_WIN32_THREADS
206 DeleteCriticalSection(&tok->cs);
207#elif defined HAVE_BEOS_THREADS
208 delete_sem(tok->sem);
209#endif
210 free(tok);
211}
212
219void
221{
222 if (tok == NULL)
223 return;
224#ifdef HAVE_PTHREAD_H
225 if (libxml_is_threaded != 0)
226 pthread_mutex_lock(&tok->lock);
227#elif defined HAVE_WIN32_THREADS
228 EnterCriticalSection(&tok->cs);
229#elif defined HAVE_BEOS_THREADS
230 if (acquire_sem(tok->sem) != B_NO_ERROR) {
231#ifdef DEBUG_THREADS
233 "xmlMutexLock():BeOS:Couldn't acquire semaphore\n");
234#endif
235 }
236 tok->tid = find_thread(NULL);
237#endif
238
239}
240
247void
249{
250 if (tok == NULL)
251 return;
252#ifdef HAVE_PTHREAD_H
253 if (libxml_is_threaded != 0)
254 pthread_mutex_unlock(&tok->lock);
255#elif defined HAVE_WIN32_THREADS
256 LeaveCriticalSection(&tok->cs);
257#elif defined HAVE_BEOS_THREADS
258 if (tok->tid == find_thread(NULL)) {
259 tok->tid = -1;
260 release_sem(tok->sem);
261 }
262#endif
263}
264
277{
278 xmlRMutexPtr tok;
279
280 if ((tok = malloc(sizeof(xmlRMutex))) == NULL)
281 return (NULL);
282#ifdef HAVE_PTHREAD_H
283 if (libxml_is_threaded != 0) {
284 pthread_mutex_init(&tok->lock, NULL);
285 tok->held = 0;
286 tok->waiters = 0;
287 pthread_cond_init(&tok->cv, NULL);
288 }
289#elif defined HAVE_WIN32_THREADS
291#elif defined HAVE_BEOS_THREADS
292 if ((tok->lock = xmlNewMutex()) == NULL) {
293 free(tok);
294 return NULL;
295 }
296 tok->count = 0;
297#endif
298 return (tok);
299}
300
308void
310{
311 if (tok == NULL)
312 return;
313#ifdef HAVE_PTHREAD_H
314 if (libxml_is_threaded != 0) {
315 pthread_mutex_destroy(&tok->lock);
316 pthread_cond_destroy(&tok->cv);
317 }
318#elif defined HAVE_WIN32_THREADS
319 DeleteCriticalSection(&tok->cs);
320#elif defined HAVE_BEOS_THREADS
321 xmlFreeMutex(tok->lock);
322#endif
323 free(tok);
324}
325
332void
334{
335 if (tok == NULL)
336 return;
337#ifdef HAVE_PTHREAD_H
338 if (libxml_is_threaded == 0)
339 return;
340
341 pthread_mutex_lock(&tok->lock);
342 if (tok->held) {
343 if (pthread_equal(tok->tid, pthread_self())) {
344 tok->held++;
345 pthread_mutex_unlock(&tok->lock);
346 return;
347 } else {
348 tok->waiters++;
349 while (tok->held)
350 pthread_cond_wait(&tok->cv, &tok->lock);
351 tok->waiters--;
352 }
353 }
354 tok->tid = pthread_self();
355 tok->held = 1;
356 pthread_mutex_unlock(&tok->lock);
357#elif defined HAVE_WIN32_THREADS
358 EnterCriticalSection(&tok->cs);
359#elif defined HAVE_BEOS_THREADS
360 if (tok->lock->tid == find_thread(NULL)) {
361 tok->count++;
362 return;
363 } else {
364 xmlMutexLock(tok->lock);
365 tok->count = 1;
366 }
367#endif
368}
369
376void
378{
379 if (tok == NULL)
380 return;
381#ifdef HAVE_PTHREAD_H
382 if (libxml_is_threaded == 0)
383 return;
384
385 pthread_mutex_lock(&tok->lock);
386 tok->held--;
387 if (tok->held == 0) {
388 if (tok->waiters)
389 pthread_cond_signal(&tok->cv);
390 memset(&tok->tid, 0, sizeof(tok->tid));
391 }
392 pthread_mutex_unlock(&tok->lock);
393#elif defined HAVE_WIN32_THREADS
394 LeaveCriticalSection(&tok->cs);
395#elif defined HAVE_BEOS_THREADS
396 if (tok->lock->tid == find_thread(NULL)) {
397 tok->count--;
398 if (tok->count == 0) {
399 xmlMutexUnlock(tok->lock);
400 }
401 return;
402 }
403#endif
404}
405
412void
414{
415 /* Make sure the global init lock is initialized and then lock it. */
416#ifdef HAVE_PTHREAD_H
417 /* The mutex is statically initialized, so we just lock it. */
418#ifdef XML_PTHREAD_WEAK
419 if (pthread_mutex_lock == NULL)
420 return;
421#endif /* XML_PTHREAD_WEAK */
422 pthread_mutex_lock(&global_init_lock);
423#elif defined HAVE_WIN32_THREADS
425
426 /* Create a new critical section */
427 if (global_init_lock == NULL) {
428 cs = malloc(sizeof(CRITICAL_SECTION));
429 if (cs == NULL) {
431 "xmlGlobalInitMutexLock: out of memory\n");
432 return;
433 }
435
436 /* Swap it into the global_init_lock */
437#ifdef InterlockedCompareExchangePointer
438 InterlockedCompareExchangePointer((void **) &global_init_lock,
439 cs, NULL);
440#else /* Use older void* version */
441 InterlockedCompareExchange((void **) &global_init_lock,
442 (void *) cs, NULL);
443#endif /* InterlockedCompareExchangePointer */
444
445 /* If another thread successfully recorded its critical
446 * section in the global_init_lock then discard the one
447 * allocated by this thread. */
448 if (global_init_lock != cs) {
450 free(cs);
451 }
452 }
453
454 /* Lock the chosen critical section */
455 EnterCriticalSection(global_init_lock);
456#elif defined HAVE_BEOS_THREADS
457 int32 sem;
458
459 /* Allocate a new semaphore */
460 sem = create_sem(1, "xmlGlobalinitMutex");
461
462 while (global_init_lock == -1) {
463 if (atomic_add(&global_init_count, 1) == 0) {
464 global_init_lock = sem;
465 } else {
466 snooze(1);
467 atomic_add(&global_init_count, -1);
468 }
469 }
470
471 /* If another thread successfully recorded its critical
472 * section in the global_init_lock then discard the one
473 * allocated by this thread. */
474 if (global_init_lock != sem)
475 delete_sem(sem);
476
477 /* Acquire the chosen semaphore */
478 if (acquire_sem(global_init_lock) != B_NO_ERROR) {
479#ifdef DEBUG_THREADS
481 "xmlGlobalInitMutexLock():BeOS:Couldn't acquire semaphore\n");
482#endif
483 }
484#endif
485}
486
487void
489{
490#ifdef HAVE_PTHREAD_H
491#ifdef XML_PTHREAD_WEAK
492 if (pthread_mutex_unlock == NULL)
493 return;
494#endif /* XML_PTHREAD_WEAK */
495 pthread_mutex_unlock(&global_init_lock);
496#elif defined HAVE_WIN32_THREADS
497 if (global_init_lock != NULL) {
498 LeaveCriticalSection(global_init_lock);
499 }
500#elif defined HAVE_BEOS_THREADS
501 release_sem(global_init_lock);
502#endif
503}
504
511void
513{
514#ifdef HAVE_PTHREAD_H
515#elif defined HAVE_WIN32_THREADS
516 if (global_init_lock != NULL) {
517 DeleteCriticalSection(global_init_lock);
518 free(global_init_lock);
519 global_init_lock = NULL;
520 }
521#endif
522}
523
524/************************************************************************
525 * *
526 * Per thread global state handling *
527 * *
528 ************************************************************************/
529
530#ifdef LIBXML_THREAD_ENABLED
531#ifdef xmlLastError
532#undef xmlLastError
533#endif
534
542static void
543xmlFreeGlobalState(void *state)
544{
546
547 /* free any memory allocated in the thread's xmlLastError */
548 xmlResetError(&(gs->xmlLastError));
549 free(state);
550}
551
562xmlNewGlobalState(void)
563{
565
566 gs = malloc(sizeof(xmlGlobalState));
567 if (gs == NULL) {
569 "xmlGetGlobalState: out of memory\n");
570 return (NULL);
571 }
572
573 memset(gs, 0, sizeof(xmlGlobalState));
575 return (gs);
576}
577#endif /* LIBXML_THREAD_ENABLED */
578
579#ifdef HAVE_PTHREAD_H
580#elif defined HAVE_WIN32_THREADS
581#if !defined(HAVE_COMPILER_TLS)
582#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
583typedef struct _xmlGlobalStateCleanupHelperParams {
585 void *memory;
586} xmlGlobalStateCleanupHelperParams;
587
588static void XMLCDECL
589xmlGlobalStateCleanupHelper(void *p)
590{
591 xmlGlobalStateCleanupHelperParams *params =
592 (xmlGlobalStateCleanupHelperParams *) p;
594 CloseHandle(params->thread);
595 xmlFreeGlobalState(params->memory);
596 free(params);
597 _endthread();
598}
599#else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */
600
601typedef struct _xmlGlobalStateCleanupHelperParams {
602 void *memory;
603 struct _xmlGlobalStateCleanupHelperParams *prev;
604 struct _xmlGlobalStateCleanupHelperParams *next;
605} xmlGlobalStateCleanupHelperParams;
606
607static xmlGlobalStateCleanupHelperParams *cleanup_helpers_head = NULL;
608static CRITICAL_SECTION cleanup_helpers_cs;
609
610#endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */
611#endif /* HAVE_COMPILER_TLS */
612#endif /* HAVE_WIN32_THREADS */
613
614#if defined HAVE_BEOS_THREADS
615
622void
623xmlGlobalStateCleanup(void *data)
624{
625 void *globalval = tls_get(globalkey);
626
627 if (globalval != NULL)
628 xmlFreeGlobalState(globalval);
629}
630#endif
631
641{
642#ifdef HAVE_PTHREAD_H
643 xmlGlobalState *globalval;
644
645 if (libxml_is_threaded == 0)
646 return (NULL);
647
648 pthread_once(&once_control, xmlOnceInit);
649
650 if ((globalval = (xmlGlobalState *)
651 pthread_getspecific(globalkey)) == NULL) {
652 xmlGlobalState *tsd = xmlNewGlobalState();
653 if (tsd == NULL)
654 return(NULL);
655
656 pthread_setspecific(globalkey, tsd);
657 return (tsd);
658 }
659 return (globalval);
660#elif defined HAVE_WIN32_THREADS
661#if defined(HAVE_COMPILER_TLS)
662 if (!tlstate_inited) {
663 tlstate_inited = 1;
664 xmlInitializeGlobalState(&tlstate);
665 }
666 return &tlstate;
667#else /* HAVE_COMPILER_TLS */
668 xmlGlobalState *globalval;
669 xmlGlobalStateCleanupHelperParams *p;
670
671 xmlOnceInit();
672#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
673 globalval = (xmlGlobalState *) TlsGetValue(globalkey);
674#else
675 p = (xmlGlobalStateCleanupHelperParams *) TlsGetValue(globalkey);
676 globalval = (xmlGlobalState *) (p ? p->memory : NULL);
677#endif
678 if (globalval == NULL) {
679 xmlGlobalState *tsd = xmlNewGlobalState();
680
681 if (tsd == NULL)
682 return(NULL);
683 p = (xmlGlobalStateCleanupHelperParams *)
684 malloc(sizeof(xmlGlobalStateCleanupHelperParams));
685 if (p == NULL) {
687 "xmlGetGlobalState: out of memory\n");
688 xmlFreeGlobalState(tsd);
689 return(NULL);
690 }
691 p->memory = tsd;
692#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
694 GetCurrentProcess(), &p->thread, 0, TRUE,
696 TlsSetValue(globalkey, tsd);
697 _beginthread(xmlGlobalStateCleanupHelper, 0, p);
698#else
699 EnterCriticalSection(&cleanup_helpers_cs);
700 if (cleanup_helpers_head != NULL) {
701 cleanup_helpers_head->prev = p;
702 }
703 p->next = cleanup_helpers_head;
704 p->prev = NULL;
705 cleanup_helpers_head = p;
706 TlsSetValue(globalkey, p);
707 LeaveCriticalSection(&cleanup_helpers_cs);
708#endif
709
710 return (tsd);
711 }
712 return (globalval);
713#endif /* HAVE_COMPILER_TLS */
714#elif defined HAVE_BEOS_THREADS
715 xmlGlobalState *globalval;
716
717 xmlOnceInit();
718
719 if ((globalval = (xmlGlobalState *) tls_get(globalkey)) == NULL) {
720 xmlGlobalState *tsd = xmlNewGlobalState();
721 if (tsd == NULL)
722 return (NULL);
723
724 tls_set(globalkey, tsd);
725 on_exit_thread(xmlGlobalStateCleanup, NULL);
726 return (tsd);
727 }
728 return (globalval);
729#else
730 return (NULL);
731#endif
732}
733
734/************************************************************************
735 * *
736 * Library wide thread interfaces *
737 * *
738 ************************************************************************/
739
749int
751{
752#ifdef HAVE_PTHREAD_H
753 pthread_t id;
754 int ret;
755
756 if (libxml_is_threaded == 0)
757 return (0);
758 id = pthread_self();
759 /* horrible but preserves compat, see warning above */
760 memcpy(&ret, &id, sizeof(ret));
761 return (ret);
762#elif defined HAVE_WIN32_THREADS
763 return GetCurrentThreadId();
764#elif defined HAVE_BEOS_THREADS
765 return find_thread(NULL);
766#else
767 return ((int) 0);
768#endif
769}
770
778int
780{
781#ifdef HAVE_PTHREAD_H
782 if (libxml_is_threaded == -1)
784 if (libxml_is_threaded == 0)
785 return (1);
786 pthread_once(&once_control, xmlOnceInit);
787#elif defined HAVE_WIN32_THREADS
788 xmlOnceInit();
789#elif defined HAVE_BEOS_THREADS
790 xmlOnceInit();
791#endif
792
793#ifdef DEBUG_THREADS
794 xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n");
795#endif
796#ifdef HAVE_PTHREAD_H
797 return (pthread_equal(mainthread,pthread_self()));
798#elif defined HAVE_WIN32_THREADS
799 return (mainthread == GetCurrentThreadId());
800#elif defined HAVE_BEOS_THREADS
801 return (mainthread == find_thread(NULL));
802#else
803 return (1);
804#endif
805}
806
813void
815{
816#ifdef DEBUG_THREADS
817 xmlGenericError(xmlGenericErrorContext, "xmlLockLibrary()\n");
818#endif
820}
821
828void
830{
831#ifdef DEBUG_THREADS
832 xmlGenericError(xmlGenericErrorContext, "xmlUnlockLibrary()\n");
833#endif
835}
836
846void
848{
849#ifdef HAVE_PTHREAD_H
850#ifdef XML_PTHREAD_WEAK
851 if (libxml_is_threaded == -1) {
852 if ((pthread_once != NULL) &&
853 (pthread_getspecific != NULL) &&
854 (pthread_setspecific != NULL) &&
855 (pthread_key_create != NULL) &&
856 (pthread_key_delete != NULL) &&
857 (pthread_mutex_init != NULL) &&
858 (pthread_mutex_destroy != NULL) &&
859 (pthread_mutex_lock != NULL) &&
860 (pthread_mutex_unlock != NULL) &&
861 (pthread_cond_init != NULL) &&
862 (pthread_cond_destroy != NULL) &&
863 (pthread_cond_wait != NULL) &&
864 (pthread_equal != NULL) &&
865 (pthread_self != NULL) &&
866 (pthread_cond_signal != NULL)) {
867 libxml_is_threaded = 1;
868
869/* fprintf(stderr, "Running multithreaded\n"); */
870 } else {
871
872/* fprintf(stderr, "Running without multithread\n"); */
873 libxml_is_threaded = 0;
874 }
875 }
876#endif /* XML_PTHREAD_WEAK */
877#endif
878}
879
899void
901{
902#ifdef DEBUG_THREADS
903 xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n");
904#endif
905#ifdef HAVE_PTHREAD_H
906 if (libxml_is_threaded != 0)
907 pthread_key_delete(globalkey);
908 once_control = once_control_init;
909#elif defined(HAVE_WIN32_THREADS)
910#if !defined(HAVE_COMPILER_TLS)
911 if (globalkey != TLS_OUT_OF_INDEXES) {
912#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
913 xmlGlobalStateCleanupHelperParams *p;
914
915 EnterCriticalSection(&cleanup_helpers_cs);
916 p = cleanup_helpers_head;
917 while (p != NULL) {
918 xmlGlobalStateCleanupHelperParams *temp = p;
919
920 p = p->next;
921 xmlFreeGlobalState(temp->memory);
922 free(temp);
923 }
924 cleanup_helpers_head = 0;
925 LeaveCriticalSection(&cleanup_helpers_cs);
926#endif
927 TlsFree(globalkey);
928 globalkey = TLS_OUT_OF_INDEXES;
929 }
930#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
931 DeleteCriticalSection(&cleanup_helpers_cs);
932#endif
933#endif
934 run_once.done = 0;
935 run_once.control = 0;
936#endif
937}
938
939#ifdef LIBXML_THREAD_ENABLED
940
950static void
951xmlOnceInit(void)
952{
953#ifdef HAVE_PTHREAD_H
954 (void) pthread_key_create(&globalkey, xmlFreeGlobalState);
955 mainthread = pthread_self();
957#elif defined(HAVE_WIN32_THREADS)
958 if (!run_once.done) {
959 if (InterlockedIncrement(&run_once.control) == 1) {
960#if !defined(HAVE_COMPILER_TLS)
961#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
962 InitializeCriticalSection(&cleanup_helpers_cs);
963#endif
964 globalkey = TlsAlloc();
965#endif
966 mainthread = GetCurrentThreadId();
968 run_once.done = 1;
969 } else {
970 /* Another thread is working; give up our slice and
971 * wait until they're done. */
972 while (!run_once.done)
973 Sleep(0);
974 }
975 }
976#elif defined HAVE_BEOS_THREADS
977 if (atomic_add(&run_once_init, 1) == 0) {
978 globalkey = tls_allocate();
979 tls_set(globalkey, NULL);
980 mainthread = find_thread(NULL);
982 } else
983 atomic_add(&run_once_init, -1);
984#endif
985}
986#endif
987
999#ifdef HAVE_PTHREAD_H
1000#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
1001#if defined(LIBXML_STATIC_FOR_DLL)
1002int XMLCALL
1003xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
1005#else
1006/* declare to avoid "no previous prototype for 'DllMain'" warning */
1007/* Note that we do NOT want to include this function declaration in
1008 a public header because it's meant to be called by Windows itself,
1009 not a program that uses this library. This also has to be exported. */
1010
1012DllMain (HINSTANCE hinstDLL,
1013 DWORD fdwReason,
1015
1017DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
1019#endif
1020{
1021 switch (fdwReason) {
1022 case DLL_THREAD_DETACH:
1023 if (globalkey != TLS_OUT_OF_INDEXES) {
1024 xmlGlobalState *globalval = NULL;
1025 xmlGlobalStateCleanupHelperParams *p =
1026 (xmlGlobalStateCleanupHelperParams *)
1027 TlsGetValue(globalkey);
1028 globalval = (xmlGlobalState *) (p ? p->memory : NULL);
1029 if (globalval) {
1030 xmlFreeGlobalState(globalval);
1031 TlsSetValue(globalkey, NULL);
1032 }
1033 if (p) {
1034 EnterCriticalSection(&cleanup_helpers_cs);
1035 if (p == cleanup_helpers_head)
1036 cleanup_helpers_head = p->next;
1037 else
1038 p->prev->next = p->next;
1039 if (p->next != NULL)
1040 p->next->prev = p->prev;
1041 LeaveCriticalSection(&cleanup_helpers_cs);
1042 free(p);
1043 }
1044 }
1045 break;
1046 }
1047 return TRUE;
1048}
1049#endif
static int state
Definition: maze.c:121
#define InterlockedIncrement
Definition: armddk.h:53
static void atomic_add(int volatile i, atomic_t volatile *v)
Definition: atomic.h:43
static HANDLE thread
Definition: service.c:33
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:739
#define DLL_THREAD_DETACH
Definition: compat.h:133
#define GetCurrentProcess()
Definition: compat.h:759
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
LPVOID WINAPI TlsGetValue(IN DWORD Index)
Definition: thread.c:1240
DWORD WINAPI TlsAlloc(VOID)
Definition: thread.c:1100
BOOL WINAPI TlsSetValue(IN DWORD Index, IN LPVOID Value)
Definition: thread.c:1276
BOOL WINAPI TlsFree(IN DWORD Index)
Definition: thread.c:1166
long int32
Definition: platform.h:12
#define INFINITE
Definition: serial.h:102
#define XMLCALL
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
__declspec(noinline)
Definition: floatconv.c:47
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum const GLfloat * params
Definition: glext.h:5645
GLfloat GLfloat p
Definition: glext.h:8902
GLuint id
Definition: glext.h:5910
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
#define cs
Definition: i386-dis.c:442
#define gs
Definition: i386-dis.c:445
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define InterlockedCompareExchange
Definition: interlocked.h:104
BOOL WINAPI DllMain(IN HINSTANCE hinstDLL, IN DWORD dwReason, IN LPVOID lpvReserved)
Definition: kbsdll.c:95
PETHREAD find_thread(_In_ UINT_PTR Pid, _In_ UINT_PTR Tid)
Definition: utils.c:41
static IN DWORD IN LPVOID lpvReserved
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static char memory[1024 *256]
Definition: process.c:116
static HANDLE sem
Definition: sync.c:674
static TfClientId tid
static DWORD thread_id
Definition: protocol.c:159
long LONG
Definition: pedump.c:60
static unsigned __int64 next
Definition: rand_nt.c:6
static calc_node_t temp
Definition: rpn_ieee.c:38
_CRTIMP uintptr_t __cdecl _beginthread(_In_ void(__cdecl *_StartAddress)(void *), _In_ unsigned _StackSize, _In_opt_ void *_ArgList)
_CRTIMP void __cdecl _endthread(void)
Definition: thread.c:95
XMLPUBFUN void XMLCALL xmlInitializeGlobalState(xmlGlobalStatePtr gs)
Definition: globals.c:454
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:353
XMLPUBVAR xmlGenericErrorFunc xmlGenericError
Definition: globals.h:337
int __xmlInitializeDict(void)
Definition: dict.c:173
#define memset(x, y, z)
Definition: compat.h:39
int empty
Definition: threads.c:93
int empty
Definition: threads.c:114
Definition: dialog.c:52
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
rwlock_t lock
Definition: tcpcore.h:0
void __xmlGlobalInitMutexDestroy(void)
Definition: threads.c:512
xmlMutexPtr xmlNewMutex(void)
Definition: threads.c:168
void xmlLockLibrary(void)
Definition: threads.c:814
int xmlGetThreadId(void)
Definition: threads.c:750
xmlRMutexPtr xmlNewRMutex(void)
Definition: threads.c:276
void xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
Definition: threads.c:309
void xmlInitThreads(void)
Definition: threads.c:847
void xmlUnlockLibrary(void)
Definition: threads.c:829
void __xmlGlobalInitMutexLock(void)
Definition: threads.c:413
void xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
Definition: threads.c:377
int xmlIsMainThread(void)
Definition: threads.c:779
void xmlMutexLock(xmlMutexPtr tok)
Definition: threads.c:220
void xmlMutexUnlock(xmlMutexPtr tok)
Definition: threads.c:248
static xmlRMutexPtr xmlLibraryLock
Definition: threads.c:153
void xmlRMutexLock(xmlRMutexPtr tok)
Definition: threads.c:333
void xmlFreeMutex(xmlMutexPtr tok)
Definition: threads.c:197
void xmlCleanupThreads(void)
Definition: threads.c:900
xmlGlobalStatePtr xmlGetGlobalState(void)
Definition: threads.c:640
void __xmlGlobalInitMutexUnlock(void)
Definition: threads.c:488
int ret
HANDLE WINAPI GetCurrentThread(void)
Definition: proc.c:1148
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define TLS_OUT_OF_INDEXES
Definition: winbase.h:575
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define WINAPI
Definition: msvc.h:6
#define DUPLICATE_SAME_ACCESS
XMLPUBFUN void XMLCALL xmlResetError(xmlErrorPtr err)
#define XMLPUBFUN
Definition: xmlexports.h:61
#define XMLCDECL
Definition: xmlexports.h:52