summaryrefslogtreecommitdiff
path: root/chromium/third_party/libxml/src/threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/libxml/src/threads.c')
-rw-r--r--chromium/third_party/libxml/src/threads.c332
1 files changed, 162 insertions, 170 deletions
diff --git a/chromium/third_party/libxml/src/threads.c b/chromium/third_party/libxml/src/threads.c
index 9fa477e53b6..56a917e6de5 100644
--- a/chromium/third_party/libxml/src/threads.c
+++ b/chromium/third_party/libxml/src/threads.c
@@ -16,20 +16,6 @@
#include <libxml/threads.h>
#include <libxml/globals.h>
-#ifdef LIBXML_THREAD_ENABLED
- #ifdef HAVE_PTHREAD_H
- #include <pthread.h>
- #define HAVE_POSIX_THREADS
- #elif defined(_WIN32)
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #ifndef HAVE_COMPILER_TLS
- #include <process.h>
- #endif
- #define HAVE_WIN32_THREADS
- #endif
-#endif
-
#if defined(SOLARIS)
#include <note.h>
#endif
@@ -39,15 +25,40 @@
/* #define DEBUG_THREADS */
-#ifdef HAVE_POSIX_THREADS
+#if defined(HAVE_POSIX_THREADS) && \
+ defined(__GLIBC__) && \
+ __GLIBC__ * 100 + __GLIBC_MINOR__ >= 234
-#if defined(__GNUC__) && defined(__linux__)
+/*
+ * The modern way available since glibc 2.32.
+ *
+ * The check above is for glibc 2.34 which merged the pthread symbols into
+ * libc. Since we still allow linking without pthread symbols (see below),
+ * this only works if pthread symbols are guaranteed to be available.
+ */
-static int libxml_is_threaded = -1;
+#include <sys/single_threaded.h>
-#define XML_PTHREAD_WEAK
+#define XML_IS_THREADED() (!__libc_single_threaded)
+
+#elif defined(HAVE_POSIX_THREADS) && \
+ defined(__GLIBC__) && \
+ defined(__GNUC__)
+
+/*
+ * The traditional way to check for single-threaded applications with
+ * glibc was to check whether the separate libpthread library is
+ * linked in. This works by not linking libxml2 with libpthread (see
+ * BASE_THREAD_LIBS in configure.ac and Makefile.am) and declaring
+ * pthread functions as weak symbols.
+ *
+ * In glibc 2.34, the pthread symbols were moved from libpthread to libc,
+ * so this doesn't work anymore.
+ *
+ * At some point, this legacy code and the BASE_THREAD_LIBS hack in
+ * configure.ac can probably be removed.
+ */
-#pragma weak pthread_once
#pragma weak pthread_getspecific
#pragma weak pthread_setspecific
#pragma weak pthread_key_create
@@ -65,13 +76,16 @@ static int libxml_is_threaded = -1;
#pragma weak pthread_key_delete
#pragma weak pthread_cond_signal
-#else /* __GNUC__, __GLIBC__, __linux__ */
+#define XML_PTHREAD_WEAK
+#define XML_IS_THREADED() libxml_is_threaded
+
+static int libxml_is_threaded = -1;
-static int libxml_is_threaded = 1;
+#else /* other POSIX platforms */
-#endif /* __GNUC__, __GLIBC__, __linux__ */
+#define XML_IS_THREADED() 1
-#endif /* HAVE_POSIX_THREADS */
+#endif
/*
* TODO: this module still uses malloc/free and not xmlMalloc/xmlFree
@@ -80,19 +94,6 @@ static int libxml_is_threaded = 1;
*/
/*
- * xmlMutex are a simple mutual exception locks
- */
-struct _xmlMutex {
-#ifdef HAVE_POSIX_THREADS
- pthread_mutex_t lock;
-#elif defined HAVE_WIN32_THREADS
- CRITICAL_SECTION cs;
-#else
- int empty;
-#endif
-};
-
-/*
* xmlRMutex are reentrant mutual exception locks
*/
struct _xmlRMutex {
@@ -118,8 +119,6 @@ struct _xmlRMutex {
#ifdef HAVE_POSIX_THREADS
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)
@@ -129,18 +128,28 @@ static __declspec(thread) int tlstate_inited = 0;
static DWORD globalkey = TLS_OUT_OF_INDEXES;
#endif /* HAVE_COMPILER_TLS */
static DWORD mainthread;
-static struct {
- DWORD done;
- LONG control;
-} run_once = { 0, 0};
static volatile LPCRITICAL_SECTION global_init_lock = NULL;
#endif
static xmlRMutexPtr xmlLibraryLock = NULL;
-#ifdef LIBXML_THREAD_ENABLED
-static void xmlOnceInit(void);
+/**
+ * xmlInitMutex:
+ * @mutex: the mutex
+ *
+ * Initialize a mutex.
+ */
+void
+xmlInitMutex(xmlMutexPtr mutex)
+{
+#ifdef HAVE_POSIX_THREADS
+ pthread_mutex_init(&mutex->lock, NULL);
+#elif defined HAVE_WIN32_THREADS
+ InitializeCriticalSection(&mutex->cs);
+#else
+ (void) mutex;
#endif
+}
/**
* xmlNewMutex:
@@ -157,21 +166,33 @@ xmlNewMutex(void)
if ((tok = malloc(sizeof(xmlMutex))) == NULL)
return (NULL);
+ xmlInitMutex(tok);
+ return (tok);
+}
+
+/**
+ * xmlCleanupMutex:
+ * @mutex: the simple mutex
+ *
+ * Reclaim resources associated with a mutex.
+ */
+void
+xmlCleanupMutex(xmlMutexPtr mutex)
+{
#ifdef HAVE_POSIX_THREADS
- if (libxml_is_threaded != 0)
- pthread_mutex_init(&tok->lock, NULL);
+ pthread_mutex_destroy(&mutex->lock);
#elif defined HAVE_WIN32_THREADS
- InitializeCriticalSection(&tok->cs);
+ DeleteCriticalSection(&mutex->cs);
+#else
+ (void) mutex;
#endif
- return (tok);
}
/**
* xmlFreeMutex:
* @tok: the simple mutex
*
- * xmlFreeMutex() is used to reclaim resources associated with a libxml2 token
- * struct.
+ * Free a mutex.
*/
void
xmlFreeMutex(xmlMutexPtr tok)
@@ -179,12 +200,7 @@ xmlFreeMutex(xmlMutexPtr tok)
if (tok == NULL)
return;
-#ifdef HAVE_POSIX_THREADS
- if (libxml_is_threaded != 0)
- pthread_mutex_destroy(&tok->lock);
-#elif defined HAVE_WIN32_THREADS
- DeleteCriticalSection(&tok->cs);
-#endif
+ xmlCleanupMutex(tok);
free(tok);
}
@@ -200,7 +216,11 @@ xmlMutexLock(xmlMutexPtr tok)
if (tok == NULL)
return;
#ifdef HAVE_POSIX_THREADS
- if (libxml_is_threaded != 0)
+ /*
+ * This assumes that __libc_single_threaded won't change while the
+ * lock is held.
+ */
+ if (XML_IS_THREADED() != 0)
pthread_mutex_lock(&tok->lock);
#elif defined HAVE_WIN32_THREADS
EnterCriticalSection(&tok->cs);
@@ -220,7 +240,7 @@ xmlMutexUnlock(xmlMutexPtr tok)
if (tok == NULL)
return;
#ifdef HAVE_POSIX_THREADS
- if (libxml_is_threaded != 0)
+ if (XML_IS_THREADED() != 0)
pthread_mutex_unlock(&tok->lock);
#elif defined HAVE_WIN32_THREADS
LeaveCriticalSection(&tok->cs);
@@ -245,12 +265,10 @@ xmlNewRMutex(void)
if ((tok = malloc(sizeof(xmlRMutex))) == NULL)
return (NULL);
#ifdef HAVE_POSIX_THREADS
- 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);
#endif
@@ -270,10 +288,8 @@ xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
if (tok == NULL)
return;
#ifdef HAVE_POSIX_THREADS
- 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);
#endif
@@ -292,7 +308,7 @@ xmlRMutexLock(xmlRMutexPtr tok)
if (tok == NULL)
return;
#ifdef HAVE_POSIX_THREADS
- if (libxml_is_threaded == 0)
+ if (XML_IS_THREADED() == 0)
return;
pthread_mutex_lock(&tok->lock);
@@ -328,7 +344,7 @@ xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
if (tok == NULL)
return;
#ifdef HAVE_POSIX_THREADS
- if (libxml_is_threaded == 0)
+ if (XML_IS_THREADED() == 0)
return;
pthread_mutex_lock(&tok->lock);
@@ -355,11 +371,14 @@ __xmlGlobalInitMutexLock(void)
{
/* Make sure the global init lock is initialized and then lock it. */
#ifdef HAVE_POSIX_THREADS
- /* The mutex is statically initialized, so we just lock it. */
#ifdef XML_PTHREAD_WEAK
if (pthread_mutex_lock == NULL)
return;
-#endif /* XML_PTHREAD_WEAK */
+#else
+ if (XML_IS_THREADED() == 0)
+ return;
+#endif
+ /* The mutex is statically initialized, so we just lock it. */
pthread_mutex_lock(&global_init_lock);
#elif defined HAVE_WIN32_THREADS
LPCRITICAL_SECTION cs;
@@ -402,9 +421,12 @@ __xmlGlobalInitMutexUnlock(void)
{
#ifdef HAVE_POSIX_THREADS
#ifdef XML_PTHREAD_WEAK
- if (pthread_mutex_unlock == NULL)
+ if (pthread_mutex_lock == NULL)
return;
-#endif /* XML_PTHREAD_WEAK */
+#else
+ if (XML_IS_THREADED() == 0)
+ return;
+#endif
pthread_mutex_unlock(&global_init_lock);
#elif defined HAVE_WIN32_THREADS
if (global_init_lock != NULL) {
@@ -496,7 +518,7 @@ typedef struct _xmlGlobalStateCleanupHelperParams {
void *memory;
} xmlGlobalStateCleanupHelperParams;
-static void XMLCDECL
+static void
xmlGlobalStateCleanupHelper(void *p)
{
xmlGlobalStateCleanupHelperParams *params =
@@ -525,6 +547,8 @@ static CRITICAL_SECTION cleanup_helpers_cs;
/**
* xmlGetGlobalState:
*
+ * DEPRECATED: Internal function, do not use.
+ *
* xmlGetGlobalState() is called to retrieve the global state for a thread.
*
* Returns the thread global state or NULL in case of error
@@ -535,11 +559,9 @@ xmlGetGlobalState(void)
#ifdef HAVE_POSIX_THREADS
xmlGlobalState *globalval;
- if (libxml_is_threaded == 0)
+ if (XML_IS_THREADED() == 0)
return (NULL);
- pthread_once(&once_control, xmlOnceInit);
-
if ((globalval = (xmlGlobalState *)
pthread_getspecific(globalkey)) == NULL) {
xmlGlobalState *tsd = xmlNewGlobalState();
@@ -560,8 +582,6 @@ xmlGetGlobalState(void)
#else /* HAVE_COMPILER_TLS */
xmlGlobalState *globalval;
xmlGlobalStateCleanupHelperParams *p;
-
- xmlOnceInit();
#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
globalval = (xmlGlobalState *) TlsGetValue(globalkey);
#else
@@ -618,6 +638,8 @@ xmlGetGlobalState(void)
/**
* xmlGetThreadId:
*
+ * DEPRECATED: Internal function, do not use.
+ *
* 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
@@ -631,7 +653,7 @@ xmlGetThreadId(void)
pthread_t id;
int ret;
- if (libxml_is_threaded == 0)
+ if (XML_IS_THREADED() == 0)
return (0);
id = pthread_self();
/* horrible but preserves compat, see warning above */
@@ -647,6 +669,8 @@ xmlGetThreadId(void)
/**
* xmlIsMainThread:
*
+ * DEPRECATED: Internal function, do not use.
+ *
* xmlIsMainThread() check whether the current thread is the main thread.
*
* Returns 1 if the current thread is the main thread, 0 otherwise
@@ -654,20 +678,14 @@ xmlGetThreadId(void)
int
xmlIsMainThread(void)
{
-#ifdef HAVE_POSIX_THREADS
- if (libxml_is_threaded == -1)
- xmlInitThreads();
- if (libxml_is_threaded == 0)
- return (1);
- pthread_once(&once_control, xmlOnceInit);
-#elif defined HAVE_WIN32_THREADS
- xmlOnceInit();
-#endif
+ xmlInitParser();
#ifdef DEBUG_THREADS
xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n");
#endif
#ifdef HAVE_POSIX_THREADS
+ if (XML_IS_THREADED() == 0)
+ return (1);
return (pthread_equal(mainthread,pthread_self()));
#elif defined HAVE_WIN32_THREADS
return (mainthread == GetCurrentThreadId());
@@ -709,19 +727,31 @@ xmlUnlockLibrary(void)
/**
* xmlInitThreads:
*
- * DEPRECATED: This function will be made private. Call xmlInitParser to
- * initialize the library.
- *
- * xmlInitThreads() is used to to initialize all the thread related
- * data of the libxml2 library.
+ * DEPRECATED: Alias for xmlInitParser.
*/
void
xmlInitThreads(void)
{
+ xmlInitParser();
+}
+
+/**
+ * xmlInitThreadsInternal:
+ *
+ * Used to to initialize all the thread related data.
+ */
+void
+xmlInitThreadsInternal(void)
+{
#ifdef HAVE_POSIX_THREADS
#ifdef XML_PTHREAD_WEAK
- if (libxml_is_threaded == -1) {
- if ((pthread_once != NULL) &&
+ /*
+ * This is somewhat unreliable since libpthread could be loaded
+ * later with dlopen() and threads could be created. But it's
+ * long-standing behavior and hard to work around.
+ */
+ if (libxml_is_threaded == -1)
+ libxml_is_threaded =
(pthread_getspecific != NULL) &&
(pthread_setspecific != NULL) &&
(pthread_key_create != NULL) &&
@@ -733,51 +763,56 @@ xmlInitThreads(void)
(pthread_cond_init != NULL) &&
(pthread_cond_destroy != NULL) &&
(pthread_cond_wait != NULL) &&
- (pthread_equal != NULL) &&
+ /*
+ * pthread_equal can be inline, resuting in -Waddress warnings.
+ * Let's assume it's available if all the other functions are.
+ */
+ /* (pthread_equal != NULL) && */
(pthread_self != NULL) &&
- (pthread_cond_signal != NULL)) {
- libxml_is_threaded = 1;
-
-/* fprintf(stderr, "Running multithreaded\n"); */
- } else {
-
-/* fprintf(stderr, "Running without multithread\n"); */
- libxml_is_threaded = 0;
- }
- }
+ (pthread_cond_signal != NULL);
+ if (libxml_is_threaded == 0)
+ return;
#endif /* XML_PTHREAD_WEAK */
+ pthread_key_create(&globalkey, xmlFreeGlobalState);
+ mainthread = pthread_self();
+#elif defined(HAVE_WIN32_THREADS)
+#if !defined(HAVE_COMPILER_TLS)
+#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
+ InitializeCriticalSection(&cleanup_helpers_cs);
+#endif
+ globalkey = TlsAlloc();
+#endif
+ mainthread = GetCurrentThreadId();
#endif
}
/**
* xmlCleanupThreads:
*
- * DEPRECATED: This function will be made private. Call xmlCleanupParser
+ * DEPRECATED: This function is a no-op. Call xmlCleanupParser
* to free global state but see the warnings there. xmlCleanupParser
* should be only called once at program exit. In most cases, you don't
* have call cleanup functions at all.
- *
- * 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)
{
-#ifdef DEBUG_THREADS
- xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n");
-#endif
+}
+
+/**
+ * xmlCleanupThreadsInternal:
+ *
+ * Used to to cleanup all the thread related data.
+ */
+void
+xmlCleanupThreadsInternal(void)
+{
#ifdef HAVE_POSIX_THREADS
- if (libxml_is_threaded != 0)
- pthread_key_delete(globalkey);
- once_control = once_control_init;
+#ifdef XML_PTHREAD_WEAK
+ if (libxml_is_threaded == 0)
+ return;
+#endif /* XML_PTHREAD_WEAK */
+ pthread_key_delete(globalkey);
#elif defined(HAVE_WIN32_THREADS)
#if !defined(HAVE_COMPILER_TLS)
if (globalkey != TLS_OUT_OF_INDEXES) {
@@ -803,51 +838,8 @@ xmlCleanupThreads(void)
DeleteCriticalSection(&cleanup_helpers_cs);
#endif
#endif
- run_once.done = 0;
- run_once.control = 0;
-#endif
-}
-
-#ifdef LIBXML_THREAD_ENABLED
-
-/**
- * xmlOnceInit
- *
- * xmlOnceInit() is used to initialize the value of mainthread for use
- * in other routines. This function should only be called using
- * pthread_once() in association with the once_control variable to ensure
- * that the function is only called once. See man pthread_once for more
- * details.
- */
-static void
-xmlOnceInit(void)
-{
-#ifdef HAVE_POSIX_THREADS
- (void) pthread_key_create(&globalkey, xmlFreeGlobalState);
- mainthread = pthread_self();
- __xmlInitializeDict();
-#elif defined(HAVE_WIN32_THREADS)
- if (!run_once.done) {
- if (InterlockedIncrement(&run_once.control) == 1) {
-#if !defined(HAVE_COMPILER_TLS)
-#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
- InitializeCriticalSection(&cleanup_helpers_cs);
-#endif
- globalkey = TlsAlloc();
-#endif
- mainthread = GetCurrentThreadId();
- __xmlInitializeDict();
- run_once.done = 1;
- } else {
- /* Another thread is working; give up our slice and
- * wait until they're done. */
- while (!run_once.done)
- Sleep(0);
- }
- }
#endif
}
-#endif
/**
* DllMain:
@@ -863,7 +855,7 @@ xmlOnceInit(void)
#ifdef HAVE_POSIX_THREADS
#elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
#if defined(LIBXML_STATIC_FOR_DLL)
-int XMLCALL
+int
xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
ATTRIBUTE_UNUSED void *lpvReserved)
#else