Re: [xml] [patch] make libxml2 slightly more thread-friendly
- From: Ted Phelps <phelps mantara com>
- To: veillard redhat com
- Cc: xml gnome org
- Subject: Re: [xml] [patch] make libxml2 slightly more thread-friendly
- Date: Mon, 12 Feb 2007 10:44:07 -0600
Daniel Veillard writes:
see libxml.h in same directory as the C sources, prefix the function names
by __ so even if it shows up in the shared object people are not tempted to
call them and dont export from include/libxml/*.h
Ah, I see it. Thanks.
Hum, if you know you're in a specific environment where volatile is
expected then go ahead, just avoid it for the platform agnostic code
:-)
Ok, I've put the volatile qualifier back in.
Looks good except the __ renaming and include file.
Done.
Would you be so kind to make the last changes for the function name
and include, then I guess that should be commited,
Please see below. Thanks again for your help.
Cheers,
-Ted
diff -Naurp libxml2-2.6.27.orig/libxml.h libxml2-2.6.27/libxml.h
--- libxml2-2.6.27.orig/libxml.h 2006-05-31 14:29:44.000000000 +0100
+++ libxml2-2.6.27/libxml.h 2007-02-12 16:32:17.000000000 +0000
@@ -64,6 +64,11 @@ void __xmlLoaderErr(void *ctx, const cha
void __htmlParseContent(void *ctx);
#endif
+/*
+ * internal global initialization critical section routines.
+ */
+void __xmlGlobalInitMutexLock(void);
+void __xmlGlobalInitMutexUnlock(void);
#ifdef IN_LIBXML
#ifdef __GNUC__
diff -Naurp libxml2-2.6.27.orig/parser.c libxml2-2.6.27/parser.c
--- libxml2-2.6.27.orig/parser.c 2006-10-17 15:28:27.000000000 +0100
+++ libxml2-2.6.27/parser.c 2007-02-12 16:35:39.000000000 +0000
@@ -12839,26 +12839,34 @@ xmlInitParser(void) {
if (xmlParserInitialized != 0)
return;
- if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
- (xmlGenericError == NULL))
- initGenericErrorDefaultFunc(NULL);
- xmlInitGlobals();
- xmlInitThreads();
- xmlInitMemory();
- xmlInitCharEncodingHandlers();
- xmlDefaultSAXHandlerInit();
- xmlRegisterDefaultInputCallbacks();
+#ifdef LIBXML_THREAD_ENABLED
+ __xmlGlobalInitMutexLock();
+ if (xmlParserInitialized == 0) {
+#endif
+ if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
+ (xmlGenericError == NULL))
+ initGenericErrorDefaultFunc(NULL);
+ xmlInitGlobals();
+ xmlInitThreads();
+ xmlInitMemory();
+ xmlInitCharEncodingHandlers();
+ xmlDefaultSAXHandlerInit();
+ xmlRegisterDefaultInputCallbacks();
#ifdef LIBXML_OUTPUT_ENABLED
- xmlRegisterDefaultOutputCallbacks();
+ xmlRegisterDefaultOutputCallbacks();
#endif /* LIBXML_OUTPUT_ENABLED */
#ifdef LIBXML_HTML_ENABLED
- htmlInitAutoClose();
- htmlDefaultSAXHandlerInit();
+ htmlInitAutoClose();
+ htmlDefaultSAXHandlerInit();
#endif
#ifdef LIBXML_XPATH_ENABLED
- xmlXPathInit();
+ xmlXPathInit();
+#endif
+ xmlParserInitialized = 1;
+#ifdef LIBXML_THREAD_ENABLED
+ }
+ __xmlGlobalInitMutexUnlock();
#endif
- xmlParserInitialized = 1;
}
/**
diff -Naurp libxml2-2.6.27.orig/threads.c libxml2-2.6.27/threads.c
--- libxml2-2.6.27.orig/threads.c 2006-06-26 13:16:03.000000000 +0100
+++ libxml2-2.6.27/threads.c 2007-02-12 16:38:20.000000000 +0000
@@ -139,6 +139,7 @@ struct _xmlRMutex {
static pthread_key_t globalkey;
static pthread_t mainthread;
static pthread_once_t once_control = 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;
@@ -152,11 +153,14 @@ static struct
DWORD done;
DWORD 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;
@@ -413,6 +417,85 @@ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBU
#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
+ int err;
+
+ /* The mutex is statically initialized, so we just lock it. */
+ 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));
+ InitializeCriticalSection(cs);
+
+ /* Swap it into the global_init_lock */
+ InterlockedCompareExchangePointer(&global_init_lock, cs, NULL);
+
+ /* 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) {
+ 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");
+ 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 *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]