[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [xml] [patch] make libxml2 slightly more thread-friendly



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]