diff options
author | wawaka <wawaka@yandex-team.ru> | 2022-02-10 16:47:48 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:47:48 +0300 |
commit | ed524783c88c81047033c5d6e5543db3a2251ad5 (patch) | |
tree | 5c595c0ac1b14fbb70e7e71df44b52e47f850387 /contrib/libs/libxml/threads.c | |
parent | 11ec0273ab97c87692cd0004865c7f24d14f9902 (diff) | |
download | ydb-ed524783c88c81047033c5d6e5543db3a2251ad5.tar.gz |
Restoring authorship annotation for <wawaka@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/libxml/threads.c')
-rw-r--r-- | contrib/libs/libxml/threads.c | 1964 |
1 files changed, 982 insertions, 982 deletions
diff --git a/contrib/libs/libxml/threads.c b/contrib/libs/libxml/threads.c index 72df9ba997..a46f0bbc38 100644 --- a/contrib/libs/libxml/threads.c +++ b/contrib/libs/libxml/threads.c @@ -1,56 +1,56 @@ -/** - * threads.c: set of generic threading related routines - * - * See Copyright for the status of this software. - * - * Gary Pennington <Gary.Pennington@uk.sun.com> - * daniel@veillard.com - */ - -#define IN_LIBXML -#include "libxml.h" - -#include <string.h> - -#include <libxml/threads.h> -#include <libxml/globals.h> - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_PTHREAD_H -#include <pthread.h> -#elif defined HAVE_WIN32_THREADS +/** + * threads.c: set of generic threading related routines + * + * See Copyright for the status of this software. + * + * Gary Pennington <Gary.Pennington@uk.sun.com> + * daniel@veillard.com + */ + +#define IN_LIBXML +#include "libxml.h" + +#include <string.h> + +#include <libxml/threads.h> +#include <libxml/globals.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_PTHREAD_H +#include <pthread.h> +#elif defined HAVE_WIN32_THREADS #define WIN32_LEAN_AND_MEAN -#include <windows.h> -#ifndef HAVE_COMPILER_TLS -#include <process.h> -#endif -#endif - -#ifdef HAVE_BEOS_THREADS -#include <OS.h> -#include <TLS.h> -#endif - -#if defined(SOLARIS) -#include <note.h> -#endif - -/* #define DEBUG_THREADS */ - -#ifdef HAVE_PTHREAD_H - +#include <windows.h> +#ifndef HAVE_COMPILER_TLS +#include <process.h> +#endif +#endif + +#ifdef HAVE_BEOS_THREADS +#include <OS.h> +#include <TLS.h> +#endif + +#if defined(SOLARIS) +#include <note.h> +#endif + +/* #define DEBUG_THREADS */ + +#ifdef HAVE_PTHREAD_H + #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 303) && \ defined(__GLIBC__) && defined(__linux__) -static int libxml_is_threaded = -1; +static int libxml_is_threaded = -1; #define XML_PTHREAD_WEAK @@ -78,928 +78,928 @@ static int libxml_is_threaded = 1; #endif /* __GNUC__, __GLIBC__, __linux__ */ -#endif /* HAVE_PTHREAD_H */ - -/* - * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree +#endif /* HAVE_PTHREAD_H */ + +/* + * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree * to avoid some craziness since xmlMalloc/xmlFree may actually - * be hosted on allocated blocks needing them for the allocation ... - */ - -/* - * xmlMutex are a simple mutual exception locks - */ -struct _xmlMutex { -#ifdef HAVE_PTHREAD_H - pthread_mutex_t lock; -#elif defined HAVE_WIN32_THREADS - HANDLE mutex; -#elif defined HAVE_BEOS_THREADS - sem_id sem; - thread_id tid; -#else - int empty; -#endif -}; - -/* - * xmlRMutex are reentrant mutual exception locks - */ -struct _xmlRMutex { -#ifdef HAVE_PTHREAD_H - pthread_mutex_t lock; - unsigned int held; - unsigned int waiters; - pthread_t tid; - pthread_cond_t cv; -#elif defined HAVE_WIN32_THREADS - CRITICAL_SECTION cs; - unsigned int count; -#elif defined HAVE_BEOS_THREADS - xmlMutexPtr lock; - thread_id tid; - int32 count; -#else - int empty; -#endif -}; - -/* - * This module still has some internal static data. - * - xmlLibraryLock a global lock - * - globalkey used for per-thread data - */ - -#ifdef HAVE_PTHREAD_H -static pthread_key_t globalkey; -static pthread_t mainthread; -static pthread_once_t once_control = PTHREAD_ONCE_INIT; -static pthread_once_t once_control_init = PTHREAD_ONCE_INIT; -static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER; -#elif defined HAVE_WIN32_THREADS -#if defined(HAVE_COMPILER_TLS) -static __declspec(thread) xmlGlobalState tlstate; -static __declspec(thread) int tlstate_inited = 0; -#else /* HAVE_COMPILER_TLS */ -static DWORD globalkey = TLS_OUT_OF_INDEXES; -#endif /* HAVE_COMPILER_TLS */ -static DWORD mainthread; -static struct { - DWORD done; + * be hosted on allocated blocks needing them for the allocation ... + */ + +/* + * xmlMutex are a simple mutual exception locks + */ +struct _xmlMutex { +#ifdef HAVE_PTHREAD_H + pthread_mutex_t lock; +#elif defined HAVE_WIN32_THREADS + HANDLE mutex; +#elif defined HAVE_BEOS_THREADS + sem_id sem; + thread_id tid; +#else + int empty; +#endif +}; + +/* + * xmlRMutex are reentrant mutual exception locks + */ +struct _xmlRMutex { +#ifdef HAVE_PTHREAD_H + pthread_mutex_t lock; + unsigned int held; + unsigned int waiters; + pthread_t tid; + pthread_cond_t cv; +#elif defined HAVE_WIN32_THREADS + CRITICAL_SECTION cs; + unsigned int count; +#elif defined HAVE_BEOS_THREADS + xmlMutexPtr lock; + thread_id tid; + int32 count; +#else + int empty; +#endif +}; + +/* + * This module still has some internal static data. + * - xmlLibraryLock a global lock + * - globalkey used for per-thread data + */ + +#ifdef HAVE_PTHREAD_H +static pthread_key_t globalkey; +static pthread_t mainthread; +static pthread_once_t once_control = PTHREAD_ONCE_INIT; +static pthread_once_t once_control_init = PTHREAD_ONCE_INIT; +static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER; +#elif defined HAVE_WIN32_THREADS +#if defined(HAVE_COMPILER_TLS) +static __declspec(thread) xmlGlobalState tlstate; +static __declspec(thread) int tlstate_inited = 0; +#else /* HAVE_COMPILER_TLS */ +static DWORD globalkey = TLS_OUT_OF_INDEXES; +#endif /* HAVE_COMPILER_TLS */ +static DWORD mainthread; +static struct { + DWORD done; LONG control; -} run_once = { 0, 0}; -static volatile LPCRITICAL_SECTION global_init_lock = NULL; - -/* endif HAVE_WIN32_THREADS */ -#elif defined HAVE_BEOS_THREADS -int32 globalkey = 0; -thread_id mainthread = 0; -int32 run_once_init = 0; -static int32 global_init_lock = -1; -static vint32 global_init_count = 0; -#endif - -static xmlRMutexPtr xmlLibraryLock = NULL; - -#ifdef LIBXML_THREAD_ENABLED -static void xmlOnceInit(void); -#endif - -/** - * xmlNewMutex: - * - * xmlNewMutex() is used to allocate a libxml2 token struct for use in - * synchronizing access to data. - * - * Returns a new simple mutex pointer or NULL in case of error - */ -xmlMutexPtr -xmlNewMutex(void) -{ - xmlMutexPtr tok; - - if ((tok = malloc(sizeof(xmlMutex))) == NULL) - return (NULL); -#ifdef HAVE_PTHREAD_H - if (libxml_is_threaded != 0) - pthread_mutex_init(&tok->lock, NULL); -#elif defined HAVE_WIN32_THREADS - tok->mutex = CreateMutex(NULL, FALSE, NULL); -#elif defined HAVE_BEOS_THREADS - if ((tok->sem = create_sem(1, "xmlMutex")) < B_OK) { - free(tok); - return NULL; - } - tok->tid = -1; -#endif - return (tok); -} - -/** - * xmlFreeMutex: - * @tok: the simple mutex - * - * xmlFreeMutex() is used to reclaim resources associated with a libxml2 token - * struct. - */ -void -xmlFreeMutex(xmlMutexPtr tok) -{ - if (tok == NULL) - return; - -#ifdef HAVE_PTHREAD_H - if (libxml_is_threaded != 0) - pthread_mutex_destroy(&tok->lock); -#elif defined HAVE_WIN32_THREADS - CloseHandle(tok->mutex); -#elif defined HAVE_BEOS_THREADS - delete_sem(tok->sem); -#endif - free(tok); -} - -/** - * xmlMutexLock: - * @tok: the simple mutex - * - * xmlMutexLock() is used to lock a libxml2 token. - */ -void -xmlMutexLock(xmlMutexPtr tok) -{ - if (tok == NULL) - return; -#ifdef HAVE_PTHREAD_H - if (libxml_is_threaded != 0) - pthread_mutex_lock(&tok->lock); -#elif defined HAVE_WIN32_THREADS - WaitForSingleObject(tok->mutex, INFINITE); -#elif defined HAVE_BEOS_THREADS - if (acquire_sem(tok->sem) != B_NO_ERROR) { -#ifdef DEBUG_THREADS - xmlGenericError(xmlGenericErrorContext, +} run_once = { 0, 0}; +static volatile LPCRITICAL_SECTION global_init_lock = NULL; + +/* endif HAVE_WIN32_THREADS */ +#elif defined HAVE_BEOS_THREADS +int32 globalkey = 0; +thread_id mainthread = 0; +int32 run_once_init = 0; +static int32 global_init_lock = -1; +static vint32 global_init_count = 0; +#endif + +static xmlRMutexPtr xmlLibraryLock = NULL; + +#ifdef LIBXML_THREAD_ENABLED +static void xmlOnceInit(void); +#endif + +/** + * xmlNewMutex: + * + * xmlNewMutex() is used to allocate a libxml2 token struct for use in + * synchronizing access to data. + * + * Returns a new simple mutex pointer or NULL in case of error + */ +xmlMutexPtr +xmlNewMutex(void) +{ + xmlMutexPtr tok; + + if ((tok = malloc(sizeof(xmlMutex))) == NULL) + return (NULL); +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) + pthread_mutex_init(&tok->lock, NULL); +#elif defined HAVE_WIN32_THREADS + tok->mutex = CreateMutex(NULL, FALSE, NULL); +#elif defined HAVE_BEOS_THREADS + if ((tok->sem = create_sem(1, "xmlMutex")) < B_OK) { + free(tok); + return NULL; + } + tok->tid = -1; +#endif + return (tok); +} + +/** + * xmlFreeMutex: + * @tok: the simple mutex + * + * xmlFreeMutex() is used to reclaim resources associated with a libxml2 token + * struct. + */ +void +xmlFreeMutex(xmlMutexPtr tok) +{ + if (tok == NULL) + return; + +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) + pthread_mutex_destroy(&tok->lock); +#elif defined HAVE_WIN32_THREADS + CloseHandle(tok->mutex); +#elif defined HAVE_BEOS_THREADS + delete_sem(tok->sem); +#endif + free(tok); +} + +/** + * xmlMutexLock: + * @tok: the simple mutex + * + * xmlMutexLock() is used to lock a libxml2 token. + */ +void +xmlMutexLock(xmlMutexPtr tok) +{ + if (tok == NULL) + return; +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) + pthread_mutex_lock(&tok->lock); +#elif defined HAVE_WIN32_THREADS + WaitForSingleObject(tok->mutex, INFINITE); +#elif defined HAVE_BEOS_THREADS + if (acquire_sem(tok->sem) != B_NO_ERROR) { +#ifdef DEBUG_THREADS + xmlGenericError(xmlGenericErrorContext, "xmlMutexLock():BeOS:Couldn't acquire semaphore\n"); -#endif - } - tok->tid = find_thread(NULL); -#endif - -} - -/** - * xmlMutexUnlock: - * @tok: the simple mutex - * - * xmlMutexUnlock() is used to unlock a libxml2 token. - */ -void -xmlMutexUnlock(xmlMutexPtr tok) -{ - if (tok == NULL) - return; -#ifdef HAVE_PTHREAD_H - if (libxml_is_threaded != 0) - pthread_mutex_unlock(&tok->lock); -#elif defined HAVE_WIN32_THREADS - ReleaseMutex(tok->mutex); -#elif defined HAVE_BEOS_THREADS - if (tok->tid == find_thread(NULL)) { - tok->tid = -1; - release_sem(tok->sem); - } -#endif -} - -/** - * xmlNewRMutex: - * - * xmlRNewMutex() is used to allocate a reentrant mutex for use in - * synchronizing access to data. token_r is a re-entrant lock and thus useful - * for synchronizing access to data structures that may be manipulated in a - * recursive fashion. - * - * Returns the new reentrant mutex pointer or NULL in case of error - */ -xmlRMutexPtr -xmlNewRMutex(void) -{ - xmlRMutexPtr tok; - - if ((tok = malloc(sizeof(xmlRMutex))) == NULL) - return (NULL); -#ifdef HAVE_PTHREAD_H - if (libxml_is_threaded != 0) { - pthread_mutex_init(&tok->lock, NULL); - tok->held = 0; - tok->waiters = 0; - pthread_cond_init(&tok->cv, NULL); - } -#elif defined HAVE_WIN32_THREADS - InitializeCriticalSection(&tok->cs); - tok->count = 0; -#elif defined HAVE_BEOS_THREADS - if ((tok->lock = xmlNewMutex()) == NULL) { - free(tok); - return NULL; - } - tok->count = 0; -#endif - return (tok); -} - -/** - * xmlFreeRMutex: - * @tok: the reentrant mutex - * - * xmlRFreeMutex() is used to reclaim resources associated with a - * reentrant mutex. - */ -void -xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED) -{ - if (tok == NULL) - return; -#ifdef HAVE_PTHREAD_H - if (libxml_is_threaded != 0) { - pthread_mutex_destroy(&tok->lock); - pthread_cond_destroy(&tok->cv); - } -#elif defined HAVE_WIN32_THREADS - DeleteCriticalSection(&tok->cs); -#elif defined HAVE_BEOS_THREADS - xmlFreeMutex(tok->lock); -#endif - free(tok); -} - -/** - * xmlRMutexLock: - * @tok: the reentrant mutex - * - * xmlRMutexLock() is used to lock a libxml2 token_r. - */ -void -xmlRMutexLock(xmlRMutexPtr tok) -{ - if (tok == NULL) - return; -#ifdef HAVE_PTHREAD_H - if (libxml_is_threaded == 0) - return; - - pthread_mutex_lock(&tok->lock); - if (tok->held) { - if (pthread_equal(tok->tid, pthread_self())) { - tok->held++; - pthread_mutex_unlock(&tok->lock); - return; - } else { - tok->waiters++; - while (tok->held) - pthread_cond_wait(&tok->cv, &tok->lock); - tok->waiters--; - } - } - tok->tid = pthread_self(); - tok->held = 1; - pthread_mutex_unlock(&tok->lock); -#elif defined HAVE_WIN32_THREADS - EnterCriticalSection(&tok->cs); - tok->count++; -#elif defined HAVE_BEOS_THREADS - if (tok->lock->tid == find_thread(NULL)) { - tok->count++; - return; - } else { - xmlMutexLock(tok->lock); - tok->count = 1; - } -#endif -} - -/** - * xmlRMutexUnlock: - * @tok: the reentrant mutex - * - * xmlRMutexUnlock() is used to unlock a libxml2 token_r. - */ -void -xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED) -{ - if (tok == NULL) - return; -#ifdef HAVE_PTHREAD_H - if (libxml_is_threaded == 0) - return; - - pthread_mutex_lock(&tok->lock); - tok->held--; - if (tok->held == 0) { - if (tok->waiters) - pthread_cond_signal(&tok->cv); - memset(&tok->tid, 0, sizeof(tok->tid)); - } - pthread_mutex_unlock(&tok->lock); -#elif defined HAVE_WIN32_THREADS - if (tok->count > 0) { +#endif + } + tok->tid = find_thread(NULL); +#endif + +} + +/** + * xmlMutexUnlock: + * @tok: the simple mutex + * + * xmlMutexUnlock() is used to unlock a libxml2 token. + */ +void +xmlMutexUnlock(xmlMutexPtr tok) +{ + if (tok == NULL) + return; +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) + pthread_mutex_unlock(&tok->lock); +#elif defined HAVE_WIN32_THREADS + ReleaseMutex(tok->mutex); +#elif defined HAVE_BEOS_THREADS + if (tok->tid == find_thread(NULL)) { + tok->tid = -1; + release_sem(tok->sem); + } +#endif +} + +/** + * xmlNewRMutex: + * + * xmlRNewMutex() is used to allocate a reentrant mutex for use in + * synchronizing access to data. token_r is a re-entrant lock and thus useful + * for synchronizing access to data structures that may be manipulated in a + * recursive fashion. + * + * Returns the new reentrant mutex pointer or NULL in case of error + */ +xmlRMutexPtr +xmlNewRMutex(void) +{ + xmlRMutexPtr tok; + + if ((tok = malloc(sizeof(xmlRMutex))) == NULL) + return (NULL); +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) { + pthread_mutex_init(&tok->lock, NULL); + tok->held = 0; + tok->waiters = 0; + pthread_cond_init(&tok->cv, NULL); + } +#elif defined HAVE_WIN32_THREADS + InitializeCriticalSection(&tok->cs); + tok->count = 0; +#elif defined HAVE_BEOS_THREADS + if ((tok->lock = xmlNewMutex()) == NULL) { + free(tok); + return NULL; + } + tok->count = 0; +#endif + return (tok); +} + +/** + * xmlFreeRMutex: + * @tok: the reentrant mutex + * + * xmlRFreeMutex() is used to reclaim resources associated with a + * reentrant mutex. + */ +void +xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED) +{ + if (tok == NULL) + return; +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded != 0) { + pthread_mutex_destroy(&tok->lock); + pthread_cond_destroy(&tok->cv); + } +#elif defined HAVE_WIN32_THREADS + DeleteCriticalSection(&tok->cs); +#elif defined HAVE_BEOS_THREADS + xmlFreeMutex(tok->lock); +#endif + free(tok); +} + +/** + * xmlRMutexLock: + * @tok: the reentrant mutex + * + * xmlRMutexLock() is used to lock a libxml2 token_r. + */ +void +xmlRMutexLock(xmlRMutexPtr tok) +{ + if (tok == NULL) + return; +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded == 0) + return; + + pthread_mutex_lock(&tok->lock); + if (tok->held) { + if (pthread_equal(tok->tid, pthread_self())) { + tok->held++; + pthread_mutex_unlock(&tok->lock); + return; + } else { + tok->waiters++; + while (tok->held) + pthread_cond_wait(&tok->cv, &tok->lock); + tok->waiters--; + } + } + tok->tid = pthread_self(); + tok->held = 1; + pthread_mutex_unlock(&tok->lock); +#elif defined HAVE_WIN32_THREADS + EnterCriticalSection(&tok->cs); + tok->count++; +#elif defined HAVE_BEOS_THREADS + if (tok->lock->tid == find_thread(NULL)) { + tok->count++; + return; + } else { + xmlMutexLock(tok->lock); + tok->count = 1; + } +#endif +} + +/** + * xmlRMutexUnlock: + * @tok: the reentrant mutex + * + * xmlRMutexUnlock() is used to unlock a libxml2 token_r. + */ +void +xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED) +{ + if (tok == NULL) + return; +#ifdef HAVE_PTHREAD_H + if (libxml_is_threaded == 0) + return; + + pthread_mutex_lock(&tok->lock); + tok->held--; + if (tok->held == 0) { + if (tok->waiters) + pthread_cond_signal(&tok->cv); + memset(&tok->tid, 0, sizeof(tok->tid)); + } + pthread_mutex_unlock(&tok->lock); +#elif defined HAVE_WIN32_THREADS + if (tok->count > 0) { tok->count--; LeaveCriticalSection(&tok->cs); - } -#elif defined HAVE_BEOS_THREADS - if (tok->lock->tid == find_thread(NULL)) { - tok->count--; - if (tok->count == 0) { - xmlMutexUnlock(tok->lock); - } - return; - } -#endif -} - -/** - * xmlGlobalInitMutexLock - * - * Makes sure that the global initialization mutex is initialized and - * locks it. - */ -void -__xmlGlobalInitMutexLock(void) -{ - /* Make sure the global init lock is initialized and then lock it. */ -#ifdef HAVE_PTHREAD_H - /* The mutex is statically initialized, so we just lock it. */ + } +#elif defined HAVE_BEOS_THREADS + if (tok->lock->tid == find_thread(NULL)) { + tok->count--; + if (tok->count == 0) { + xmlMutexUnlock(tok->lock); + } + return; + } +#endif +} + +/** + * xmlGlobalInitMutexLock + * + * Makes sure that the global initialization mutex is initialized and + * locks it. + */ +void +__xmlGlobalInitMutexLock(void) +{ + /* Make sure the global init lock is initialized and then lock it. */ +#ifdef HAVE_PTHREAD_H + /* The mutex is statically initialized, so we just lock it. */ #ifdef XML_PTHREAD_WEAK if (pthread_mutex_lock == NULL) return; #endif /* XML_PTHREAD_WEAK */ pthread_mutex_lock(&global_init_lock); -#elif defined HAVE_WIN32_THREADS - LPCRITICAL_SECTION cs; - - /* Create a new critical section */ - if (global_init_lock == NULL) { - cs = malloc(sizeof(CRITICAL_SECTION)); - if (cs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlGlobalInitMutexLock: out of memory\n"); - return; - } - InitializeCriticalSection(cs); - - /* Swap it into the global_init_lock */ -#ifdef InterlockedCompareExchangePointer +#elif defined HAVE_WIN32_THREADS + LPCRITICAL_SECTION cs; + + /* Create a new critical section */ + if (global_init_lock == NULL) { + cs = malloc(sizeof(CRITICAL_SECTION)); + if (cs == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlGlobalInitMutexLock: out of memory\n"); + return; + } + InitializeCriticalSection(cs); + + /* Swap it into the global_init_lock */ +#ifdef InterlockedCompareExchangePointer InterlockedCompareExchangePointer((void **) &global_init_lock, cs, NULL); -#else /* Use older void* version */ - InterlockedCompareExchange((void **) &global_init_lock, - (void *) cs, NULL); -#endif /* InterlockedCompareExchangePointer */ - - /* If another thread successfully recorded its critical - * section in the global_init_lock then discard the one - * allocated by this thread. */ - if (global_init_lock != cs) { - DeleteCriticalSection(cs); - free(cs); - } - } - - /* Lock the chosen critical section */ - EnterCriticalSection(global_init_lock); -#elif defined HAVE_BEOS_THREADS - int32 sem; - - /* Allocate a new semaphore */ - sem = create_sem(1, "xmlGlobalinitMutex"); - - while (global_init_lock == -1) { - if (atomic_add(&global_init_count, 1) == 0) { - global_init_lock = sem; - } else { - snooze(1); - atomic_add(&global_init_count, -1); - } - } - - /* If another thread successfully recorded its critical - * section in the global_init_lock then discard the one - * allocated by this thread. */ - if (global_init_lock != sem) - 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"); -#endif - } -#endif -} - -void -__xmlGlobalInitMutexUnlock(void) -{ -#ifdef HAVE_PTHREAD_H +#else /* Use older void* version */ + InterlockedCompareExchange((void **) &global_init_lock, + (void *) cs, NULL); +#endif /* InterlockedCompareExchangePointer */ + + /* If another thread successfully recorded its critical + * section in the global_init_lock then discard the one + * allocated by this thread. */ + if (global_init_lock != cs) { + DeleteCriticalSection(cs); + free(cs); + } + } + + /* Lock the chosen critical section */ + EnterCriticalSection(global_init_lock); +#elif defined HAVE_BEOS_THREADS + int32 sem; + + /* Allocate a new semaphore */ + sem = create_sem(1, "xmlGlobalinitMutex"); + + while (global_init_lock == -1) { + if (atomic_add(&global_init_count, 1) == 0) { + global_init_lock = sem; + } else { + snooze(1); + atomic_add(&global_init_count, -1); + } + } + + /* If another thread successfully recorded its critical + * section in the global_init_lock then discard the one + * allocated by this thread. */ + if (global_init_lock != sem) + 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"); +#endif + } +#endif +} + +void +__xmlGlobalInitMutexUnlock(void) +{ +#ifdef HAVE_PTHREAD_H #ifdef XML_PTHREAD_WEAK if (pthread_mutex_unlock == NULL) return; #endif /* XML_PTHREAD_WEAK */ pthread_mutex_unlock(&global_init_lock); -#elif defined HAVE_WIN32_THREADS - if (global_init_lock != NULL) { - LeaveCriticalSection(global_init_lock); - } -#elif defined HAVE_BEOS_THREADS - release_sem(global_init_lock); -#endif -} - -/** - * xmlGlobalInitMutexDestroy - * - * Makes sure that the global initialization mutex is destroyed before - * application termination. - */ -void -__xmlGlobalInitMutexDestroy(void) -{ -#ifdef HAVE_PTHREAD_H -#elif defined HAVE_WIN32_THREADS - if (global_init_lock != NULL) { - DeleteCriticalSection(global_init_lock); - free(global_init_lock); - global_init_lock = NULL; - } -#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 void -xmlFreeGlobalState(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 xmlGlobalStatePtr -xmlNewGlobalState(void) -{ - xmlGlobalState *gs; - - gs = malloc(sizeof(xmlGlobalState)); - if (gs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlGetGlobalState: out of memory\n"); - return (NULL); - } - - memset(gs, 0, sizeof(xmlGlobalState)); - xmlInitializeGlobalState(gs); - return (gs); -} -#endif /* LIBXML_THREAD_ENABLED */ - -#ifdef HAVE_PTHREAD_H -#elif defined 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 - */ -xmlGlobalStatePtr -xmlGetGlobalState(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(); - if (tsd == NULL) - return(NULL); - - 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(); - - if (tsd == NULL) - return(NULL); - p = (xmlGlobalStateCleanupHelperParams *) - malloc(sizeof(xmlGlobalStateCleanupHelperParams)); - if (p == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlGetGlobalState: out of memory\n"); - xmlFreeGlobalState(tsd); - return(NULL); - } - 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(); - if (tsd == NULL) - return (NULL); - - 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 - * Note that this is likely to be broken on some platforms using pthreads - * as the specification doesn't mandate pthread_t to be an integer type - * - * Returns the current thread ID number - */ -int -xmlGetThreadId(void) -{ -#ifdef HAVE_PTHREAD_H - pthread_t id; - int ret; - - if (libxml_is_threaded == 0) - return (0); - id = pthread_self(); - /* horrible but preserves compat, see warning above */ - memcpy(&ret, &id, sizeof(ret)); - return (ret); -#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 - */ -int -xmlIsMainThread(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 (pthread_equal(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. - */ -void -xmlLockLibrary(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. - */ -void -xmlUnlockLibrary(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. - */ -void -xmlInitThreads(void) -{ -#ifdef HAVE_PTHREAD_H +#elif defined HAVE_WIN32_THREADS + if (global_init_lock != NULL) { + LeaveCriticalSection(global_init_lock); + } +#elif defined HAVE_BEOS_THREADS + release_sem(global_init_lock); +#endif +} + +/** + * xmlGlobalInitMutexDestroy + * + * Makes sure that the global initialization mutex is destroyed before + * application termination. + */ +void +__xmlGlobalInitMutexDestroy(void) +{ +#ifdef HAVE_PTHREAD_H +#elif defined HAVE_WIN32_THREADS + if (global_init_lock != NULL) { + DeleteCriticalSection(global_init_lock); + free(global_init_lock); + global_init_lock = NULL; + } +#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 void +xmlFreeGlobalState(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 xmlGlobalStatePtr +xmlNewGlobalState(void) +{ + xmlGlobalState *gs; + + gs = malloc(sizeof(xmlGlobalState)); + if (gs == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlGetGlobalState: out of memory\n"); + return (NULL); + } + + memset(gs, 0, sizeof(xmlGlobalState)); + xmlInitializeGlobalState(gs); + return (gs); +} +#endif /* LIBXML_THREAD_ENABLED */ + +#ifdef HAVE_PTHREAD_H +#elif defined 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 + */ +xmlGlobalStatePtr +xmlGetGlobalState(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(); + if (tsd == NULL) + return(NULL); + + 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(); + + if (tsd == NULL) + return(NULL); + p = (xmlGlobalStateCleanupHelperParams *) + malloc(sizeof(xmlGlobalStateCleanupHelperParams)); + if (p == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlGetGlobalState: out of memory\n"); + xmlFreeGlobalState(tsd); + return(NULL); + } + 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(); + if (tsd == NULL) + return (NULL); + + 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 + * Note that this is likely to be broken on some platforms using pthreads + * as the specification doesn't mandate pthread_t to be an integer type + * + * Returns the current thread ID number + */ +int +xmlGetThreadId(void) +{ +#ifdef HAVE_PTHREAD_H + pthread_t id; + int ret; + + if (libxml_is_threaded == 0) + return (0); + id = pthread_self(); + /* horrible but preserves compat, see warning above */ + memcpy(&ret, &id, sizeof(ret)); + return (ret); +#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 + */ +int +xmlIsMainThread(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 (pthread_equal(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. + */ +void +xmlLockLibrary(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. + */ +void +xmlUnlockLibrary(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. + */ +void +xmlInitThreads(void) +{ +#ifdef HAVE_PTHREAD_H #ifdef XML_PTHREAD_WEAK - if (libxml_is_threaded == -1) { - if ((pthread_once != NULL) && - (pthread_getspecific != NULL) && - (pthread_setspecific != NULL) && - (pthread_key_create != NULL) && - (pthread_key_delete != NULL) && - (pthread_mutex_init != NULL) && - (pthread_mutex_destroy != NULL) && - (pthread_mutex_lock != NULL) && - (pthread_mutex_unlock != NULL) && - (pthread_cond_init != NULL) && - (pthread_cond_destroy != NULL) && - (pthread_cond_wait != NULL) && - (pthread_equal != NULL) && - (pthread_self != 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; - } - } + if (libxml_is_threaded == -1) { + if ((pthread_once != NULL) && + (pthread_getspecific != NULL) && + (pthread_setspecific != NULL) && + (pthread_key_create != NULL) && + (pthread_key_delete != NULL) && + (pthread_mutex_init != NULL) && + (pthread_mutex_destroy != NULL) && + (pthread_mutex_lock != NULL) && + (pthread_mutex_unlock != NULL) && + (pthread_cond_init != NULL) && + (pthread_cond_destroy != NULL) && + (pthread_cond_wait != NULL) && + (pthread_equal != NULL) && + (pthread_self != 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 /* XML_PTHREAD_WEAK */ -#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) - InitializeCriticalSection(&cleanup_helpers_cs); -#endif -} - -/** - * xmlCleanupThreads: - * - * xmlCleanupThreads() is used to to cleanup all the thread related - * data of the libxml2 library once processing has ended. - * - * WARNING: if your application is multithreaded or has plugin support - * calling this may crash the application if another thread or - * a plugin is still using libxml2. It's sometimes very hard to - * guess if libxml2 is in use in the application, some libraries - * or plugins may use it without notice. In case of doubt abstain - * from calling this function or do it just before calling exit() - * to avoid leak reports from valgrind ! - */ -void -xmlCleanupThreads(void) -{ -#ifdef DEBUG_THREADS - xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n"); -#endif -#ifdef HAVE_PTHREAD_H +#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) + InitializeCriticalSection(&cleanup_helpers_cs); +#endif +} + +/** + * xmlCleanupThreads: + * + * xmlCleanupThreads() is used to to cleanup all the thread related + * data of the libxml2 library once processing has ended. + * + * WARNING: if your application is multithreaded or has plugin support + * calling this may crash the application if another thread or + * a plugin is still using libxml2. It's sometimes very hard to + * guess if libxml2 is in use in the application, some libraries + * or plugins may use it without notice. In case of doubt abstain + * from calling this function or do it just before calling exit() + * to avoid leak reports from valgrind ! + */ +void +xmlCleanupThreads(void) +{ +#ifdef DEBUG_THREADS + xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n"); +#endif +#ifdef HAVE_PTHREAD_H if (libxml_is_threaded != 0) - pthread_key_delete(globalkey); - once_control = once_control_init; -#elif 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 void -xmlOnceInit(void) -{ -#ifdef HAVE_PTHREAD_H - (void) pthread_key_create(&globalkey, xmlFreeGlobalState); - mainthread = pthread_self(); - __xmlInitializeDict(); -#elif defined(HAVE_WIN32_THREADS) - if (!run_once.done) { - if (InterlockedIncrement(&run_once.control) == 1) { -#if !defined(HAVE_COMPILER_TLS) - globalkey = TlsAlloc(); -#endif - mainthread = GetCurrentThreadId(); - __xmlInitializeDict(); - 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); - } - } -#elif defined HAVE_BEOS_THREADS - if (atomic_add(&run_once_init, 1) == 0) { - globalkey = tls_allocate(); - tls_set(globalkey, NULL); - mainthread = find_thread(NULL); - __xmlInitializeDict(); - } 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 - */ -#ifdef HAVE_PTHREAD_H -#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) -#if defined(LIBXML_STATIC_FOR_DLL) + pthread_key_delete(globalkey); + once_control = once_control_init; +#elif 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 void +xmlOnceInit(void) +{ +#ifdef HAVE_PTHREAD_H + (void) pthread_key_create(&globalkey, xmlFreeGlobalState); + mainthread = pthread_self(); + __xmlInitializeDict(); +#elif defined(HAVE_WIN32_THREADS) + if (!run_once.done) { + if (InterlockedIncrement(&run_once.control) == 1) { +#if !defined(HAVE_COMPILER_TLS) + globalkey = TlsAlloc(); +#endif + mainthread = GetCurrentThreadId(); + __xmlInitializeDict(); + 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); + } + } +#elif defined HAVE_BEOS_THREADS + if (atomic_add(&run_once_init, 1) == 0) { + globalkey = tls_allocate(); + tls_set(globalkey, NULL); + mainthread = find_thread(NULL); + __xmlInitializeDict(); + } 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 + */ +#ifdef HAVE_PTHREAD_H +#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) +#if defined(LIBXML_STATIC_FOR_DLL) int XMLCALL xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason, ATTRIBUTE_UNUSED void *lpvReserved) -#else +#else /* declare to avoid "no previous prototype for 'DllMain'" warning */ /* Note that we do NOT want to include this function declaration in a public header because it's meant to be called by Windows itself, @@ -1010,39 +1010,39 @@ DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); -BOOL WINAPI +BOOL WINAPI DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason, ATTRIBUTE_UNUSED 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" +#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" |