Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenthreads.c
Go to the documentation of this file.
00001 00010 #define IN_LIBXML 00011 #include "libxml.h" 00012 00013 #include <string.h> 00014 00015 #include <libxml/threads.h> 00016 #include <libxml/globals.h> 00017 00018 #ifdef HAVE_SYS_TYPES_H 00019 #include <sys/types.h> 00020 #endif 00021 #ifdef HAVE_UNISTD_H 00022 #include <unistd.h> 00023 #endif 00024 #ifdef HAVE_STDLIB_H 00025 #include <stdlib.h> 00026 #endif 00027 #ifdef HAVE_PTHREAD_H 00028 #include <pthread.h> 00029 #elif defined HAVE_WIN32_THREADS 00030 #include <windows.h> 00031 #ifndef HAVE_COMPILER_TLS 00032 #include <process.h> 00033 #endif 00034 #endif 00035 00036 #ifdef HAVE_BEOS_THREADS 00037 #include <OS.h> 00038 #include <TLS.h> 00039 #endif 00040 00041 #if defined(SOLARIS) 00042 #include <note.h> 00043 #endif 00044 00045 /* #define DEBUG_THREADS */ 00046 00047 #ifdef HAVE_PTHREAD_H 00048 00049 static int libxml_is_threaded = -1; 00050 #ifdef __GNUC__ 00051 #ifdef linux 00052 #if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ > 3) 00053 extern int pthread_once (pthread_once_t *__once_control, 00054 void (*__init_routine) (void)) 00055 __attribute((weak)); 00056 extern void *pthread_getspecific (pthread_key_t __key) 00057 __attribute((weak)); 00058 extern int pthread_setspecific (pthread_key_t __key, 00059 __const void *__pointer) 00060 __attribute((weak)); 00061 extern int pthread_key_create (pthread_key_t *__key, 00062 void (*__destr_function) (void *)) 00063 __attribute((weak)); 00064 extern int pthread_key_delete (pthread_key_t __key) 00065 __attribute((weak)); 00066 extern int pthread_mutex_init () 00067 __attribute((weak)); 00068 extern int pthread_mutex_destroy () 00069 __attribute((weak)); 00070 extern int pthread_mutex_lock () 00071 __attribute((weak)); 00072 extern int pthread_mutex_unlock () 00073 __attribute((weak)); 00074 extern int pthread_cond_init () 00075 __attribute((weak)); 00076 extern int pthread_cond_destroy () 00077 __attribute((weak)); 00078 extern int pthread_cond_wait () 00079 __attribute((weak)); 00080 extern int pthread_equal () 00081 __attribute((weak)); 00082 extern pthread_t pthread_self () 00083 __attribute((weak)); 00084 extern int pthread_key_create () 00085 __attribute((weak)); 00086 extern int pthread_key_delete () 00087 __attribute((weak)); 00088 extern int pthread_cond_signal () 00089 __attribute((weak)); 00090 #endif 00091 #endif /* linux */ 00092 #endif /* __GNUC__ */ 00093 #endif /* HAVE_PTHREAD_H */ 00094 00095 /* 00096 * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree 00097 * to avoid some crazyness since xmlMalloc/xmlFree may actually 00098 * be hosted on allocated blocks needing them for the allocation ... 00099 */ 00100 00101 /* 00102 * xmlMutex are a simple mutual exception locks 00103 */ 00104 struct _xmlMutex { 00105 #ifdef HAVE_PTHREAD_H 00106 pthread_mutex_t lock; 00107 #elif defined HAVE_WIN32_THREADS 00108 HANDLE mutex; 00109 #elif defined HAVE_BEOS_THREADS 00110 sem_id sem; 00111 thread_id tid; 00112 #else 00113 int empty; 00114 #endif 00115 }; 00116 00117 /* 00118 * xmlRMutex are reentrant mutual exception locks 00119 */ 00120 struct _xmlRMutex { 00121 #ifdef HAVE_PTHREAD_H 00122 pthread_mutex_t lock; 00123 unsigned int held; 00124 unsigned int waiters; 00125 pthread_t tid; 00126 pthread_cond_t cv; 00127 #elif defined HAVE_WIN32_THREADS 00128 CRITICAL_SECTION cs; 00129 unsigned int count; 00130 #elif defined HAVE_BEOS_THREADS 00131 xmlMutexPtr lock; 00132 thread_id tid; 00133 int32 count; 00134 #else 00135 int empty; 00136 #endif 00137 }; 00138 00139 /* 00140 * This module still has some internal static data. 00141 * - xmlLibraryLock a global lock 00142 * - globalkey used for per-thread data 00143 */ 00144 00145 #ifdef HAVE_PTHREAD_H 00146 static pthread_key_t globalkey; 00147 static pthread_t mainthread; 00148 static pthread_once_t once_control = PTHREAD_ONCE_INIT; 00149 static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER; 00150 #elif defined HAVE_WIN32_THREADS 00151 #if defined(HAVE_COMPILER_TLS) 00152 static __declspec(thread) xmlGlobalState tlstate; 00153 static __declspec(thread) int tlstate_inited = 0; 00154 #else /* HAVE_COMPILER_TLS */ 00155 static DWORD globalkey = TLS_OUT_OF_INDEXES; 00156 #endif /* HAVE_COMPILER_TLS */ 00157 static DWORD mainthread; 00158 static struct { 00159 DWORD done; 00160 DWORD control; 00161 } run_once = { 0, 0}; 00162 static volatile LPCRITICAL_SECTION global_init_lock = NULL; 00163 00164 /* endif HAVE_WIN32_THREADS */ 00165 #elif defined HAVE_BEOS_THREADS 00166 int32 globalkey = 0; 00167 thread_id mainthread = 0; 00168 int32 run_once_init = 0; 00169 static int32 global_init_lock = -1; 00170 static vint32 global_init_count = 0; 00171 #endif 00172 00173 static xmlRMutexPtr xmlLibraryLock = NULL; 00174 00175 #ifdef LIBXML_THREAD_ENABLED 00176 static void xmlOnceInit(void); 00177 #endif 00178 00187 xmlMutexPtr 00188 xmlNewMutex(void) 00189 { 00190 xmlMutexPtr tok; 00191 00192 if ((tok = malloc(sizeof(xmlMutex))) == NULL) 00193 return (NULL); 00194 #ifdef HAVE_PTHREAD_H 00195 if (libxml_is_threaded != 0) 00196 pthread_mutex_init(&tok->lock, NULL); 00197 #elif defined HAVE_WIN32_THREADS 00198 tok->mutex = CreateMutex(NULL, FALSE, NULL); 00199 #elif defined HAVE_BEOS_THREADS 00200 if ((tok->sem = create_sem(1, "xmlMutex")) < B_OK) { 00201 free(tok); 00202 return NULL; 00203 } 00204 tok->tid = -1; 00205 #endif 00206 return (tok); 00207 } 00208 00216 void 00217 xmlFreeMutex(xmlMutexPtr tok) 00218 { 00219 if (tok == NULL) 00220 return; 00221 00222 #ifdef HAVE_PTHREAD_H 00223 if (libxml_is_threaded != 0) 00224 pthread_mutex_destroy(&tok->lock); 00225 #elif defined HAVE_WIN32_THREADS 00226 CloseHandle(tok->mutex); 00227 #elif defined HAVE_BEOS_THREADS 00228 delete_sem(tok->sem); 00229 #endif 00230 free(tok); 00231 } 00232 00239 void 00240 xmlMutexLock(xmlMutexPtr tok) 00241 { 00242 if (tok == NULL) 00243 return; 00244 #ifdef HAVE_PTHREAD_H 00245 if (libxml_is_threaded != 0) 00246 pthread_mutex_lock(&tok->lock); 00247 #elif defined HAVE_WIN32_THREADS 00248 WaitForSingleObject(tok->mutex, INFINITE); 00249 #elif defined HAVE_BEOS_THREADS 00250 if (acquire_sem(tok->sem) != B_NO_ERROR) { 00251 #ifdef DEBUG_THREADS 00252 xmlGenericError(xmlGenericErrorContext, 00253 "xmlMutexLock():BeOS:Couldn't aquire semaphore\n"); 00254 exit(); 00255 #endif 00256 } 00257 tok->tid = find_thread(NULL); 00258 #endif 00259 00260 } 00261 00268 void 00269 xmlMutexUnlock(xmlMutexPtr tok) 00270 { 00271 if (tok == NULL) 00272 return; 00273 #ifdef HAVE_PTHREAD_H 00274 if (libxml_is_threaded != 0) 00275 pthread_mutex_unlock(&tok->lock); 00276 #elif defined HAVE_WIN32_THREADS 00277 ReleaseMutex(tok->mutex); 00278 #elif defined HAVE_BEOS_THREADS 00279 if (tok->tid == find_thread(NULL)) { 00280 tok->tid = -1; 00281 release_sem(tok->sem); 00282 } 00283 #endif 00284 } 00285 00296 xmlRMutexPtr 00297 xmlNewRMutex(void) 00298 { 00299 xmlRMutexPtr tok; 00300 00301 if ((tok = malloc(sizeof(xmlRMutex))) == NULL) 00302 return (NULL); 00303 #ifdef HAVE_PTHREAD_H 00304 if (libxml_is_threaded != 0) { 00305 pthread_mutex_init(&tok->lock, NULL); 00306 tok->held = 0; 00307 tok->waiters = 0; 00308 pthread_cond_init(&tok->cv, NULL); 00309 } 00310 #elif defined HAVE_WIN32_THREADS 00311 InitializeCriticalSection(&tok->cs); 00312 tok->count = 0; 00313 #elif defined HAVE_BEOS_THREADS 00314 if ((tok->lock = xmlNewMutex()) == NULL) { 00315 free(tok); 00316 return NULL; 00317 } 00318 tok->count = 0; 00319 #endif 00320 return (tok); 00321 } 00322 00330 void 00331 xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED) 00332 { 00333 if (tok == NULL) 00334 return; 00335 #ifdef HAVE_PTHREAD_H 00336 if (libxml_is_threaded != 0) { 00337 pthread_mutex_destroy(&tok->lock); 00338 pthread_cond_destroy(&tok->cv); 00339 } 00340 #elif defined HAVE_WIN32_THREADS 00341 DeleteCriticalSection(&tok->cs); 00342 #elif defined HAVE_BEOS_THREADS 00343 xmlFreeMutex(tok->lock); 00344 #endif 00345 free(tok); 00346 } 00347 00354 void 00355 xmlRMutexLock(xmlRMutexPtr tok) 00356 { 00357 if (tok == NULL) 00358 return; 00359 #ifdef HAVE_PTHREAD_H 00360 if (libxml_is_threaded == 0) 00361 return; 00362 00363 pthread_mutex_lock(&tok->lock); 00364 if (tok->held) { 00365 if (pthread_equal(tok->tid, pthread_self())) { 00366 tok->held++; 00367 pthread_mutex_unlock(&tok->lock); 00368 return; 00369 } else { 00370 tok->waiters++; 00371 while (tok->held) 00372 pthread_cond_wait(&tok->cv, &tok->lock); 00373 tok->waiters--; 00374 } 00375 } 00376 tok->tid = pthread_self(); 00377 tok->held = 1; 00378 pthread_mutex_unlock(&tok->lock); 00379 #elif defined HAVE_WIN32_THREADS 00380 EnterCriticalSection(&tok->cs); 00381 ++tok->count; 00382 #elif defined HAVE_BEOS_THREADS 00383 if (tok->lock->tid == find_thread(NULL)) { 00384 tok->count++; 00385 return; 00386 } else { 00387 xmlMutexLock(tok->lock); 00388 tok->count = 1; 00389 } 00390 #endif 00391 } 00392 00399 void 00400 xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED) 00401 { 00402 if (tok == NULL) 00403 return; 00404 #ifdef HAVE_PTHREAD_H 00405 if (libxml_is_threaded == 0) 00406 return; 00407 00408 pthread_mutex_lock(&tok->lock); 00409 tok->held--; 00410 if (tok->held == 0) { 00411 if (tok->waiters) 00412 pthread_cond_signal(&tok->cv); 00413 memset(&tok->tid, 0, sizeof(tok->tid)); 00414 } 00415 pthread_mutex_unlock(&tok->lock); 00416 #elif defined HAVE_WIN32_THREADS 00417 if (!--tok->count) 00418 LeaveCriticalSection(&tok->cs); 00419 #elif defined HAVE_BEOS_THREADS 00420 if (tok->lock->tid == find_thread(NULL)) { 00421 tok->count--; 00422 if (tok->count == 0) { 00423 xmlMutexUnlock(tok->lock); 00424 } 00425 return; 00426 } 00427 #endif 00428 } 00429 00436 void 00437 __xmlGlobalInitMutexLock(void) 00438 { 00439 /* Make sure the global init lock is initialized and then lock it. */ 00440 #ifdef HAVE_PTHREAD_H 00441 /* The mutex is statically initialized, so we just lock it. */ 00442 if (pthread_mutex_lock) 00443 pthread_mutex_lock(&global_init_lock); 00444 #elif defined HAVE_WIN32_THREADS 00445 LPCRITICAL_SECTION cs; 00446 00447 /* Create a new critical section */ 00448 if (global_init_lock == NULL) { 00449 cs = malloc(sizeof(CRITICAL_SECTION)); 00450 if (cs == NULL) { 00451 xmlGenericError(xmlGenericErrorContext, 00452 "xmlGlobalInitMutexLock: out of memory\n"); 00453 return; 00454 } 00455 InitializeCriticalSection(cs); 00456 00457 /* Swap it into the global_init_lock */ 00458 #ifdef InterlockedCompareExchangePointer 00459 InterlockedCompareExchangePointer(&global_init_lock, cs, NULL); 00460 #else /* Use older void* version */ 00461 InterlockedCompareExchange((void **) &global_init_lock, 00462 (void *) cs, NULL); 00463 #endif /* InterlockedCompareExchangePointer */ 00464 00465 /* If another thread successfully recorded its critical 00466 * section in the global_init_lock then discard the one 00467 * allocated by this thread. */ 00468 if (global_init_lock != cs) { 00469 DeleteCriticalSection(cs); 00470 free(cs); 00471 } 00472 } 00473 00474 /* Lock the chosen critical section */ 00475 EnterCriticalSection(global_init_lock); 00476 #elif defined HAVE_BEOS_THREADS 00477 int32 sem; 00478 00479 /* Allocate a new semaphore */ 00480 sem = create_sem(1, "xmlGlobalinitMutex"); 00481 00482 while (global_init_lock == -1) { 00483 if (atomic_add(&global_init_count, 1) == 0) { 00484 global_init_lock = sem; 00485 } else { 00486 snooze(1); 00487 atomic_add(&global_init_count, -1); 00488 } 00489 } 00490 00491 /* If another thread successfully recorded its critical 00492 * section in the global_init_lock then discard the one 00493 * allocated by this thread. */ 00494 if (global_init_lock != sem) 00495 delete_sem(sem); 00496 00497 /* Acquire the chosen semaphore */ 00498 if (acquire_sem(global_init_lock) != B_NO_ERROR) { 00499 #ifdef DEBUG_THREADS 00500 xmlGenericError(xmlGenericErrorContext, 00501 "xmlGlobalInitMutexLock():BeOS:Couldn't acquire semaphore\n"); 00502 exit(); 00503 #endif 00504 } 00505 #endif 00506 } 00507 00508 void 00509 __xmlGlobalInitMutexUnlock(void) 00510 { 00511 #ifdef HAVE_PTHREAD_H 00512 if (pthread_mutex_unlock) 00513 pthread_mutex_unlock(&global_init_lock); 00514 #elif defined HAVE_WIN32_THREADS 00515 if (global_init_lock != NULL) { 00516 LeaveCriticalSection(global_init_lock); 00517 } 00518 #elif defined HAVE_BEOS_THREADS 00519 release_sem(global_init_lock); 00520 #endif 00521 } 00522 00529 void 00530 __xmlGlobalInitMutexDestroy(void) 00531 { 00532 #ifdef HAVE_PTHREAD_H 00533 #elif defined HAVE_WIN32_THREADS 00534 if (global_init_lock != NULL) { 00535 DeleteCriticalSection(global_init_lock); 00536 free(global_init_lock); 00537 global_init_lock = NULL; 00538 } 00539 #endif 00540 } 00541 00542 /************************************************************************ 00543 * * 00544 * Per thread global state handling * 00545 * * 00546 ************************************************************************/ 00547 00548 #ifdef LIBXML_THREAD_ENABLED 00549 #ifdef xmlLastError 00550 #undef xmlLastError 00551 #endif 00552 00560 static void 00561 xmlFreeGlobalState(void *state) 00562 { 00563 xmlGlobalState *gs = (xmlGlobalState *) state; 00564 00565 /* free any memory allocated in the thread's xmlLastError */ 00566 xmlResetError(&(gs->xmlLastError)); 00567 free(state); 00568 } 00569 00579 static xmlGlobalStatePtr 00580 xmlNewGlobalState(void) 00581 { 00582 xmlGlobalState *gs; 00583 00584 gs = malloc(sizeof(xmlGlobalState)); 00585 if (gs == NULL) { 00586 xmlGenericError(xmlGenericErrorContext, 00587 "xmlGetGlobalState: out of memory\n"); 00588 return (NULL); 00589 } 00590 00591 memset(gs, 0, sizeof(xmlGlobalState)); 00592 xmlInitializeGlobalState(gs); 00593 return (gs); 00594 } 00595 #endif /* LIBXML_THREAD_ENABLED */ 00596 00597 #ifdef HAVE_PTHREAD_H 00598 #elif defined HAVE_WIN32_THREADS 00599 #if !defined(HAVE_COMPILER_TLS) 00600 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) 00601 typedef struct _xmlGlobalStateCleanupHelperParams { 00602 HANDLE thread; 00603 void *memory; 00604 } xmlGlobalStateCleanupHelperParams; 00605 00606 static void XMLCDECL 00607 xmlGlobalStateCleanupHelper(void *p) 00608 { 00609 xmlGlobalStateCleanupHelperParams *params = 00610 (xmlGlobalStateCleanupHelperParams *) p; 00611 WaitForSingleObject(params->thread, INFINITE); 00612 CloseHandle(params->thread); 00613 xmlFreeGlobalState(params->memory); 00614 free(params); 00615 _endthread(); 00616 } 00617 #else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */ 00618 00619 typedef struct _xmlGlobalStateCleanupHelperParams { 00620 void *memory; 00621 struct _xmlGlobalStateCleanupHelperParams *prev; 00622 struct _xmlGlobalStateCleanupHelperParams *next; 00623 } xmlGlobalStateCleanupHelperParams; 00624 00625 static xmlGlobalStateCleanupHelperParams *cleanup_helpers_head = NULL; 00626 static CRITICAL_SECTION cleanup_helpers_cs; 00627 00628 #endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */ 00629 #endif /* HAVE_COMPILER_TLS */ 00630 #endif /* HAVE_WIN32_THREADS */ 00631 00632 #if defined HAVE_BEOS_THREADS 00633 00640 void 00641 xmlGlobalStateCleanup(void *data) 00642 { 00643 void *globalval = tls_get(globalkey); 00644 00645 if (globalval != NULL) 00646 xmlFreeGlobalState(globalval); 00647 } 00648 #endif 00649 00657 xmlGlobalStatePtr 00658 xmlGetGlobalState(void) 00659 { 00660 #ifdef HAVE_PTHREAD_H 00661 xmlGlobalState *globalval; 00662 00663 if (libxml_is_threaded == 0) 00664 return (NULL); 00665 00666 pthread_once(&once_control, xmlOnceInit); 00667 00668 if ((globalval = (xmlGlobalState *) 00669 pthread_getspecific(globalkey)) == NULL) { 00670 xmlGlobalState *tsd = xmlNewGlobalState(); 00671 if (tsd == NULL) 00672 return(NULL); 00673 00674 pthread_setspecific(globalkey, tsd); 00675 return (tsd); 00676 } 00677 return (globalval); 00678 #elif defined HAVE_WIN32_THREADS 00679 #if defined(HAVE_COMPILER_TLS) 00680 if (!tlstate_inited) { 00681 tlstate_inited = 1; 00682 xmlInitializeGlobalState(&tlstate); 00683 } 00684 return &tlstate; 00685 #else /* HAVE_COMPILER_TLS */ 00686 xmlGlobalState *globalval; 00687 xmlGlobalStateCleanupHelperParams *p; 00688 00689 xmlOnceInit(); 00690 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) 00691 globalval = (xmlGlobalState *) TlsGetValue(globalkey); 00692 #else 00693 p = (xmlGlobalStateCleanupHelperParams *) TlsGetValue(globalkey); 00694 globalval = (xmlGlobalState *) (p ? p->memory : NULL); 00695 #endif 00696 if (globalval == NULL) { 00697 xmlGlobalState *tsd = xmlNewGlobalState(); 00698 00699 if (tsd == NULL) 00700 return(NULL); 00701 p = (xmlGlobalStateCleanupHelperParams *) 00702 malloc(sizeof(xmlGlobalStateCleanupHelperParams)); 00703 if (p == NULL) { 00704 xmlGenericError(xmlGenericErrorContext, 00705 "xmlGetGlobalState: out of memory\n"); 00706 xmlFreeGlobalState(tsd); 00707 return(NULL); 00708 } 00709 p->memory = tsd; 00710 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) 00711 DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), 00712 GetCurrentProcess(), &p->thread, 0, TRUE, 00713 DUPLICATE_SAME_ACCESS); 00714 TlsSetValue(globalkey, tsd); 00715 _beginthread(xmlGlobalStateCleanupHelper, 0, p); 00716 #else 00717 EnterCriticalSection(&cleanup_helpers_cs); 00718 if (cleanup_helpers_head != NULL) { 00719 cleanup_helpers_head->prev = p; 00720 } 00721 p->next = cleanup_helpers_head; 00722 p->prev = NULL; 00723 cleanup_helpers_head = p; 00724 TlsSetValue(globalkey, p); 00725 LeaveCriticalSection(&cleanup_helpers_cs); 00726 #endif 00727 00728 return (tsd); 00729 } 00730 return (globalval); 00731 #endif /* HAVE_COMPILER_TLS */ 00732 #elif defined HAVE_BEOS_THREADS 00733 xmlGlobalState *globalval; 00734 00735 xmlOnceInit(); 00736 00737 if ((globalval = (xmlGlobalState *) tls_get(globalkey)) == NULL) { 00738 xmlGlobalState *tsd = xmlNewGlobalState(); 00739 if (tsd == NULL) 00740 return (NULL); 00741 00742 tls_set(globalkey, tsd); 00743 on_exit_thread(xmlGlobalStateCleanup, NULL); 00744 return (tsd); 00745 } 00746 return (globalval); 00747 #else 00748 return (NULL); 00749 #endif 00750 } 00751 00752 /************************************************************************ 00753 * * 00754 * Library wide thread interfaces * 00755 * * 00756 ************************************************************************/ 00757 00767 int 00768 xmlGetThreadId(void) 00769 { 00770 #ifdef HAVE_PTHREAD_H 00771 pthread_t id; 00772 int ret; 00773 00774 if (libxml_is_threaded == 0) 00775 return (0); 00776 id = pthread_self(); 00777 /* horrible but preserves compat, see warning above */ 00778 memcpy(&ret, &id, sizeof(ret)); 00779 return (ret); 00780 #elif defined HAVE_WIN32_THREADS 00781 return GetCurrentThreadId(); 00782 #elif defined HAVE_BEOS_THREADS 00783 return find_thread(NULL); 00784 #else 00785 return ((int) 0); 00786 #endif 00787 } 00788 00796 int 00797 xmlIsMainThread(void) 00798 { 00799 #ifdef HAVE_PTHREAD_H 00800 if (libxml_is_threaded == -1) 00801 xmlInitThreads(); 00802 if (libxml_is_threaded == 0) 00803 return (1); 00804 pthread_once(&once_control, xmlOnceInit); 00805 #elif defined HAVE_WIN32_THREADS 00806 xmlOnceInit(); 00807 #elif defined HAVE_BEOS_THREADS 00808 xmlOnceInit(); 00809 #endif 00810 00811 #ifdef DEBUG_THREADS 00812 xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n"); 00813 #endif 00814 #ifdef HAVE_PTHREAD_H 00815 return (pthread_equal(mainthread,pthread_self())); 00816 #elif defined HAVE_WIN32_THREADS 00817 return (mainthread == GetCurrentThreadId()); 00818 #elif defined HAVE_BEOS_THREADS 00819 return (mainthread == find_thread(NULL)); 00820 #else 00821 return (1); 00822 #endif 00823 } 00824 00831 void 00832 xmlLockLibrary(void) 00833 { 00834 #ifdef DEBUG_THREADS 00835 xmlGenericError(xmlGenericErrorContext, "xmlLockLibrary()\n"); 00836 #endif 00837 xmlRMutexLock(xmlLibraryLock); 00838 } 00839 00846 void 00847 xmlUnlockLibrary(void) 00848 { 00849 #ifdef DEBUG_THREADS 00850 xmlGenericError(xmlGenericErrorContext, "xmlUnlockLibrary()\n"); 00851 #endif 00852 xmlRMutexUnlock(xmlLibraryLock); 00853 } 00854 00861 void 00862 xmlInitThreads(void) 00863 { 00864 #ifdef HAVE_PTHREAD_H 00865 if (libxml_is_threaded == -1) { 00866 if ((pthread_once != NULL) && 00867 (pthread_getspecific != NULL) && 00868 (pthread_setspecific != NULL) && 00869 (pthread_key_create != NULL) && 00870 (pthread_key_delete != NULL) && 00871 (pthread_mutex_init != NULL) && 00872 (pthread_mutex_destroy != NULL) && 00873 (pthread_mutex_lock != NULL) && 00874 (pthread_mutex_unlock != NULL) && 00875 (pthread_cond_init != NULL) && 00876 (pthread_cond_destroy != NULL) && 00877 (pthread_cond_wait != NULL) && 00878 (pthread_equal != NULL) && 00879 (pthread_self != NULL) && 00880 (pthread_cond_signal != NULL)) { 00881 libxml_is_threaded = 1; 00882 00883 /* fprintf(stderr, "Running multithreaded\n"); */ 00884 } else { 00885 00886 /* fprintf(stderr, "Running without multithread\n"); */ 00887 libxml_is_threaded = 0; 00888 } 00889 } 00890 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) 00891 InitializeCriticalSection(&cleanup_helpers_cs); 00892 #endif 00893 } 00894 00909 void 00910 xmlCleanupThreads(void) 00911 { 00912 #ifdef DEBUG_THREADS 00913 xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n"); 00914 #endif 00915 #ifdef HAVE_PTHREAD_H 00916 if ((libxml_is_threaded) && (pthread_key_delete != NULL)) 00917 pthread_key_delete(globalkey); 00918 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) 00919 if (globalkey != TLS_OUT_OF_INDEXES) { 00920 xmlGlobalStateCleanupHelperParams *p; 00921 00922 EnterCriticalSection(&cleanup_helpers_cs); 00923 p = cleanup_helpers_head; 00924 while (p != NULL) { 00925 xmlGlobalStateCleanupHelperParams *temp = p; 00926 00927 p = p->next; 00928 xmlFreeGlobalState(temp->memory); 00929 free(temp); 00930 } 00931 cleanup_helpers_head = 0; 00932 LeaveCriticalSection(&cleanup_helpers_cs); 00933 TlsFree(globalkey); 00934 globalkey = TLS_OUT_OF_INDEXES; 00935 } 00936 DeleteCriticalSection(&cleanup_helpers_cs); 00937 #endif 00938 } 00939 00940 #ifdef LIBXML_THREAD_ENABLED 00941 00951 static void 00952 xmlOnceInit(void) 00953 { 00954 #ifdef HAVE_PTHREAD_H 00955 (void) pthread_key_create(&globalkey, xmlFreeGlobalState); 00956 mainthread = pthread_self(); 00957 #elif defined(HAVE_WIN32_THREADS) 00958 if (!run_once.done) { 00959 if (InterlockedIncrement(&run_once.control) == 1) { 00960 #if !defined(HAVE_COMPILER_TLS) 00961 globalkey = TlsAlloc(); 00962 #endif 00963 mainthread = GetCurrentThreadId(); 00964 run_once.done = 1; 00965 } else { 00966 /* Another thread is working; give up our slice and 00967 * wait until they're done. */ 00968 while (!run_once.done) 00969 Sleep(0); 00970 } 00971 } 00972 #elif defined HAVE_BEOS_THREADS 00973 if (atomic_add(&run_once_init, 1) == 0) { 00974 globalkey = tls_allocate(); 00975 tls_set(globalkey, NULL); 00976 mainthread = find_thread(NULL); 00977 } else 00978 atomic_add(&run_once_init, -1); 00979 #endif 00980 } 00981 #endif 00982 00994 #ifdef HAVE_PTHREAD_H 00995 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) 00996 #if defined(LIBXML_STATIC_FOR_DLL) 00997 BOOL XMLCALL 00998 xmlDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 00999 #else 01000 BOOL WINAPI 01001 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 01002 #endif 01003 { 01004 switch (fdwReason) { 01005 case DLL_THREAD_DETACH: 01006 if (globalkey != TLS_OUT_OF_INDEXES) { 01007 xmlGlobalState *globalval = NULL; 01008 xmlGlobalStateCleanupHelperParams *p = 01009 (xmlGlobalStateCleanupHelperParams *) 01010 TlsGetValue(globalkey); 01011 globalval = (xmlGlobalState *) (p ? p->memory : NULL); 01012 if (globalval) { 01013 xmlFreeGlobalState(globalval); 01014 TlsSetValue(globalkey, NULL); 01015 } 01016 if (p) { 01017 EnterCriticalSection(&cleanup_helpers_cs); 01018 if (p == cleanup_helpers_head) 01019 cleanup_helpers_head = p->next; 01020 else 01021 p->prev->next = p->next; 01022 if (p->next != NULL) 01023 p->next->prev = p->prev; 01024 LeaveCriticalSection(&cleanup_helpers_cs); 01025 free(p); 01026 } 01027 } 01028 break; 01029 } 01030 return TRUE; 01031 } 01032 #endif 01033 #define bottom_threads 01034 #include "elfgcchack.h" Generated on Sat May 26 2012 04:33:33 for ReactOS by
1.7.6.1
|