📄 threads.c
字号:
delete_sem(sem); /* Acquire the chosen semaphore */ if (acquire_sem(global_init_lock) != B_NO_ERROR) {#ifdef DEBUG_THREADS xmlGenericError(xmlGenericErrorContext, "xmlGlobalInitMutexLock():BeOS:Couldn't acquire semaphore\n"); exit();#endif }#endif}void__xmlGlobalInitMutexUnlock(void){#ifdef HAVE_PTHREAD_H pthread_mutex_unlock(&global_init_lock);#elif defined HAVE_WIN32_THREADS LeaveCriticalSection(global_init_lock);#elif defined HAVE_BEOS_THREADS release_sem(global_init_lock);#endif}/************************************************************************ * * * Per thread global state handling * * * ************************************************************************/#ifdef LIBXML_THREAD_ENABLED#ifdef xmlLastError#undef xmlLastError#endif/** * xmlFreeGlobalState: * @state: a thread global state * * xmlFreeGlobalState() is called when a thread terminates with a non-NULL * global state. It is is used here to reclaim memory resources. */static voidxmlFreeGlobalState(void *state){ xmlGlobalState *gs = (xmlGlobalState *) state; /* free any memory allocated in the thread's xmlLastError */ xmlResetError(&(gs->xmlLastError)); free(state);}/** * xmlNewGlobalState: * * xmlNewGlobalState() allocates a global state. This structure is used to * hold all data for use by a thread when supporting backwards compatibility * of libxml2 to pre-thread-safe behaviour. * * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error */static xmlGlobalStatePtrxmlNewGlobalState(void){ xmlGlobalState *gs; gs = malloc(sizeof(xmlGlobalState)); if (gs == NULL) return(NULL); memset(gs, 0, sizeof(xmlGlobalState)); xmlInitializeGlobalState(gs); return (gs);}#endif /* LIBXML_THREAD_ENABLED */#ifdef HAVE_WIN32_THREADS#if !defined(HAVE_COMPILER_TLS)#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)typedef struct _xmlGlobalStateCleanupHelperParams{ HANDLE thread; void *memory;} xmlGlobalStateCleanupHelperParams;static void XMLCDECL xmlGlobalStateCleanupHelper (void *p){ xmlGlobalStateCleanupHelperParams *params = (xmlGlobalStateCleanupHelperParams *) p; WaitForSingleObject(params->thread, INFINITE); CloseHandle(params->thread); xmlFreeGlobalState(params->memory); free(params); _endthread();}#else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */typedef struct _xmlGlobalStateCleanupHelperParams{ void *memory; struct _xmlGlobalStateCleanupHelperParams * prev; struct _xmlGlobalStateCleanupHelperParams * next;} xmlGlobalStateCleanupHelperParams;static xmlGlobalStateCleanupHelperParams * cleanup_helpers_head = NULL;static CRITICAL_SECTION cleanup_helpers_cs;#endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */#endif /* HAVE_COMPILER_TLS */#endif /* HAVE_WIN32_THREADS */#if defined HAVE_BEOS_THREADS/** * xmlGlobalStateCleanup: * @data: unused parameter * * Used for Beos only */void xmlGlobalStateCleanup(void *data){ void *globalval = tls_get(globalkey); if (globalval != NULL) xmlFreeGlobalState(globalval);}#endif/** * xmlGetGlobalState: * * xmlGetGlobalState() is called to retrieve the global state for a thread. * * Returns the thread global state or NULL in case of error */xmlGlobalStatePtrxmlGetGlobalState(void){#ifdef HAVE_PTHREAD_H xmlGlobalState *globalval; if (libxml_is_threaded == 0) return(NULL); pthread_once(&once_control, xmlOnceInit); if ((globalval = (xmlGlobalState *) pthread_getspecific(globalkey)) == NULL) { xmlGlobalState *tsd = xmlNewGlobalState(); pthread_setspecific(globalkey, tsd); return (tsd); } return (globalval);#elif defined HAVE_WIN32_THREADS#if defined(HAVE_COMPILER_TLS) if (!tlstate_inited) { tlstate_inited = 1; xmlInitializeGlobalState(&tlstate); } return &tlstate;#else /* HAVE_COMPILER_TLS */ xmlGlobalState *globalval; xmlGlobalStateCleanupHelperParams * p; xmlOnceInit();#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) globalval = (xmlGlobalState *)TlsGetValue(globalkey);#else p = (xmlGlobalStateCleanupHelperParams*)TlsGetValue(globalkey); globalval = (xmlGlobalState *)(p ? p->memory : NULL);#endif if (globalval == NULL) { xmlGlobalState *tsd = xmlNewGlobalState(); p = (xmlGlobalStateCleanupHelperParams *) malloc(sizeof(xmlGlobalStateCleanupHelperParams)); p->memory = tsd;#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL) DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &p->thread, 0, TRUE, DUPLICATE_SAME_ACCESS); TlsSetValue(globalkey, tsd); _beginthread(xmlGlobalStateCleanupHelper, 0, p);#else EnterCriticalSection(&cleanup_helpers_cs); if (cleanup_helpers_head != NULL) { cleanup_helpers_head->prev = p; } p->next = cleanup_helpers_head; p->prev = NULL; cleanup_helpers_head = p; TlsSetValue(globalkey, p); LeaveCriticalSection(&cleanup_helpers_cs); #endif return (tsd); } return (globalval);#endif /* HAVE_COMPILER_TLS */#elif defined HAVE_BEOS_THREADS xmlGlobalState *globalval; xmlOnceInit(); if ((globalval = (xmlGlobalState *) tls_get(globalkey)) == NULL) { xmlGlobalState *tsd = xmlNewGlobalState(); tls_set(globalkey, tsd); on_exit_thread(xmlGlobalStateCleanup, NULL); return (tsd); } return (globalval);#else return(NULL);#endif}/************************************************************************ * * * Library wide thread interfaces * * * ************************************************************************//** * xmlGetThreadId: * * xmlGetThreadId() find the current thread ID number * * Returns the current thread ID number */intxmlGetThreadId(void){#ifdef HAVE_PTHREAD_H if (libxml_is_threaded == 0) return(0); return((int) pthread_self());#elif defined HAVE_WIN32_THREADS return GetCurrentThreadId();#elif defined HAVE_BEOS_THREADS return find_thread(NULL);#else return((int) 0);#endif}/** * xmlIsMainThread: * * xmlIsMainThread() check whether the current thread is the main thread. * * Returns 1 if the current thread is the main thread, 0 otherwise */intxmlIsMainThread(void){#ifdef HAVE_PTHREAD_H if (libxml_is_threaded == -1) xmlInitThreads(); if (libxml_is_threaded == 0) return(1); pthread_once(&once_control, xmlOnceInit);#elif defined HAVE_WIN32_THREADS xmlOnceInit (); #elif defined HAVE_BEOS_THREADS xmlOnceInit();#endif #ifdef DEBUG_THREADS xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n");#endif#ifdef HAVE_PTHREAD_H return(mainthread == pthread_self());#elif defined HAVE_WIN32_THREADS return(mainthread == GetCurrentThreadId ());#elif defined HAVE_BEOS_THREADS return(mainthread == find_thread(NULL));#else return(1);#endif}/** * xmlLockLibrary: * * xmlLockLibrary() is used to take out a re-entrant lock on the libxml2 * library. */voidxmlLockLibrary(void){#ifdef DEBUG_THREADS xmlGenericError(xmlGenericErrorContext, "xmlLockLibrary()\n");#endif xmlRMutexLock(xmlLibraryLock);}/** * xmlUnlockLibrary: * * xmlUnlockLibrary() is used to release a re-entrant lock on the libxml2 * library. */voidxmlUnlockLibrary(void){#ifdef DEBUG_THREADS xmlGenericError(xmlGenericErrorContext, "xmlUnlockLibrary()\n");#endif xmlRMutexUnlock(xmlLibraryLock);}/** * xmlInitThreads: * * xmlInitThreads() is used to to initialize all the thread related * data of the libxml2 library. */voidxmlInitThreads(void){#ifdef DEBUG_THREADS xmlGenericError(xmlGenericErrorContext, "xmlInitThreads()\n");#endif#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) InitializeCriticalSection(&cleanup_helpers_cs);#endif#ifdef HAVE_PTHREAD_H if (libxml_is_threaded == -1) { if ((pthread_once != NULL) && (pthread_getspecific != NULL) && (pthread_setspecific != NULL) && (pthread_key_create != NULL) && (pthread_mutex_init != NULL) && (pthread_mutex_destroy != NULL) && (pthread_mutex_lock != NULL) && (pthread_mutex_unlock != NULL) && (pthread_cond_init != NULL) && (pthread_equal != NULL) && (pthread_self != NULL) && (pthread_key_create != NULL) && (pthread_cond_signal != NULL)) { libxml_is_threaded = 1;/* fprintf(stderr, "Running multithreaded\n"); */ } else {/* fprintf(stderr, "Running without multithread\n"); */ libxml_is_threaded = 0; } }#endif}/** * xmlCleanupThreads: * * xmlCleanupThreads() is used to to cleanup all the thread related * data of the libxml2 library once processing has ended. */voidxmlCleanupThreads(void){#ifdef DEBUG_THREADS xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n");#endif#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) if (globalkey != TLS_OUT_OF_INDEXES) { xmlGlobalStateCleanupHelperParams * p; EnterCriticalSection(&cleanup_helpers_cs); p = cleanup_helpers_head; while (p != NULL) { xmlGlobalStateCleanupHelperParams * temp = p; p = p->next; xmlFreeGlobalState(temp->memory); free(temp); } cleanup_helpers_head = 0; LeaveCriticalSection(&cleanup_helpers_cs); TlsFree(globalkey); globalkey = TLS_OUT_OF_INDEXES; } DeleteCriticalSection(&cleanup_helpers_cs);#endif}#ifdef LIBXML_THREAD_ENABLED/** * xmlOnceInit * * xmlOnceInit() is used to initialize the value of mainthread for use * in other routines. This function should only be called using * pthread_once() in association with the once_control variable to ensure * that the function is only called once. See man pthread_once for more * details. */static voidxmlOnceInit(void) {#ifdef HAVE_PTHREAD_H (void) pthread_key_create(&globalkey, xmlFreeGlobalState); mainthread = pthread_self();#endif#if defined(HAVE_WIN32_THREADS) if (!run_once.done) { if (InterlockedIncrement(&run_once.control) == 1) {#if !defined(HAVE_COMPILER_TLS) globalkey = TlsAlloc();#endif mainthread = GetCurrentThreadId(); run_once.done = 1; } else { /* Another thread is working; give up our slice and * wait until they're done. */ while (!run_once.done) Sleep(0); } }#endif#ifdef HAVE_BEOS_THREADS if (atomic_add(&run_once_init, 1) == 0) { globalkey = tls_allocate(); tls_set(globalkey, NULL); mainthread = find_thread(NULL); } else atomic_add(&run_once_init, -1);#endif}#endif/** * DllMain: * @hinstDLL: handle to DLL instance * @fdwReason: Reason code for entry * @lpvReserved: generic pointer (depends upon reason code) * * Entry point for Windows library. It is being used to free thread-specific * storage. * * Returns TRUE always */#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))#if defined(LIBXML_STATIC_FOR_DLL)BOOL XMLCALL xmlDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) #elseBOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) #endif{ switch(fdwReason) { case DLL_THREAD_DETACH: if (globalkey != TLS_OUT_OF_INDEXES) { xmlGlobalState *globalval = NULL; xmlGlobalStateCleanupHelperParams * p = (xmlGlobalStateCleanupHelperParams*)TlsGetValue(globalkey); globalval = (xmlGlobalState *)(p ? p->memory : NULL); if (globalval) { xmlFreeGlobalState(globalval); TlsSetValue(globalkey,NULL); } if (p) { EnterCriticalSection(&cleanup_helpers_cs); if (p == cleanup_helpers_head) cleanup_helpers_head = p->next; else p->prev->next = p->next; if (p->next != NULL) p->next->prev = p->prev; LeaveCriticalSection(&cleanup_helpers_cs); free(p); } } break; } return TRUE;}#endif#define bottom_threads#include "elfgcchack.h"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -