OLD | NEW |
1 /** | 1 /** |
2 * threads.c: set of generic threading related routines | 2 * threads.c: set of generic threading related routines |
3 * | 3 * |
4 * See Copyright for the status of this software. | 4 * See Copyright for the status of this software. |
5 * | 5 * |
6 * Gary Pennington <Gary.Pennington@uk.sun.com> | 6 * Gary Pennington <Gary.Pennington@uk.sun.com> |
7 * daniel@veillard.com | 7 * daniel@veillard.com |
8 */ | 8 */ |
9 | 9 |
10 #define IN_LIBXML | 10 #define IN_LIBXML |
11 #include "libxml.h" | 11 #include "libxml.h" |
12 | 12 |
13 #include <string.h> | 13 #include <string.h> |
14 | 14 |
15 #include <libxml/threads.h> | 15 #include <libxml/threads.h> |
16 #include <libxml/globals.h> | 16 #include <libxml/globals.h> |
17 | 17 |
18 #ifdef HAVE_SYS_TYPES_H | 18 #ifdef HAVE_SYS_TYPES_H |
19 #include <sys/types.h> | 19 #include <sys/types.h> |
20 #endif | 20 #endif |
21 #ifdef HAVE_UNISTD_H | 21 #ifdef HAVE_UNISTD_H |
22 #include <unistd.h> | 22 #include <unistd.h> |
23 #endif | 23 #endif |
24 #ifdef HAVE_STDLIB_H | 24 #ifdef HAVE_STDLIB_H |
25 #include <stdlib.h> | 25 #include <stdlib.h> |
26 #endif | 26 #endif |
27 #ifdef HAVE_PTHREAD_H | 27 #ifdef HAVE_PTHREAD_H |
28 #include <pthread.h> | 28 #include <pthread.h> |
29 #endif | 29 #elif defined HAVE_WIN32_THREADS |
30 | |
31 #ifdef HAVE_WIN32_THREADS | |
32 #include <windows.h> | 30 #include <windows.h> |
33 #ifndef HAVE_COMPILER_TLS | 31 #ifndef HAVE_COMPILER_TLS |
34 #include <process.h> | 32 #include <process.h> |
35 #endif | 33 #endif |
36 #endif | 34 #endif |
37 | 35 |
38 #ifdef HAVE_BEOS_THREADS | 36 #ifdef HAVE_BEOS_THREADS |
39 #include <OS.h> | 37 #include <OS.h> |
40 #include <TLS.h> | 38 #include <TLS.h> |
41 #endif | 39 #endif |
(...skipping 14 matching lines...) Expand all Loading... |
56 void (*__init_routine) (void)) | 54 void (*__init_routine) (void)) |
57 __attribute((weak)); | 55 __attribute((weak)); |
58 extern void *pthread_getspecific (pthread_key_t __key) | 56 extern void *pthread_getspecific (pthread_key_t __key) |
59 __attribute((weak)); | 57 __attribute((weak)); |
60 extern int pthread_setspecific (pthread_key_t __key, | 58 extern int pthread_setspecific (pthread_key_t __key, |
61 __const void *__pointer) | 59 __const void *__pointer) |
62 __attribute((weak)); | 60 __attribute((weak)); |
63 extern int pthread_key_create (pthread_key_t *__key, | 61 extern int pthread_key_create (pthread_key_t *__key, |
64 void (*__destr_function) (void *)) | 62 void (*__destr_function) (void *)) |
65 __attribute((weak)); | 63 __attribute((weak)); |
| 64 extern int pthread_key_delete (pthread_key_t __key) |
| 65 __attribute((weak)); |
66 extern int pthread_mutex_init () | 66 extern int pthread_mutex_init () |
67 __attribute((weak)); | 67 __attribute((weak)); |
68 extern int pthread_mutex_destroy () | 68 extern int pthread_mutex_destroy () |
69 __attribute((weak)); | 69 __attribute((weak)); |
70 extern int pthread_mutex_lock () | 70 extern int pthread_mutex_lock () |
71 __attribute((weak)); | 71 __attribute((weak)); |
72 extern int pthread_mutex_unlock () | 72 extern int pthread_mutex_unlock () |
73 __attribute((weak)); | 73 __attribute((weak)); |
74 extern int pthread_cond_init () | 74 extern int pthread_cond_init () |
75 __attribute((weak)); | 75 __attribute((weak)); |
| 76 extern int pthread_cond_destroy () |
| 77 __attribute((weak)); |
| 78 extern int pthread_cond_wait () |
| 79 __attribute((weak)); |
76 extern int pthread_equal () | 80 extern int pthread_equal () |
77 __attribute((weak)); | 81 __attribute((weak)); |
78 extern pthread_t pthread_self () | 82 extern pthread_t pthread_self () |
79 __attribute((weak)); | 83 __attribute((weak)); |
80 extern int pthread_key_create () | 84 extern int pthread_key_create () |
81 __attribute((weak)); | 85 __attribute((weak)); |
| 86 extern int pthread_key_delete () |
| 87 __attribute((weak)); |
82 extern int pthread_cond_signal () | 88 extern int pthread_cond_signal () |
83 __attribute((weak)); | 89 __attribute((weak)); |
84 #endif | 90 #endif |
85 #endif /* linux */ | 91 #endif /* linux */ |
86 #endif /* __GNUC__ */ | 92 #endif /* __GNUC__ */ |
87 #endif /* HAVE_PTHREAD_H */ | 93 #endif /* HAVE_PTHREAD_H */ |
88 | 94 |
89 /* | 95 /* |
90 * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree | 96 * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree |
91 * to avoid some crazyness since xmlMalloc/xmlFree may actually | 97 * to avoid some crazyness since xmlMalloc/xmlFree may actually |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 return; | 403 return; |
398 #ifdef HAVE_PTHREAD_H | 404 #ifdef HAVE_PTHREAD_H |
399 if (libxml_is_threaded == 0) | 405 if (libxml_is_threaded == 0) |
400 return; | 406 return; |
401 | 407 |
402 pthread_mutex_lock(&tok->lock); | 408 pthread_mutex_lock(&tok->lock); |
403 tok->held--; | 409 tok->held--; |
404 if (tok->held == 0) { | 410 if (tok->held == 0) { |
405 if (tok->waiters) | 411 if (tok->waiters) |
406 pthread_cond_signal(&tok->cv); | 412 pthread_cond_signal(&tok->cv); |
407 tok->tid = 0; | 413 memset(&tok->tid, 0, sizeof(tok->tid)); |
408 } | 414 } |
409 pthread_mutex_unlock(&tok->lock); | 415 pthread_mutex_unlock(&tok->lock); |
410 #elif defined HAVE_WIN32_THREADS | 416 #elif defined HAVE_WIN32_THREADS |
411 if (!--tok->count) | 417 if (!--tok->count) |
412 LeaveCriticalSection(&tok->cs); | 418 LeaveCriticalSection(&tok->cs); |
413 #elif defined HAVE_BEOS_THREADS | 419 #elif defined HAVE_BEOS_THREADS |
414 if (tok->lock->tid == find_thread(NULL)) { | 420 if (tok->lock->tid == find_thread(NULL)) { |
415 tok->count--; | 421 tok->count--; |
416 if (tok->count == 0) { | 422 if (tok->count == 0) { |
417 xmlMutexUnlock(tok->lock); | 423 xmlMutexUnlock(tok->lock); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 | 520 |
515 /** | 521 /** |
516 * xmlGlobalInitMutexDestroy | 522 * xmlGlobalInitMutexDestroy |
517 * | 523 * |
518 * Makes sure that the global initialization mutex is destroyed before | 524 * Makes sure that the global initialization mutex is destroyed before |
519 * application termination. | 525 * application termination. |
520 */ | 526 */ |
521 void | 527 void |
522 __xmlGlobalInitMutexDestroy(void) | 528 __xmlGlobalInitMutexDestroy(void) |
523 { | 529 { |
524 #if defined HAVE_WIN32_THREADS | 530 #ifdef HAVE_PTHREAD_H |
| 531 #elif defined HAVE_WIN32_THREADS |
525 if (global_init_lock != NULL) { | 532 if (global_init_lock != NULL) { |
526 DeleteCriticalSection(global_init_lock); | 533 DeleteCriticalSection(global_init_lock); |
527 free(global_init_lock); | 534 free(global_init_lock); |
528 global_init_lock = NULL; | 535 global_init_lock = NULL; |
529 } | 536 } |
530 #endif | 537 #endif |
531 } | 538 } |
532 | 539 |
533 /************************************************************************ | 540 /************************************************************************ |
534 * * | 541 * * |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 "xmlGetGlobalState: out of memory\n"); | 585 "xmlGetGlobalState: out of memory\n"); |
579 return (NULL); | 586 return (NULL); |
580 } | 587 } |
581 | 588 |
582 memset(gs, 0, sizeof(xmlGlobalState)); | 589 memset(gs, 0, sizeof(xmlGlobalState)); |
583 xmlInitializeGlobalState(gs); | 590 xmlInitializeGlobalState(gs); |
584 return (gs); | 591 return (gs); |
585 } | 592 } |
586 #endif /* LIBXML_THREAD_ENABLED */ | 593 #endif /* LIBXML_THREAD_ENABLED */ |
587 | 594 |
588 | 595 #ifdef HAVE_PTHREAD_H |
589 #ifdef HAVE_WIN32_THREADS | 596 #elif defined HAVE_WIN32_THREADS |
590 #if !defined(HAVE_COMPILER_TLS) | 597 #if !defined(HAVE_COMPILER_TLS) |
591 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) | 598 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) |
592 typedef struct _xmlGlobalStateCleanupHelperParams { | 599 typedef struct _xmlGlobalStateCleanupHelperParams { |
593 HANDLE thread; | 600 HANDLE thread; |
594 void *memory; | 601 void *memory; |
595 } xmlGlobalStateCleanupHelperParams; | 602 } xmlGlobalStateCleanupHelperParams; |
596 | 603 |
597 static void XMLCDECL | 604 static void XMLCDECL |
598 xmlGlobalStateCleanupHelper(void *p) | 605 xmlGlobalStateCleanupHelper(void *p) |
599 { | 606 { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 if (globalval == NULL) { | 694 if (globalval == NULL) { |
688 xmlGlobalState *tsd = xmlNewGlobalState(); | 695 xmlGlobalState *tsd = xmlNewGlobalState(); |
689 | 696 |
690 if (tsd == NULL) | 697 if (tsd == NULL) |
691 return(NULL); | 698 return(NULL); |
692 p = (xmlGlobalStateCleanupHelperParams *) | 699 p = (xmlGlobalStateCleanupHelperParams *) |
693 malloc(sizeof(xmlGlobalStateCleanupHelperParams)); | 700 malloc(sizeof(xmlGlobalStateCleanupHelperParams)); |
694 if (p == NULL) { | 701 if (p == NULL) { |
695 xmlGenericError(xmlGenericErrorContext, | 702 xmlGenericError(xmlGenericErrorContext, |
696 "xmlGetGlobalState: out of memory\n"); | 703 "xmlGetGlobalState: out of memory\n"); |
| 704 xmlFreeGlobalState(tsd); |
697 return(NULL); | 705 return(NULL); |
698 } | 706 } |
699 p->memory = tsd; | 707 p->memory = tsd; |
700 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) | 708 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) |
701 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), | 709 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), |
702 GetCurrentProcess(), &p->thread, 0, TRUE, | 710 GetCurrentProcess(), &p->thread, 0, TRUE, |
703 DUPLICATE_SAME_ACCESS); | 711 DUPLICATE_SAME_ACCESS); |
704 TlsSetValue(globalkey, tsd); | 712 TlsSetValue(globalkey, tsd); |
705 _beginthread(xmlGlobalStateCleanupHelper, 0, p); | 713 _beginthread(xmlGlobalStateCleanupHelper, 0, p); |
706 #else | 714 #else |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 /************************************************************************ | 750 /************************************************************************ |
743 * * | 751 * * |
744 * Library wide thread interfaces * | 752 * Library wide thread interfaces * |
745 * * | 753 * * |
746 ************************************************************************/ | 754 ************************************************************************/ |
747 | 755 |
748 /** | 756 /** |
749 * xmlGetThreadId: | 757 * xmlGetThreadId: |
750 * | 758 * |
751 * xmlGetThreadId() find the current thread ID number | 759 * xmlGetThreadId() find the current thread ID number |
| 760 * Note that this is likely to be broken on some platforms using pthreads |
| 761 * as the specification doesn't mandate pthread_t to be an integer type |
752 * | 762 * |
753 * Returns the current thread ID number | 763 * Returns the current thread ID number |
754 */ | 764 */ |
755 int | 765 int |
756 xmlGetThreadId(void) | 766 xmlGetThreadId(void) |
757 { | 767 { |
758 #ifdef HAVE_PTHREAD_H | 768 #ifdef HAVE_PTHREAD_H |
| 769 pthread_t id; |
| 770 int ret; |
| 771 |
759 if (libxml_is_threaded == 0) | 772 if (libxml_is_threaded == 0) |
760 return (0); | 773 return (0); |
761 return ((int) pthread_self()); | 774 id = pthread_self(); |
| 775 /* horrible but preserves compat, see warning above */ |
| 776 memcpy(&ret, &id, sizeof(ret)); |
| 777 return (ret); |
762 #elif defined HAVE_WIN32_THREADS | 778 #elif defined HAVE_WIN32_THREADS |
763 return GetCurrentThreadId(); | 779 return GetCurrentThreadId(); |
764 #elif defined HAVE_BEOS_THREADS | 780 #elif defined HAVE_BEOS_THREADS |
765 return find_thread(NULL); | 781 return find_thread(NULL); |
766 #else | 782 #else |
767 return ((int) 0); | 783 return ((int) 0); |
768 #endif | 784 #endif |
769 } | 785 } |
770 | 786 |
771 /** | 787 /** |
(...skipping 15 matching lines...) Expand all Loading... |
787 #elif defined HAVE_WIN32_THREADS | 803 #elif defined HAVE_WIN32_THREADS |
788 xmlOnceInit(); | 804 xmlOnceInit(); |
789 #elif defined HAVE_BEOS_THREADS | 805 #elif defined HAVE_BEOS_THREADS |
790 xmlOnceInit(); | 806 xmlOnceInit(); |
791 #endif | 807 #endif |
792 | 808 |
793 #ifdef DEBUG_THREADS | 809 #ifdef DEBUG_THREADS |
794 xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n"); | 810 xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n"); |
795 #endif | 811 #endif |
796 #ifdef HAVE_PTHREAD_H | 812 #ifdef HAVE_PTHREAD_H |
797 return (mainthread == pthread_self()); | 813 return (pthread_equal(mainthread,pthread_self())); |
798 #elif defined HAVE_WIN32_THREADS | 814 #elif defined HAVE_WIN32_THREADS |
799 return (mainthread == GetCurrentThreadId()); | 815 return (mainthread == GetCurrentThreadId()); |
800 #elif defined HAVE_BEOS_THREADS | 816 #elif defined HAVE_BEOS_THREADS |
801 return (mainthread == find_thread(NULL)); | 817 return (mainthread == find_thread(NULL)); |
802 #else | 818 #else |
803 return (1); | 819 return (1); |
804 #endif | 820 #endif |
805 } | 821 } |
806 | 822 |
807 /** | 823 /** |
(...skipping 28 matching lines...) Expand all Loading... |
836 | 852 |
837 /** | 853 /** |
838 * xmlInitThreads: | 854 * xmlInitThreads: |
839 * | 855 * |
840 * xmlInitThreads() is used to to initialize all the thread related | 856 * xmlInitThreads() is used to to initialize all the thread related |
841 * data of the libxml2 library. | 857 * data of the libxml2 library. |
842 */ | 858 */ |
843 void | 859 void |
844 xmlInitThreads(void) | 860 xmlInitThreads(void) |
845 { | 861 { |
846 #ifdef DEBUG_THREADS | |
847 xmlGenericError(xmlGenericErrorContext, "xmlInitThreads()\n"); | |
848 #endif | |
849 #if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBX
ML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) | |
850 InitializeCriticalSection(&cleanup_helpers_cs); | |
851 #endif | |
852 #ifdef HAVE_PTHREAD_H | 862 #ifdef HAVE_PTHREAD_H |
853 if (libxml_is_threaded == -1) { | 863 if (libxml_is_threaded == -1) { |
854 if ((pthread_once != NULL) && | 864 if ((pthread_once != NULL) && |
855 (pthread_getspecific != NULL) && | 865 (pthread_getspecific != NULL) && |
856 (pthread_setspecific != NULL) && | 866 (pthread_setspecific != NULL) && |
857 (pthread_key_create != NULL) && | 867 (pthread_key_create != NULL) && |
| 868 (pthread_key_delete != NULL) && |
858 (pthread_mutex_init != NULL) && | 869 (pthread_mutex_init != NULL) && |
859 (pthread_mutex_destroy != NULL) && | 870 (pthread_mutex_destroy != NULL) && |
860 (pthread_mutex_lock != NULL) && | 871 (pthread_mutex_lock != NULL) && |
861 (pthread_mutex_unlock != NULL) && | 872 (pthread_mutex_unlock != NULL) && |
862 (pthread_cond_init != NULL) && | 873 (pthread_cond_init != NULL) && |
| 874 (pthread_cond_destroy != NULL) && |
| 875 (pthread_cond_wait != NULL) && |
863 (pthread_equal != NULL) && | 876 (pthread_equal != NULL) && |
864 (pthread_self != NULL) && | 877 (pthread_self != NULL) && |
865 (pthread_cond_signal != NULL)) { | 878 (pthread_cond_signal != NULL)) { |
866 libxml_is_threaded = 1; | 879 libxml_is_threaded = 1; |
867 | 880 |
868 /* fprintf(stderr, "Running multithreaded\n"); */ | 881 /* fprintf(stderr, "Running multithreaded\n"); */ |
869 } else { | 882 } else { |
870 | 883 |
871 /* fprintf(stderr, "Running without multithread\n"); */ | 884 /* fprintf(stderr, "Running without multithread\n"); */ |
872 libxml_is_threaded = 0; | 885 libxml_is_threaded = 0; |
873 } | 886 } |
874 } | 887 } |
| 888 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LI
BXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) |
| 889 InitializeCriticalSection(&cleanup_helpers_cs); |
875 #endif | 890 #endif |
876 } | 891 } |
877 | 892 |
878 /** | 893 /** |
879 * xmlCleanupThreads: | 894 * xmlCleanupThreads: |
880 * | 895 * |
881 * xmlCleanupThreads() is used to to cleanup all the thread related | 896 * xmlCleanupThreads() is used to to cleanup all the thread related |
882 * data of the libxml2 library once processing has ended. | 897 * data of the libxml2 library once processing has ended. |
| 898 * |
| 899 * WARNING: if your application is multithreaded or has plugin support |
| 900 * calling this may crash the application if another thread or |
| 901 * a plugin is still using libxml2. It's sometimes very hard to |
| 902 * guess if libxml2 is in use in the application, some libraries |
| 903 * or plugins may use it without notice. In case of doubt abstain |
| 904 * from calling this function or do it just before calling exit() |
| 905 * to avoid leak reports from valgrind ! |
883 */ | 906 */ |
884 void | 907 void |
885 xmlCleanupThreads(void) | 908 xmlCleanupThreads(void) |
886 { | 909 { |
887 #ifdef DEBUG_THREADS | 910 #ifdef DEBUG_THREADS |
888 xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n"); | 911 xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n"); |
889 #endif | 912 #endif |
890 #if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBX
ML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) | 913 #ifdef HAVE_PTHREAD_H |
| 914 if ((libxml_is_threaded) && (pthread_key_delete != NULL)) |
| 915 pthread_key_delete(globalkey); |
| 916 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LI
BXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) |
891 if (globalkey != TLS_OUT_OF_INDEXES) { | 917 if (globalkey != TLS_OUT_OF_INDEXES) { |
892 xmlGlobalStateCleanupHelperParams *p; | 918 xmlGlobalStateCleanupHelperParams *p; |
893 | 919 |
894 EnterCriticalSection(&cleanup_helpers_cs); | 920 EnterCriticalSection(&cleanup_helpers_cs); |
895 p = cleanup_helpers_head; | 921 p = cleanup_helpers_head; |
896 while (p != NULL) { | 922 while (p != NULL) { |
897 xmlGlobalStateCleanupHelperParams *temp = p; | 923 xmlGlobalStateCleanupHelperParams *temp = p; |
898 | 924 |
899 p = p->next; | 925 p = p->next; |
900 xmlFreeGlobalState(temp->memory); | 926 xmlFreeGlobalState(temp->memory); |
(...skipping 18 matching lines...) Expand all Loading... |
919 * pthread_once() in association with the once_control variable to ensure | 945 * pthread_once() in association with the once_control variable to ensure |
920 * that the function is only called once. See man pthread_once for more | 946 * that the function is only called once. See man pthread_once for more |
921 * details. | 947 * details. |
922 */ | 948 */ |
923 static void | 949 static void |
924 xmlOnceInit(void) | 950 xmlOnceInit(void) |
925 { | 951 { |
926 #ifdef HAVE_PTHREAD_H | 952 #ifdef HAVE_PTHREAD_H |
927 (void) pthread_key_create(&globalkey, xmlFreeGlobalState); | 953 (void) pthread_key_create(&globalkey, xmlFreeGlobalState); |
928 mainthread = pthread_self(); | 954 mainthread = pthread_self(); |
929 #endif | 955 #elif defined(HAVE_WIN32_THREADS) |
930 | |
931 #if defined(HAVE_WIN32_THREADS) | |
932 if (!run_once.done) { | 956 if (!run_once.done) { |
933 if (InterlockedIncrement(&run_once.control) == 1) { | 957 if (InterlockedIncrement(&run_once.control) == 1) { |
934 #if !defined(HAVE_COMPILER_TLS) | 958 #if !defined(HAVE_COMPILER_TLS) |
935 globalkey = TlsAlloc(); | 959 globalkey = TlsAlloc(); |
936 #endif | 960 #endif |
937 mainthread = GetCurrentThreadId(); | 961 mainthread = GetCurrentThreadId(); |
938 run_once.done = 1; | 962 run_once.done = 1; |
939 } else { | 963 } else { |
940 /* Another thread is working; give up our slice and | 964 /* Another thread is working; give up our slice and |
941 * wait until they're done. */ | 965 * wait until they're done. */ |
942 while (!run_once.done) | 966 while (!run_once.done) |
943 Sleep(0); | 967 Sleep(0); |
944 } | 968 } |
945 } | 969 } |
946 #endif | 970 #elif defined HAVE_BEOS_THREADS |
947 | |
948 #ifdef HAVE_BEOS_THREADS | |
949 if (atomic_add(&run_once_init, 1) == 0) { | 971 if (atomic_add(&run_once_init, 1) == 0) { |
950 globalkey = tls_allocate(); | 972 globalkey = tls_allocate(); |
951 tls_set(globalkey, NULL); | 973 tls_set(globalkey, NULL); |
952 mainthread = find_thread(NULL); | 974 mainthread = find_thread(NULL); |
953 } else | 975 } else |
954 atomic_add(&run_once_init, -1); | 976 atomic_add(&run_once_init, -1); |
955 #endif | 977 #endif |
956 } | 978 } |
957 #endif | 979 #endif |
958 | 980 |
959 /** | 981 /** |
960 * DllMain: | 982 * DllMain: |
961 * @hinstDLL: handle to DLL instance | 983 * @hinstDLL: handle to DLL instance |
962 * @fdwReason: Reason code for entry | 984 * @fdwReason: Reason code for entry |
963 * @lpvReserved: generic pointer (depends upon reason code) | 985 * @lpvReserved: generic pointer (depends upon reason code) |
964 * | 986 * |
965 * Entry point for Windows library. It is being used to free thread-specific | 987 * Entry point for Windows library. It is being used to free thread-specific |
966 * storage. | 988 * storage. |
967 * | 989 * |
968 * Returns TRUE always | 990 * Returns TRUE always |
969 */ | 991 */ |
970 #if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBX
ML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) | 992 #ifdef HAVE_PTHREAD_H |
| 993 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LI
BXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) |
971 #if defined(LIBXML_STATIC_FOR_DLL) | 994 #if defined(LIBXML_STATIC_FOR_DLL) |
972 BOOL XMLCALL | 995 BOOL XMLCALL |
973 xmlDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | 996 xmlDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) |
974 #else | 997 #else |
975 BOOL WINAPI | 998 BOOL WINAPI |
976 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | 999 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) |
977 #endif | 1000 #endif |
978 { | 1001 { |
979 switch (fdwReason) { | 1002 switch (fdwReason) { |
980 case DLL_THREAD_DETACH: | 1003 case DLL_THREAD_DETACH: |
(...skipping 19 matching lines...) Expand all Loading... |
1000 free(p); | 1023 free(p); |
1001 } | 1024 } |
1002 } | 1025 } |
1003 break; | 1026 break; |
1004 } | 1027 } |
1005 return TRUE; | 1028 return TRUE; |
1006 } | 1029 } |
1007 #endif | 1030 #endif |
1008 #define bottom_threads | 1031 #define bottom_threads |
1009 #include "elfgcchack.h" | 1032 #include "elfgcchack.h" |
OLD | NEW |