Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / gnulib-local / lib / libxml / threads.c
index 7124bca..b9d6cae 100644 (file)
@@ -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;
 }