summaryrefslogtreecommitdiff
path: root/gnulib-local/lib/libxml/threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnulib-local/lib/libxml/threads.c')
-rw-r--r--gnulib-local/lib/libxml/threads.c584
1 files changed, 378 insertions, 206 deletions
diff --git a/gnulib-local/lib/libxml/threads.c b/gnulib-local/lib/libxml/threads.c
index 7124bca..b9d6cae 100644
--- a/gnulib-local/lib/libxml/threads.c
+++ b/gnulib-local/lib/libxml/threads.c
@@ -1,5 +1,5 @@
/**
- * threads.c: set of generic threading related routines
+ * threads.c: set of generic threading related routines
*
* See Copyright for the status of this software.
*
@@ -26,9 +26,7 @@
#endif
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
-#endif
-
-#ifdef HAVE_WIN32_THREADS
+#elif defined HAVE_WIN32_THREADS
#include <windows.h>
#ifndef HAVE_COMPILER_TLS
#include <process.h>
@@ -49,7 +47,7 @@
#ifdef HAVE_PTHREAD_H
static int libxml_is_threaded = -1;
-#ifdef __GNUC__
+#if defined(__GNUC__) && defined(__GLIBC__)
#ifdef linux
#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ > 3)
extern int pthread_once (pthread_once_t *__once_control,
@@ -63,6 +61,8 @@ extern int pthread_setspecific (pthread_key_t __key,
extern int pthread_key_create (pthread_key_t *__key,
void (*__destr_function) (void *))
__attribute((weak));
+extern int pthread_key_delete (pthread_key_t __key)
+ __attribute((weak));
extern int pthread_mutex_init ()
__attribute((weak));
extern int pthread_mutex_destroy ()
@@ -73,17 +73,23 @@ extern int pthread_mutex_unlock ()
__attribute((weak));
extern int pthread_cond_init ()
__attribute((weak));
+extern int pthread_cond_destroy ()
+ __attribute((weak));
+extern int pthread_cond_wait ()
+ __attribute((weak));
extern int pthread_equal ()
__attribute((weak));
extern pthread_t pthread_self ()
__attribute((weak));
extern int pthread_key_create ()
__attribute((weak));
+extern int pthread_key_delete ()
+ __attribute((weak));
extern int pthread_cond_signal ()
__attribute((weak));
#endif
#endif /* linux */
-#endif /* __GNUC__ */
+#endif /* defined(__GNUC__) && defined(__GLIBC__) */
#endif /* HAVE_PTHREAD_H */
/*
@@ -101,8 +107,8 @@ struct _xmlMutex {
#elif defined HAVE_WIN32_THREADS
HANDLE mutex;
#elif defined HAVE_BEOS_THREADS
- sem_id sem;
- thread_id tid;
+ sem_id sem;
+ thread_id tid;
#else
int empty;
#endif
@@ -114,21 +120,22 @@ struct _xmlMutex {
struct _xmlRMutex {
#ifdef HAVE_PTHREAD_H
pthread_mutex_t lock;
- unsigned int held;
- unsigned int waiters;
- pthread_t tid;
- pthread_cond_t cv;
+ 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;
+ xmlMutexPtr lock;
+ thread_id tid;
+ int32 count;
#else
int empty;
#endif
};
+
/*
* This module still has some internal static data.
* - xmlLibraryLock a global lock
@@ -136,9 +143,11 @@ struct _xmlRMutex {
*/
#ifdef HAVE_PTHREAD_H
-static pthread_key_t globalkey;
-static pthread_t mainthread;
+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;
@@ -147,19 +156,23 @@ static __declspec(thread) int tlstate_inited = 0;
static DWORD globalkey = TLS_OUT_OF_INDEXES;
#endif /* HAVE_COMPILER_TLS */
static DWORD mainthread;
-static struct
-{
+static struct {
DWORD done;
DWORD control;
-} run_once = { 0, 0 };
+} 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;
+static xmlRMutexPtr xmlLibraryLock = NULL;
+
#ifdef LIBXML_THREAD_ENABLED
static void xmlOnceInit(void);
#endif
@@ -181,15 +194,15 @@ xmlNewMutex(void)
return (NULL);
#ifdef HAVE_PTHREAD_H
if (libxml_is_threaded != 0)
- pthread_mutex_init(&tok->lock, NULL);
+ 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;
+ if ((tok->sem = create_sem(1, "xmlMutex")) < B_OK) {
+ free(tok);
+ return NULL;
+ }
+ tok->tid = -1;
#endif
return (tok);
}
@@ -204,15 +217,16 @@ xmlNewMutex(void)
void
xmlFreeMutex(xmlMutexPtr tok)
{
- if (tok == NULL) return;
+ if (tok == NULL)
+ return;
#ifdef HAVE_PTHREAD_H
if (libxml_is_threaded != 0)
- pthread_mutex_destroy(&tok->lock);
+ pthread_mutex_destroy(&tok->lock);
#elif defined HAVE_WIN32_THREADS
CloseHandle(tok->mutex);
#elif defined HAVE_BEOS_THREADS
- delete_sem(tok->sem);
+ delete_sem(tok->sem);
#endif
free(tok);
}
@@ -230,17 +244,17 @@ xmlMutexLock(xmlMutexPtr tok)
return;
#ifdef HAVE_PTHREAD_H
if (libxml_is_threaded != 0)
- pthread_mutex_lock(&tok->lock);
+ 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) {
+ if (acquire_sem(tok->sem) != B_NO_ERROR) {
#ifdef DEBUG_THREADS
- xmlGenericError(xmlGenericErrorContext, "xmlMutexLock():BeOS:Couldn't aquire semaphore\n");
- exit();
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlMutexLock():BeOS:Couldn't aquire semaphore\n");
#endif
- }
- tok->tid = find_thread(NULL);
+ }
+ tok->tid = find_thread(NULL);
#endif
}
@@ -258,14 +272,14 @@ xmlMutexUnlock(xmlMutexPtr tok)
return;
#ifdef HAVE_PTHREAD_H
if (libxml_is_threaded != 0)
- pthread_mutex_unlock(&tok->lock);
+ 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);
- }
+ if (tok->tid == find_thread(NULL)) {
+ tok->tid = -1;
+ release_sem(tok->sem);
+ }
#endif
}
@@ -288,20 +302,20 @@ xmlNewRMutex(void)
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);
+ 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;
+ if ((tok->lock = xmlNewMutex()) == NULL) {
+ free(tok);
+ return NULL;
+ }
+ tok->count = 0;
#endif
return (tok);
}
@@ -320,13 +334,13 @@ xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
return;
#ifdef HAVE_PTHREAD_H
if (libxml_is_threaded != 0) {
- pthread_mutex_destroy(&tok->lock);
- pthread_cond_destroy(&tok->cv);
+ 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);
+ xmlFreeMutex(tok->lock);
#endif
free(tok);
}
@@ -364,15 +378,15 @@ xmlRMutexLock(xmlRMutexPtr tok)
pthread_mutex_unlock(&tok->lock);
#elif defined HAVE_WIN32_THREADS
EnterCriticalSection(&tok->cs);
- ++tok->count;
+ tok->count++;
#elif defined HAVE_BEOS_THREADS
- if (tok->lock->tid == find_thread(NULL)) {
- tok->count++;
- return;
- } else {
- xmlMutexLock(tok->lock);
- tok->count = 1;
- }
+ if (tok->lock->tid == find_thread(NULL)) {
+ tok->count++;
+ return;
+ } else {
+ xmlMutexLock(tok->lock);
+ tok->count = 1;
+ }
#endif
}
@@ -390,26 +404,139 @@ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
#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);
- tok->tid = 0;
+ memset(&tok->tid, 0, sizeof(tok->tid));
}
pthread_mutex_unlock(&tok->lock);
#elif defined HAVE_WIN32_THREADS
- if (!--tok->count)
- LeaveCriticalSection(&tok->cs);
+ 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;
- }
+ 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. */
+ if (pthread_mutex_lock != NULL)
+ 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
+ InterlockedCompareExchangePointer(&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
+ if (pthread_mutex_unlock != NULL)
+ 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
}
@@ -423,6 +550,7 @@ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
#ifdef xmlLastError
#undef xmlLastError
#endif
+
/**
* xmlFreeGlobalState:
* @state: a thread global state
@@ -453,10 +581,13 @@ static xmlGlobalStatePtr
xmlNewGlobalState(void)
{
xmlGlobalState *gs;
-
+
gs = malloc(sizeof(xmlGlobalState));
- if (gs == NULL)
- return(NULL);
+ if (gs == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlGetGlobalState: out of memory\n");
+ return (NULL);
+ }
memset(gs, 0, sizeof(xmlGlobalState));
xmlInitializeGlobalState(gs);
@@ -464,19 +595,20 @@ xmlNewGlobalState(void)
}
#endif /* LIBXML_THREAD_ENABLED */
-
-#ifdef HAVE_WIN32_THREADS
+#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
-{
+typedef struct _xmlGlobalStateCleanupHelperParams {
HANDLE thread;
void *memory;
} xmlGlobalStateCleanupHelperParams;
-static void XMLCDECL xmlGlobalStateCleanupHelper (void *p)
+static void XMLCDECL
+xmlGlobalStateCleanupHelper(void *p)
{
- xmlGlobalStateCleanupHelperParams *params = (xmlGlobalStateCleanupHelperParams *) p;
+ xmlGlobalStateCleanupHelperParams *params =
+ (xmlGlobalStateCleanupHelperParams *) p;
WaitForSingleObject(params->thread, INFINITE);
CloseHandle(params->thread);
xmlFreeGlobalState(params->memory);
@@ -485,14 +617,13 @@ static void XMLCDECL xmlGlobalStateCleanupHelper (void *p)
}
#else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */
-typedef struct _xmlGlobalStateCleanupHelperParams
-{
+typedef struct _xmlGlobalStateCleanupHelperParams {
void *memory;
- struct _xmlGlobalStateCleanupHelperParams * prev;
- struct _xmlGlobalStateCleanupHelperParams * next;
+ struct _xmlGlobalStateCleanupHelperParams *prev;
+ struct _xmlGlobalStateCleanupHelperParams *next;
} xmlGlobalStateCleanupHelperParams;
-static xmlGlobalStateCleanupHelperParams * cleanup_helpers_head = NULL;
+static xmlGlobalStateCleanupHelperParams *cleanup_helpers_head = NULL;
static CRITICAL_SECTION cleanup_helpers_cs;
#endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */
@@ -500,17 +631,20 @@ static CRITICAL_SECTION cleanup_helpers_cs;
#endif /* HAVE_WIN32_THREADS */
#if defined HAVE_BEOS_THREADS
+
/**
* xmlGlobalStateCleanup:
* @data: unused parameter
*
* Used for Beos only
*/
-void xmlGlobalStateCleanup(void *data)
+void
+xmlGlobalStateCleanup(void *data)
{
- void *globalval = tls_get(globalkey);
- if (globalval != NULL)
- xmlFreeGlobalState(globalval);
+ void *globalval = tls_get(globalkey);
+
+ if (globalval != NULL)
+ xmlFreeGlobalState(globalval);
}
#endif
@@ -528,13 +662,15 @@ xmlGetGlobalState(void)
xmlGlobalState *globalval;
if (libxml_is_threaded == 0)
- return(NULL);
+ return (NULL);
pthread_once(&once_control, xmlOnceInit);
if ((globalval = (xmlGlobalState *)
- pthread_getspecific(globalkey)) == NULL) {
+ pthread_getspecific(globalkey)) == NULL) {
xmlGlobalState *tsd = xmlNewGlobalState();
+ if (tsd == NULL)
+ return(NULL);
pthread_setspecific(globalkey, tsd);
return (tsd);
@@ -543,43 +679,54 @@ xmlGetGlobalState(void)
#elif defined HAVE_WIN32_THREADS
#if defined(HAVE_COMPILER_TLS)
if (!tlstate_inited) {
- tlstate_inited = 1;
- xmlInitializeGlobalState(&tlstate);
+ tlstate_inited = 1;
+ xmlInitializeGlobalState(&tlstate);
}
return &tlstate;
#else /* HAVE_COMPILER_TLS */
xmlGlobalState *globalval;
- xmlGlobalStateCleanupHelperParams * p;
+ xmlGlobalStateCleanupHelperParams *p;
xmlOnceInit();
#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
- globalval = (xmlGlobalState *)TlsGetValue(globalkey);
+ globalval = (xmlGlobalState *) TlsGetValue(globalkey);
#else
- p = (xmlGlobalStateCleanupHelperParams*)TlsGetValue(globalkey);
- globalval = (xmlGlobalState *)(p ? p->memory : NULL);
+ 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;
+ 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);
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
+ GetCurrentProcess(), &p->thread, 0, TRUE,
+ DUPLICATE_SAME_ACCESS);
+ TlsSetValue(globalkey, tsd);
+ _beginthread(xmlGlobalStateCleanupHelper, 0, p);
#else
- EnterCriticalSection(&cleanup_helpers_cs);
+ 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);
+ p->next = cleanup_helpers_head;
+ p->prev = NULL;
+ cleanup_helpers_head = p;
+ TlsSetValue(globalkey, p);
+ LeaveCriticalSection(&cleanup_helpers_cs);
#endif
- return (tsd);
+ return (tsd);
}
return (globalval);
#endif /* HAVE_COMPILER_TLS */
@@ -588,9 +735,10 @@ xmlGetGlobalState(void)
xmlOnceInit();
- if ((globalval = (xmlGlobalState *)
- tls_get(globalkey)) == NULL) {
+ if ((globalval = (xmlGlobalState *) tls_get(globalkey)) == NULL) {
xmlGlobalState *tsd = xmlNewGlobalState();
+ if (tsd == NULL)
+ return (NULL);
tls_set(globalkey, tsd);
on_exit_thread(xmlGlobalStateCleanup, NULL);
@@ -598,7 +746,7 @@ xmlGetGlobalState(void)
}
return (globalval);
#else
- return(NULL);
+ return (NULL);
#endif
}
@@ -612,6 +760,8 @@ xmlGetGlobalState(void)
* 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
*/
@@ -619,15 +769,21 @@ int
xmlGetThreadId(void)
{
#ifdef HAVE_PTHREAD_H
+ pthread_t id;
+ int ret;
+
if (libxml_is_threaded == 0)
- return(0);
- return((int) pthread_self());
+ 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);
+ return find_thread(NULL);
#else
- return((int) 0);
+ return ((int) 0);
#endif
}
@@ -645,25 +801,25 @@ xmlIsMainThread(void)
if (libxml_is_threaded == -1)
xmlInitThreads();
if (libxml_is_threaded == 0)
- return(1);
+ return (1);
pthread_once(&once_control, xmlOnceInit);
#elif defined HAVE_WIN32_THREADS
- xmlOnceInit ();
+ xmlOnceInit();
#elif defined HAVE_BEOS_THREADS
xmlOnceInit();
#endif
-
+
#ifdef DEBUG_THREADS
xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n");
#endif
#ifdef HAVE_PTHREAD_H
- return(mainthread == pthread_self());
+ return (pthread_equal(mainthread,pthread_self()));
#elif defined HAVE_WIN32_THREADS
- return(mainthread == GetCurrentThreadId ());
+ return (mainthread == GetCurrentThreadId());
#elif defined HAVE_BEOS_THREADS
- return(mainthread == find_thread(NULL));
+ return (mainthread == find_thread(NULL));
#else
- return(1);
+ return (1);
#endif
}
@@ -706,34 +862,34 @@ xmlUnlockLibrary(void)
void
xmlInitThreads(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;
+ (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 {
+ } else {
+
/* fprintf(stderr, "Running without multithread\n"); */
- libxml_is_threaded = 0;
- }
+ libxml_is_threaded = 0;
+ }
}
+#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+ InitializeCriticalSection(&cleanup_helpers_cs);
#endif
}
@@ -742,6 +898,14 @@ xmlInitThreads(void)
*
* 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)
@@ -749,27 +913,34 @@ xmlCleanupThreads(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))
+#ifdef HAVE_PTHREAD_H
+ if ((libxml_is_threaded) && (pthread_key_delete != NULL))
+ 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;
+ 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
*
@@ -780,38 +951,36 @@ xmlCleanupThreads(void)
* details.
*/
static void
-xmlOnceInit(void) {
+xmlOnceInit(void)
+{
#ifdef HAVE_PTHREAD_H
(void) pthread_key_create(&globalkey, xmlFreeGlobalState);
mainthread = pthread_self();
-#endif
-
-#if defined(HAVE_WIN32_THREADS)
+ __xmlInitializeDict();
+#elif defined(HAVE_WIN32_THREADS)
if (!run_once.done) {
- if (InterlockedIncrement(&run_once.control) == 1)
- {
+ if (InterlockedIncrement(&run_once.control) == 1) {
#if !defined(HAVE_COMPILER_TLS)
globalkey = TlsAlloc();
#endif
mainthread = GetCurrentThreadId();
+ __xmlInitializeDict();
run_once.done = 1;
- }
- else {
+ } 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);
+#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
@@ -827,38 +996,41 @@ xmlOnceInit(void) {
*
* Returns TRUE always
*/
-#if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
+#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)
-BOOL WINAPI xmlDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+BOOL XMLCALL
+xmlDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
#else
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+BOOL 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);
+ 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);
+ }
}
- 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;
+ break;
}
return TRUE;
}