diff options
Diffstat (limited to 'chromium/third_party/libxml/src/threads.c')
-rw-r--r-- | chromium/third_party/libxml/src/threads.c | 332 |
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 |