ReactOS  0.4.14-dev-52-g6116262
threads.c
Go to the documentation of this file.
1 
10 #define IN_LIBXML
11 #include "libxml.h"
12 
13 #include <string.h>
14 
15 #include <libxml/threads.h>
16 #include <libxml/globals.h>
17 
18 #ifdef HAVE_SYS_TYPES_H
19 #include <sys/types.h>
20 #endif
21 #ifdef HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24 #ifdef HAVE_STDLIB_H
25 #include <stdlib.h>
26 #endif
27 #ifdef HAVE_PTHREAD_H
28 #include <pthread.h>
29 #elif defined HAVE_WIN32_THREADS
30 //#define WIN32_LEAN_AND_MEAN
31 //#include <windows.h>
32 #ifndef HAVE_COMPILER_TLS
33 #include <process.h>
34 #endif
35 #endif
36 
37 #ifdef HAVE_BEOS_THREADS
38 #include <OS.h>
39 #include <TLS.h>
40 #endif
41 
42 #if defined(SOLARIS)
43 #include <note.h>
44 #endif
45 
46 /* #define DEBUG_THREADS */
47 
48 #ifdef HAVE_PTHREAD_H
49 
50 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 303) && \
51  defined(__GLIBC__) && defined(__linux__)
52 
53 static int libxml_is_threaded = -1;
54 
55 #define XML_PTHREAD_WEAK
56 
57 #pragma weak pthread_once
58 #pragma weak pthread_getspecific
59 #pragma weak pthread_setspecific
60 #pragma weak pthread_key_create
61 #pragma weak pthread_key_delete
62 #pragma weak pthread_mutex_init
63 #pragma weak pthread_mutex_destroy
64 #pragma weak pthread_mutex_lock
65 #pragma weak pthread_mutex_unlock
66 #pragma weak pthread_cond_init
67 #pragma weak pthread_cond_destroy
68 #pragma weak pthread_cond_wait
69 #pragma weak pthread_equal
70 #pragma weak pthread_self
71 #pragma weak pthread_key_create
72 #pragma weak pthread_key_delete
73 #pragma weak pthread_cond_signal
74 
75 #else /* __GNUC__, __GLIBC__, __linux__ */
76 
77 static int libxml_is_threaded = 1;
78 
79 #endif /* __GNUC__, __GLIBC__, __linux__ */
80 
81 #endif /* HAVE_PTHREAD_H */
82 
83 /*
84  * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree
85  * to avoid some crazyness since xmlMalloc/xmlFree may actually
86  * be hosted on allocated blocks needing them for the allocation ...
87  */
88 
89 /*
90  * xmlMutex are a simple mutual exception locks
91  */
92 struct _xmlMutex {
93 #ifdef HAVE_PTHREAD_H
94  pthread_mutex_t lock;
95 #elif defined HAVE_WIN32_THREADS
96  HANDLE mutex;
97 #elif defined HAVE_BEOS_THREADS
98  sem_id sem;
99  thread_id tid;
100 #else
101  int empty;
102 #endif
103 };
104 
105 /*
106  * xmlRMutex are reentrant mutual exception locks
107  */
108 struct _xmlRMutex {
109 #ifdef HAVE_PTHREAD_H
110  pthread_mutex_t lock;
111  unsigned int held;
112  unsigned int waiters;
113  pthread_t tid;
114  pthread_cond_t cv;
115 #elif defined HAVE_WIN32_THREADS
117  unsigned int count;
118 #elif defined HAVE_BEOS_THREADS
120  thread_id tid;
121  int32 count;
122 #else
123  int empty;
124 #endif
125 };
126 
127 /*
128  * This module still has some internal static data.
129  * - xmlLibraryLock a global lock
130  * - globalkey used for per-thread data
131  */
132 
133 #ifdef HAVE_PTHREAD_H
134 static pthread_key_t globalkey;
135 static pthread_t mainthread;
136 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
137 static pthread_once_t once_control_init = PTHREAD_ONCE_INIT;
138 static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
139 #elif defined HAVE_WIN32_THREADS
140 #if defined(HAVE_COMPILER_TLS)
141 static __declspec(thread) xmlGlobalState tlstate;
142 static __declspec(thread) int tlstate_inited = 0;
143 #else /* HAVE_COMPILER_TLS */
144 static DWORD globalkey = TLS_OUT_OF_INDEXES;
145 #endif /* HAVE_COMPILER_TLS */
146 static DWORD mainthread;
147 static struct {
148  DWORD done;
149  LONG control;
150 } run_once = { 0, 0};
151 static volatile LPCRITICAL_SECTION global_init_lock = NULL;
152 
153 /* endif HAVE_WIN32_THREADS */
154 #elif defined HAVE_BEOS_THREADS
155 int32 globalkey = 0;
156 thread_id mainthread = 0;
157 int32 run_once_init = 0;
158 static int32 global_init_lock = -1;
159 static vint32 global_init_count = 0;
160 #endif
161 
163 
164 #ifdef LIBXML_THREAD_ENABLED
165 static void xmlOnceInit(void);
166 #endif
167 
178 {
179  xmlMutexPtr tok;
180 
181  if ((tok = malloc(sizeof(xmlMutex))) == NULL)
182  return (NULL);
183 #ifdef HAVE_PTHREAD_H
184  if (libxml_is_threaded != 0)
185  pthread_mutex_init(&tok->lock, NULL);
186 #elif defined HAVE_WIN32_THREADS
187  tok->mutex = CreateMutex(NULL, FALSE, NULL);
188 #elif defined HAVE_BEOS_THREADS
189  if ((tok->sem = create_sem(1, "xmlMutex")) < B_OK) {
190  free(tok);
191  return NULL;
192  }
193  tok->tid = -1;
194 #endif
195  return (tok);
196 }
197 
205 void
207 {
208  if (tok == NULL)
209  return;
210 
211 #ifdef HAVE_PTHREAD_H
212  if (libxml_is_threaded != 0)
213  pthread_mutex_destroy(&tok->lock);
214 #elif defined HAVE_WIN32_THREADS
215  CloseHandle(tok->mutex);
216 #elif defined HAVE_BEOS_THREADS
217  delete_sem(tok->sem);
218 #endif
219  free(tok);
220 }
221 
228 void
230 {
231  if (tok == NULL)
232  return;
233 #ifdef HAVE_PTHREAD_H
234  if (libxml_is_threaded != 0)
235  pthread_mutex_lock(&tok->lock);
236 #elif defined HAVE_WIN32_THREADS
237  WaitForSingleObject(tok->mutex, INFINITE);
238 #elif defined HAVE_BEOS_THREADS
239  if (acquire_sem(tok->sem) != B_NO_ERROR) {
240 #ifdef DEBUG_THREADS
242  "xmlMutexLock():BeOS:Couldn't aquire semaphore\n");
243 #endif
244  }
245  tok->tid = find_thread(NULL);
246 #endif
247 
248 }
249 
256 void
258 {
259  if (tok == NULL)
260  return;
261 #ifdef HAVE_PTHREAD_H
262  if (libxml_is_threaded != 0)
263  pthread_mutex_unlock(&tok->lock);
264 #elif defined HAVE_WIN32_THREADS
265  ReleaseMutex(tok->mutex);
266 #elif defined HAVE_BEOS_THREADS
267  if (tok->tid == find_thread(NULL)) {
268  tok->tid = -1;
269  release_sem(tok->sem);
270  }
271 #endif
272 }
273 
286 {
287  xmlRMutexPtr tok;
288 
289  if ((tok = malloc(sizeof(xmlRMutex))) == NULL)
290  return (NULL);
291 #ifdef HAVE_PTHREAD_H
292  if (libxml_is_threaded != 0) {
293  pthread_mutex_init(&tok->lock, NULL);
294  tok->held = 0;
295  tok->waiters = 0;
296  pthread_cond_init(&tok->cv, NULL);
297  }
298 #elif defined HAVE_WIN32_THREADS
299  InitializeCriticalSection(&tok->cs);
300  tok->count = 0;
301 #elif defined HAVE_BEOS_THREADS
302  if ((tok->lock = xmlNewMutex()) == NULL) {
303  free(tok);
304  return NULL;
305  }
306  tok->count = 0;
307 #endif
308  return (tok);
309 }
310 
318 void
320 {
321  if (tok == NULL)
322  return;
323 #ifdef HAVE_PTHREAD_H
324  if (libxml_is_threaded != 0) {
325  pthread_mutex_destroy(&tok->lock);
326  pthread_cond_destroy(&tok->cv);
327  }
328 #elif defined HAVE_WIN32_THREADS
329  DeleteCriticalSection(&tok->cs);
330 #elif defined HAVE_BEOS_THREADS
331  xmlFreeMutex(tok->lock);
332 #endif
333  free(tok);
334 }
335 
342 void
344 {
345  if (tok == NULL)
346  return;
347 #ifdef HAVE_PTHREAD_H
348  if (libxml_is_threaded == 0)
349  return;
350 
351  pthread_mutex_lock(&tok->lock);
352  if (tok->held) {
353  if (pthread_equal(tok->tid, pthread_self())) {
354  tok->held++;
355  pthread_mutex_unlock(&tok->lock);
356  return;
357  } else {
358  tok->waiters++;
359  while (tok->held)
360  pthread_cond_wait(&tok->cv, &tok->lock);
361  tok->waiters--;
362  }
363  }
364  tok->tid = pthread_self();
365  tok->held = 1;
366  pthread_mutex_unlock(&tok->lock);
367 #elif defined HAVE_WIN32_THREADS
368  EnterCriticalSection(&tok->cs);
369  tok->count++;
370 #elif defined HAVE_BEOS_THREADS
371  if (tok->lock->tid == find_thread(NULL)) {
372  tok->count++;
373  return;
374  } else {
375  xmlMutexLock(tok->lock);
376  tok->count = 1;
377  }
378 #endif
379 }
380 
387 void
389 {
390  if (tok == NULL)
391  return;
392 #ifdef HAVE_PTHREAD_H
393  if (libxml_is_threaded == 0)
394  return;
395 
396  pthread_mutex_lock(&tok->lock);
397  tok->held--;
398  if (tok->held == 0) {
399  if (tok->waiters)
400  pthread_cond_signal(&tok->cv);
401  memset(&tok->tid, 0, sizeof(tok->tid));
402  }
403  pthread_mutex_unlock(&tok->lock);
404 #elif defined HAVE_WIN32_THREADS
405  if (tok->count > 0) {
406  tok->count--;
407  LeaveCriticalSection(&tok->cs);
408  }
409 #elif defined HAVE_BEOS_THREADS
410  if (tok->lock->tid == find_thread(NULL)) {
411  tok->count--;
412  if (tok->count == 0) {
413  xmlMutexUnlock(tok->lock);
414  }
415  return;
416  }
417 #endif
418 }
419 
426 void
428 {
429  /* Make sure the global init lock is initialized and then lock it. */
430 #ifdef HAVE_PTHREAD_H
431  /* The mutex is statically initialized, so we just lock it. */
432 #ifdef XML_PTHREAD_WEAK
433  if (pthread_mutex_lock == NULL)
434  return;
435 #endif /* XML_PTHREAD_WEAK */
436  pthread_mutex_lock(&global_init_lock);
437 #elif defined HAVE_WIN32_THREADS
439 
440  /* Create a new critical section */
441  if (global_init_lock == NULL) {
442  cs = malloc(sizeof(CRITICAL_SECTION));
443  if (cs == NULL) {
445  "xmlGlobalInitMutexLock: out of memory\n");
446  return;
447  }
449 
450  /* Swap it into the global_init_lock */
451 #ifdef InterlockedCompareExchangePointer
452  InterlockedCompareExchangePointer((void **) &global_init_lock,
453  cs, NULL);
454 #else /* Use older void* version */
455  InterlockedCompareExchange((void **) &global_init_lock,
456  (void *) cs, NULL);
457 #endif /* InterlockedCompareExchangePointer */
458 
459  /* If another thread successfully recorded its critical
460  * section in the global_init_lock then discard the one
461  * allocated by this thread. */
462  if (global_init_lock != cs) {
464  free(cs);
465  }
466  }
467 
468  /* Lock the chosen critical section */
469  EnterCriticalSection(global_init_lock);
470 #elif defined HAVE_BEOS_THREADS
471  int32 sem;
472 
473  /* Allocate a new semaphore */
474  sem = create_sem(1, "xmlGlobalinitMutex");
475 
476  while (global_init_lock == -1) {
477  if (atomic_add(&global_init_count, 1) == 0) {
478  global_init_lock = sem;
479  } else {
480  snooze(1);
481  atomic_add(&global_init_count, -1);
482  }
483  }
484 
485  /* If another thread successfully recorded its critical
486  * section in the global_init_lock then discard the one
487  * allocated by this thread. */
488  if (global_init_lock != sem)
489  delete_sem(sem);
490 
491  /* Acquire the chosen semaphore */
492  if (acquire_sem(global_init_lock) != B_NO_ERROR) {
493 #ifdef DEBUG_THREADS
495  "xmlGlobalInitMutexLock():BeOS:Couldn't acquire semaphore\n");
496 #endif
497  }
498 #endif
499 }
500 
501 void
503 {
504 #ifdef HAVE_PTHREAD_H
505 #ifdef XML_PTHREAD_WEAK
506  if (pthread_mutex_unlock == NULL)
507  return;
508 #endif /* XML_PTHREAD_WEAK */
509  pthread_mutex_unlock(&global_init_lock);
510 #elif defined HAVE_WIN32_THREADS
511  if (global_init_lock != NULL) {
512  LeaveCriticalSection(global_init_lock);
513  }
514 #elif defined HAVE_BEOS_THREADS
515  release_sem(global_init_lock);
516 #endif
517 }
518 
525 void
527 {
528 #ifdef HAVE_PTHREAD_H
529 #elif defined HAVE_WIN32_THREADS
530  if (global_init_lock != NULL) {
531  DeleteCriticalSection(global_init_lock);
532  free(global_init_lock);
533  global_init_lock = NULL;
534  }
535 #endif
536 }
537 
538 /************************************************************************
539  * *
540  * Per thread global state handling *
541  * *
542  ************************************************************************/
543 
544 #ifdef LIBXML_THREAD_ENABLED
545 #ifdef xmlLastError
546 #undef xmlLastError
547 #endif
548 
556 static void
557 xmlFreeGlobalState(void *state)
558 {
560 
561  /* free any memory allocated in the thread's xmlLastError */
562  xmlResetError(&(gs->xmlLastError));
563  free(state);
564 }
565 
575 static xmlGlobalStatePtr
576 xmlNewGlobalState(void)
577 {
579 
580  gs = malloc(sizeof(xmlGlobalState));
581  if (gs == NULL) {
583  "xmlGetGlobalState: out of memory\n");
584  return (NULL);
585  }
586 
587  memset(gs, 0, sizeof(xmlGlobalState));
589  return (gs);
590 }
591 #endif /* LIBXML_THREAD_ENABLED */
592 
593 #ifdef HAVE_PTHREAD_H
594 #elif defined HAVE_WIN32_THREADS
595 #if !defined(HAVE_COMPILER_TLS)
596 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
597 typedef struct _xmlGlobalStateCleanupHelperParams {
598  HANDLE thread;
599  void *memory;
600 } xmlGlobalStateCleanupHelperParams;
601 
602 static void XMLCDECL
603 xmlGlobalStateCleanupHelper(void *p)
604 {
605  xmlGlobalStateCleanupHelperParams *params =
606  (xmlGlobalStateCleanupHelperParams *) p;
608  CloseHandle(params->thread);
609  xmlFreeGlobalState(params->memory);
610  free(params);
611  _endthread();
612 }
613 #else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */
614 
615 typedef struct _xmlGlobalStateCleanupHelperParams {
616  void *memory;
617  struct _xmlGlobalStateCleanupHelperParams *prev;
618  struct _xmlGlobalStateCleanupHelperParams *next;
619 } xmlGlobalStateCleanupHelperParams;
620 
621 static xmlGlobalStateCleanupHelperParams *cleanup_helpers_head = NULL;
622 static CRITICAL_SECTION cleanup_helpers_cs;
623 
624 #endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */
625 #endif /* HAVE_COMPILER_TLS */
626 #endif /* HAVE_WIN32_THREADS */
627 
628 #if defined HAVE_BEOS_THREADS
629 
636 void
637 xmlGlobalStateCleanup(void *data)
638 {
639  void *globalval = tls_get(globalkey);
640 
641  if (globalval != NULL)
642  xmlFreeGlobalState(globalval);
643 }
644 #endif
645 
655 {
656 #ifdef HAVE_PTHREAD_H
657  xmlGlobalState *globalval;
658 
659  if (libxml_is_threaded == 0)
660  return (NULL);
661 
662  pthread_once(&once_control, xmlOnceInit);
663 
664  if ((globalval = (xmlGlobalState *)
665  pthread_getspecific(globalkey)) == NULL) {
666  xmlGlobalState *tsd = xmlNewGlobalState();
667  if (tsd == NULL)
668  return(NULL);
669 
670  pthread_setspecific(globalkey, tsd);
671  return (tsd);
672  }
673  return (globalval);
674 #elif defined HAVE_WIN32_THREADS
675 #if defined(HAVE_COMPILER_TLS)
676  if (!tlstate_inited) {
677  tlstate_inited = 1;
678  xmlInitializeGlobalState(&tlstate);
679  }
680  return &tlstate;
681 #else /* HAVE_COMPILER_TLS */
682  xmlGlobalState *globalval;
683  xmlGlobalStateCleanupHelperParams *p;
684 
685  xmlOnceInit();
686 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
687  globalval = (xmlGlobalState *) TlsGetValue(globalkey);
688 #else
689  p = (xmlGlobalStateCleanupHelperParams *) TlsGetValue(globalkey);
690  globalval = (xmlGlobalState *) (p ? p->memory : NULL);
691 #endif
692  if (globalval == NULL) {
693  xmlGlobalState *tsd = xmlNewGlobalState();
694 
695  if (tsd == NULL)
696  return(NULL);
697  p = (xmlGlobalStateCleanupHelperParams *)
698  malloc(sizeof(xmlGlobalStateCleanupHelperParams));
699  if (p == NULL) {
701  "xmlGetGlobalState: out of memory\n");
702  xmlFreeGlobalState(tsd);
703  return(NULL);
704  }
705  p->memory = tsd;
706 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
708  GetCurrentProcess(), &p->thread, 0, TRUE,
710  TlsSetValue(globalkey, tsd);
711  _beginthread(xmlGlobalStateCleanupHelper, 0, p);
712 #else
713  EnterCriticalSection(&cleanup_helpers_cs);
714  if (cleanup_helpers_head != NULL) {
715  cleanup_helpers_head->prev = p;
716  }
717  p->next = cleanup_helpers_head;
718  p->prev = NULL;
719  cleanup_helpers_head = p;
720  TlsSetValue(globalkey, p);
721  LeaveCriticalSection(&cleanup_helpers_cs);
722 #endif
723 
724  return (tsd);
725  }
726  return (globalval);
727 #endif /* HAVE_COMPILER_TLS */
728 #elif defined HAVE_BEOS_THREADS
729  xmlGlobalState *globalval;
730 
731  xmlOnceInit();
732 
733  if ((globalval = (xmlGlobalState *) tls_get(globalkey)) == NULL) {
734  xmlGlobalState *tsd = xmlNewGlobalState();
735  if (tsd == NULL)
736  return (NULL);
737 
738  tls_set(globalkey, tsd);
739  on_exit_thread(xmlGlobalStateCleanup, NULL);
740  return (tsd);
741  }
742  return (globalval);
743 #else
744  return (NULL);
745 #endif
746 }
747 
748 /************************************************************************
749  * *
750  * Library wide thread interfaces *
751  * *
752  ************************************************************************/
753 
763 int
765 {
766 #ifdef HAVE_PTHREAD_H
767  pthread_t id;
768  int ret;
769 
770  if (libxml_is_threaded == 0)
771  return (0);
772  id = pthread_self();
773  /* horrible but preserves compat, see warning above */
774  memcpy(&ret, &id, sizeof(ret));
775  return (ret);
776 #elif defined HAVE_WIN32_THREADS
777  return GetCurrentThreadId();
778 #elif defined HAVE_BEOS_THREADS
779  return find_thread(NULL);
780 #else
781  return ((int) 0);
782 #endif
783 }
784 
792 int
794 {
795 #ifdef HAVE_PTHREAD_H
796  if (libxml_is_threaded == -1)
797  xmlInitThreads();
798  if (libxml_is_threaded == 0)
799  return (1);
800  pthread_once(&once_control, xmlOnceInit);
801 #elif defined HAVE_WIN32_THREADS
802  xmlOnceInit();
803 #elif defined HAVE_BEOS_THREADS
804  xmlOnceInit();
805 #endif
806 
807 #ifdef DEBUG_THREADS
808  xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n");
809 #endif
810 #ifdef HAVE_PTHREAD_H
811  return (pthread_equal(mainthread,pthread_self()));
812 #elif defined HAVE_WIN32_THREADS
813  return (mainthread == GetCurrentThreadId());
814 #elif defined HAVE_BEOS_THREADS
815  return (mainthread == find_thread(NULL));
816 #else
817  return (1);
818 #endif
819 }
820 
827 void
829 {
830 #ifdef DEBUG_THREADS
831  xmlGenericError(xmlGenericErrorContext, "xmlLockLibrary()\n");
832 #endif
834 }
835 
842 void
844 {
845 #ifdef DEBUG_THREADS
846  xmlGenericError(xmlGenericErrorContext, "xmlUnlockLibrary()\n");
847 #endif
849 }
850 
857 void
859 {
860 #ifdef HAVE_PTHREAD_H
861 #ifdef XML_PTHREAD_WEAK
862  if (libxml_is_threaded == -1) {
863  if ((pthread_once != NULL) &&
864  (pthread_getspecific != NULL) &&
865  (pthread_setspecific != NULL) &&
866  (pthread_key_create != NULL) &&
867  (pthread_key_delete != NULL) &&
868  (pthread_mutex_init != NULL) &&
869  (pthread_mutex_destroy != NULL) &&
870  (pthread_mutex_lock != NULL) &&
871  (pthread_mutex_unlock != NULL) &&
872  (pthread_cond_init != NULL) &&
873  (pthread_cond_destroy != NULL) &&
874  (pthread_cond_wait != NULL) &&
875  (pthread_equal != NULL) &&
876  (pthread_self != NULL) &&
877  (pthread_cond_signal != NULL)) {
878  libxml_is_threaded = 1;
879 
880 /* fprintf(stderr, "Running multithreaded\n"); */
881  } else {
882 
883 /* fprintf(stderr, "Running without multithread\n"); */
884  libxml_is_threaded = 0;
885  }
886  }
887 #endif /* XML_PTHREAD_WEAK */
888 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
889  InitializeCriticalSection(&cleanup_helpers_cs);
890 #endif
891 }
892 
907 void
909 {
910 #ifdef DEBUG_THREADS
911  xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n");
912 #endif
913 #ifdef HAVE_PTHREAD_H
914  if (libxml_is_threaded != 0)
915  pthread_key_delete(globalkey);
916  once_control = once_control_init;
917 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
918  if (globalkey != TLS_OUT_OF_INDEXES) {
919  xmlGlobalStateCleanupHelperParams *p;
920 
921  EnterCriticalSection(&cleanup_helpers_cs);
922  p = cleanup_helpers_head;
923  while (p != NULL) {
924  xmlGlobalStateCleanupHelperParams *temp = p;
925 
926  p = p->next;
927  xmlFreeGlobalState(temp->memory);
928  free(temp);
929  }
930  cleanup_helpers_head = 0;
931  LeaveCriticalSection(&cleanup_helpers_cs);
932  TlsFree(globalkey);
933  globalkey = TLS_OUT_OF_INDEXES;
934  }
935  DeleteCriticalSection(&cleanup_helpers_cs);
936 #endif
937 }
938 
939 #ifdef LIBXML_THREAD_ENABLED
940 
950 static void
951 xmlOnceInit(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  globalkey = TlsAlloc();
962 #endif
963  mainthread = GetCurrentThreadId();
965  run_once.done = 1;
966  } else {
967  /* Another thread is working; give up our slice and
968  * wait until they're done. */
969  while (!run_once.done)
970  Sleep(0);
971  }
972  }
973 #elif defined HAVE_BEOS_THREADS
974  if (atomic_add(&run_once_init, 1) == 0) {
975  globalkey = tls_allocate();
976  tls_set(globalkey, NULL);
977  mainthread = find_thread(NULL);
979  } else
980  atomic_add(&run_once_init, -1);
981 #endif
982 }
983 #endif
984 
996 #ifdef HAVE_PTHREAD_H
997 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
998 #if defined(LIBXML_STATIC_FOR_DLL)
999 int XMLCALL
1000 xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
1002 #else
1003 /* declare to avoid "no previous prototype for 'DllMain'" warning */
1004 /* Note that we do NOT want to include this function declaration in
1005  a public header because it's meant to be called by Windows itself,
1006  not a program that uses this library. This also has to be exported. */
1007 
1009 DllMain (HINSTANCE hinstDLL,
1010  DWORD fdwReason,
1012 
1013 BOOL WINAPI
1014 DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
1016 #endif
1017 {
1018  switch (fdwReason) {
1019  case DLL_THREAD_DETACH:
1020  if (globalkey != TLS_OUT_OF_INDEXES) {
1021  xmlGlobalState *globalval = NULL;
1022  xmlGlobalStateCleanupHelperParams *p =
1023  (xmlGlobalStateCleanupHelperParams *)
1024  TlsGetValue(globalkey);
1025  globalval = (xmlGlobalState *) (p ? p->memory : NULL);
1026  if (globalval) {
1027  xmlFreeGlobalState(globalval);
1028  TlsSetValue(globalkey, NULL);
1029  }
1030  if (p) {
1031  EnterCriticalSection(&cleanup_helpers_cs);
1032  if (p == cleanup_helpers_head)
1033  cleanup_helpers_head = p->next;
1034  else
1035  p->prev->next = p->next;
1036  if (p->next != NULL)
1037  p->next->prev = p->prev;
1038  LeaveCriticalSection(&cleanup_helpers_cs);
1039  free(p);
1040  }
1041  }
1042  break;
1043  }
1044  return TRUE;
1045 }
1046 #endif
1047 #define bottom_threads
1048 #include "elfgcchack.h"
void xmlRMutexLock(xmlRMutexPtr tok)
Definition: threads.c:343
int xmlIsMainThread(void)
Definition: threads.c:793
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
_CRTIMP void __cdecl _endthread(void)
Definition: thread.c:95
rwlock_t lock
Definition: tcpcore.h:1163
xmlRMutexPtr xmlNewRMutex(void)
Definition: threads.c:285
BOOL WINAPI TlsSetValue(IN DWORD Index, IN LPVOID Value)
Definition: thread.c:1264
int empty
Definition: threads.c:123
void xmlLockLibrary(void)
Definition: threads.c:828
GLuint GLuint GLsizei count
Definition: gl.h:1545
xmlGlobalStatePtr xmlGetGlobalState(void)
Definition: threads.c:654
#define free
Definition: debug_ros.c:5
void xmlMutexLock(xmlMutexPtr tok)
Definition: threads.c:229
#define InterlockedCompareExchange
Definition: interlocked.h:104
int empty
Definition: threads.c:101
struct _EXCEPTION_POINTERS *_CRTIMP __declspec(noreturn) void __cdecl terminate(void)
Definition: eh.h:27
#define XMLPUBFUN
Definition: xmlexports.h:30
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
static char memory[1024 *256]
Definition: process.c:116
#define DLL_THREAD_DETACH
Definition: compat.h:122
xmlMutexPtr xmlNewMutex(void)
Definition: threads.c:177
static IN DWORD IN LPVOID lpvReserved
HANDLE mutex
Definition: loader.c:2140
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
uint32_t cs
Definition: isohybrid.c:75
static xmlRMutexPtr xmlLibraryLock
Definition: threads.c:162
#define DUPLICATE_SAME_ACCESS
GLenum const GLfloat * params
Definition: glext.h:5645
HANDLE WINAPI GetCurrentThread(VOID)
Definition: proc.c:1148
unsigned int BOOL
Definition: ntddk_ex.h:94
void xmlInitThreads(void)
Definition: threads.c:858
long LONG
Definition: pedump.c:60
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
XMLPUBVAR xmlGenericErrorFunc xmlGenericError
Definition: globals.h:346
void xmlUnlockLibrary(void)
Definition: threads.c:843
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
BOOL WINAPI DllMain(IN HINSTANCE hinstDLL, IN DWORD dwReason, IN LPVOID lpvReserved)
Definition: kbsdll.c:83
#define gs
Definition: i386-dis.c:436
PETHREAD find_thread(_In_ UINT_PTR Pid, _In_ UINT_PTR Tid)
Definition: utils.c:41
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:458
void xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
Definition: threads.c:319
void xmlMutexUnlock(xmlMutexPtr tok)
Definition: threads.c:257
#define CreateMutex
Definition: winbase.h:3573
BOOL WINAPI TlsFree(IN DWORD Index)
Definition: thread.c:1154
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
void xmlFreeMutex(xmlMutexPtr tok)
Definition: threads.c:206
int xmlGetThreadId(void)
Definition: threads.c:764
HANDLE WINAPI GetCurrentProcess(VOID)
Definition: proc.c:1138
#define WINAPI
Definition: msvc.h:8
int __xmlInitializeDict(void)
Definition: dict.c:175
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
BOOL WINAPI DECLSPEC_HOTPATCH ReleaseMutex(IN HANDLE hMutex)
Definition: synch.c:618
static HANDLE thread
Definition: service.c:33
int ret
#define ATTRIBUTE_UNUSED
Definition: win32config.h:132
static int state
Definition: maze.c:121
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
DWORD WINAPI TlsAlloc(VOID)
Definition: thread.c:1088
#define TLS_OUT_OF_INDEXES
Definition: winbase.h:530
XMLPUBFUN void XMLCALL xmlResetError(xmlErrorPtr err)
static void atomic_add(int volatile i, atomic_t volatile *v)
Definition: atomic.h:43
static unsigned __int64 next
Definition: rand_nt.c:6
#define InterlockedIncrement
Definition: armddk.h:53
void xmlCleanupThreads(void)
Definition: threads.c:908
void __xmlGlobalInitMutexDestroy(void)
Definition: threads.c:526
void __xmlGlobalInitMutexUnlock(void)
Definition: threads.c:502
static HANDLE sem
Definition: sync.c:677
static calc_node_t temp
Definition: rpn_ieee.c:38
static DWORD thread_id
Definition: protocol.c:158
#define XMLCDECL
Definition: xmlexports.h:49
LPVOID WINAPI TlsGetValue(IN DWORD Index)
Definition: thread.c:1228
_CRTIMP uintptr_t __cdecl _beginthread(_In_ void(__cdecl *_StartAddress)(void *), _In_ unsigned _StackSize, _In_opt_ void *_ArgList)
#define XMLCALL
long int32
Definition: platform.h:12
GLenum GLuint id
Definition: glext.h:5579
XMLPUBFUN void XMLCALL xmlInitializeGlobalState(xmlGlobalStatePtr gs)
Definition: globals.c:506
#define malloc
Definition: debug_ros.c:4
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
GLfloat GLfloat p
Definition: glext.h:8902
void __xmlGlobalInitMutexLock(void)
Definition: threads.c:427
#define INFINITE
Definition: serial.h:102
#define memset(x, y, z)
Definition: compat.h:39
static TfClientId tid
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
void xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
Definition: threads.c:388
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:362