[libxml2] Revert "Simplify recursive pthread mutex"



commit 83d5a87e372c9688d6dbacade2a4959ead8d38c8
Author: Nick Wellnhofer <wellnhofer aevum de>
Date:   Fri Mar 18 15:46:30 2022 +0100

    Revert "Simplify recursive pthread mutex"
    
    This reverts commit 5ffe2981b7d0547dd957a61ac6e1e3db829748d1.
    This reverts commit 4adb7677635b2c8d764767f6b484de1b26217f5d.
    
    Recursive mutexes are an XSI extension, so better not rely on them.

 threads.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 54 insertions(+), 17 deletions(-)
---
diff --git a/threads.c b/threads.c
index c024ae60..c33150ea 100644
--- a/threads.c
+++ b/threads.c
@@ -46,20 +46,23 @@ static int libxml_is_threaded = -1;
 
 #define XML_PTHREAD_WEAK
 
-#pragma weak pthread_equal
+#pragma weak pthread_once
 #pragma weak pthread_getspecific
+#pragma weak pthread_setspecific
 #pragma weak pthread_key_create
 #pragma weak pthread_key_delete
-#pragma weak pthread_mutex_destroy
 #pragma weak pthread_mutex_init
+#pragma weak pthread_mutex_destroy
 #pragma weak pthread_mutex_lock
 #pragma weak pthread_mutex_unlock
-#pragma weak pthread_mutexattr_destroy
-#pragma weak pthread_mutexattr_init
-#pragma weak pthread_mutexattr_settype
-#pragma weak pthread_once
+#pragma weak pthread_cond_init
+#pragma weak pthread_cond_destroy
+#pragma weak pthread_cond_wait
+#pragma weak pthread_equal
 #pragma weak pthread_self
-#pragma weak pthread_setspecific
+#pragma weak pthread_key_create
+#pragma weak pthread_key_delete
+#pragma weak pthread_cond_signal
 
 #else /* __GNUC__, __GLIBC__, __linux__ */
 
@@ -97,6 +100,10 @@ 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;
 #elif defined HAVE_WIN32_THREADS
     CRITICAL_SECTION cs;
 #elif defined HAVE_BEOS_THREADS
@@ -274,11 +281,10 @@ xmlNewRMutex(void)
         return (NULL);
 #ifdef HAVE_PTHREAD_H
     if (libxml_is_threaded != 0) {
-        pthread_mutexattr_t attr;
-        pthread_mutexattr_init(&attr);
-        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-        pthread_mutex_init(&tok->lock, &attr);
-        pthread_mutexattr_destroy(&attr);
+        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);
@@ -307,6 +313,7 @@ xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
 #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);
@@ -328,8 +335,25 @@ xmlRMutexLock(xmlRMutexPtr tok)
     if (tok == NULL)
         return;
 #ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded != 0)
-        pthread_mutex_lock(&tok->lock);
+    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);
 #elif defined HAVE_BEOS_THREADS
@@ -355,8 +379,17 @@ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
     if (tok == NULL)
         return;
 #ifdef HAVE_PTHREAD_H
-    if (libxml_is_threaded != 0)
-        pthread_mutex_unlock(&tok->lock);
+    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
     LeaveCriticalSection(&tok->cs);
 #elif defined HAVE_BEOS_THREADS
@@ -825,8 +858,12 @@ xmlInitThreads(void)
             (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_self != NULL) &&
+            (pthread_cond_signal != NULL)) {
             libxml_is_threaded = 1;
 
 /* fprintf(stderr, "Running multithreaded\n"); */


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