mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-26 00:37:43 +03:00
threads: Rework initialization
Make init/cleanup functions private. Merge xmlOnceInit into xmlInitThreadsInternal.
This commit is contained in:
@@ -5,4 +5,7 @@ void __xmlGlobalInitMutexLock(void);
|
|||||||
void __xmlGlobalInitMutexUnlock(void);
|
void __xmlGlobalInitMutexUnlock(void);
|
||||||
void __xmlGlobalInitMutexDestroy(void);
|
void __xmlGlobalInitMutexDestroy(void);
|
||||||
|
|
||||||
|
void xmlInitThreadsInternal(void);
|
||||||
|
void xmlCleanupThreadsInternal(void);
|
||||||
|
|
||||||
#endif /* XML_THREADS_H_PRIVATE__ */
|
#endif /* XML_THREADS_H_PRIVATE__ */
|
||||||
|
|||||||
4
parser.c
4
parser.c
@@ -14495,7 +14495,7 @@ xmlInitParser(void) {
|
|||||||
__xmlGlobalInitMutexLock();
|
__xmlGlobalInitMutexLock();
|
||||||
if (xmlParserInitialized == 0) {
|
if (xmlParserInitialized == 0) {
|
||||||
#endif
|
#endif
|
||||||
xmlInitThreads();
|
xmlInitThreadsInternal();
|
||||||
xmlInitGlobalsInternal();
|
xmlInitGlobalsInternal();
|
||||||
xmlInitMemoryInternal();
|
xmlInitMemoryInternal();
|
||||||
xmlInitializeDict();
|
xmlInitializeDict();
|
||||||
@@ -14555,7 +14555,7 @@ xmlCleanupParser(void) {
|
|||||||
xmlRelaxNGCleanupTypes();
|
xmlRelaxNGCleanupTypes();
|
||||||
#endif
|
#endif
|
||||||
xmlCleanupGlobalsInternal();
|
xmlCleanupGlobalsInternal();
|
||||||
xmlCleanupThreads(); /* must be last if called not from the main thread */
|
xmlCleanupThreadsInternal();
|
||||||
xmlCleanupMemoryInternal();
|
xmlCleanupMemoryInternal();
|
||||||
xmlParserInitialized = 0;
|
xmlParserInitialized = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
124
threads.c
124
threads.c
@@ -47,7 +47,6 @@ static int libxml_is_threaded = -1;
|
|||||||
|
|
||||||
#define XML_PTHREAD_WEAK
|
#define XML_PTHREAD_WEAK
|
||||||
|
|
||||||
#pragma weak pthread_once
|
|
||||||
#pragma weak pthread_getspecific
|
#pragma weak pthread_getspecific
|
||||||
#pragma weak pthread_setspecific
|
#pragma weak pthread_setspecific
|
||||||
#pragma weak pthread_key_create
|
#pragma weak pthread_key_create
|
||||||
@@ -118,8 +117,6 @@ struct _xmlRMutex {
|
|||||||
#ifdef HAVE_POSIX_THREADS
|
#ifdef HAVE_POSIX_THREADS
|
||||||
static pthread_key_t globalkey;
|
static pthread_key_t globalkey;
|
||||||
static pthread_t mainthread;
|
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;
|
static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
#elif defined HAVE_WIN32_THREADS
|
#elif defined HAVE_WIN32_THREADS
|
||||||
#if defined(HAVE_COMPILER_TLS)
|
#if defined(HAVE_COMPILER_TLS)
|
||||||
@@ -129,19 +126,11 @@ static __declspec(thread) int tlstate_inited = 0;
|
|||||||
static DWORD globalkey = TLS_OUT_OF_INDEXES;
|
static DWORD globalkey = TLS_OUT_OF_INDEXES;
|
||||||
#endif /* HAVE_COMPILER_TLS */
|
#endif /* HAVE_COMPILER_TLS */
|
||||||
static DWORD mainthread;
|
static DWORD mainthread;
|
||||||
static struct {
|
|
||||||
DWORD done;
|
|
||||||
LONG control;
|
|
||||||
} run_once = { 0, 0};
|
|
||||||
static volatile LPCRITICAL_SECTION global_init_lock = NULL;
|
static volatile LPCRITICAL_SECTION global_init_lock = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static xmlRMutexPtr xmlLibraryLock = NULL;
|
static xmlRMutexPtr xmlLibraryLock = NULL;
|
||||||
|
|
||||||
#ifdef LIBXML_THREAD_ENABLED
|
|
||||||
static void xmlOnceInit(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlNewMutex:
|
* xmlNewMutex:
|
||||||
*
|
*
|
||||||
@@ -538,8 +527,6 @@ xmlGetGlobalState(void)
|
|||||||
if (libxml_is_threaded == 0)
|
if (libxml_is_threaded == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
pthread_once(&once_control, xmlOnceInit);
|
|
||||||
|
|
||||||
if ((globalval = (xmlGlobalState *)
|
if ((globalval = (xmlGlobalState *)
|
||||||
pthread_getspecific(globalkey)) == NULL) {
|
pthread_getspecific(globalkey)) == NULL) {
|
||||||
xmlGlobalState *tsd = xmlNewGlobalState();
|
xmlGlobalState *tsd = xmlNewGlobalState();
|
||||||
@@ -560,8 +547,6 @@ xmlGetGlobalState(void)
|
|||||||
#else /* HAVE_COMPILER_TLS */
|
#else /* HAVE_COMPILER_TLS */
|
||||||
xmlGlobalState *globalval;
|
xmlGlobalState *globalval;
|
||||||
xmlGlobalStateCleanupHelperParams *p;
|
xmlGlobalStateCleanupHelperParams *p;
|
||||||
|
|
||||||
xmlOnceInit();
|
|
||||||
#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
|
#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
|
||||||
globalval = (xmlGlobalState *) TlsGetValue(globalkey);
|
globalval = (xmlGlobalState *) TlsGetValue(globalkey);
|
||||||
#else
|
#else
|
||||||
@@ -654,14 +639,10 @@ xmlGetThreadId(void)
|
|||||||
int
|
int
|
||||||
xmlIsMainThread(void)
|
xmlIsMainThread(void)
|
||||||
{
|
{
|
||||||
|
xmlInitParser();
|
||||||
#ifdef HAVE_POSIX_THREADS
|
#ifdef HAVE_POSIX_THREADS
|
||||||
if (libxml_is_threaded == -1)
|
|
||||||
xmlInitThreads();
|
|
||||||
if (libxml_is_threaded == 0)
|
if (libxml_is_threaded == 0)
|
||||||
return (1);
|
return (1);
|
||||||
pthread_once(&once_control, xmlOnceInit);
|
|
||||||
#elif defined HAVE_WIN32_THREADS
|
|
||||||
xmlOnceInit();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_THREADS
|
#ifdef DEBUG_THREADS
|
||||||
@@ -709,20 +690,26 @@ xmlUnlockLibrary(void)
|
|||||||
/**
|
/**
|
||||||
* xmlInitThreads:
|
* xmlInitThreads:
|
||||||
*
|
*
|
||||||
* DEPRECATED: This function will be made private. Call xmlInitParser to
|
* DEPRECATED: Alias for xmlInitParser.
|
||||||
* initialize the library.
|
|
||||||
*
|
|
||||||
* xmlInitThreads() is used to to initialize all the thread related
|
|
||||||
* data of the libxml2 library.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xmlInitThreads(void)
|
xmlInitThreads(void)
|
||||||
|
{
|
||||||
|
xmlInitParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlInitThreadsInternal:
|
||||||
|
*
|
||||||
|
* Used to to initialize all the thread related data.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlInitThreadsInternal(void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_POSIX_THREADS
|
#ifdef HAVE_POSIX_THREADS
|
||||||
#ifdef XML_PTHREAD_WEAK
|
#ifdef XML_PTHREAD_WEAK
|
||||||
if (libxml_is_threaded == -1) {
|
if (libxml_is_threaded == -1) {
|
||||||
if ((pthread_once != NULL) &&
|
if ((pthread_getspecific != NULL) &&
|
||||||
(pthread_getspecific != NULL) &&
|
|
||||||
(pthread_setspecific != NULL) &&
|
(pthread_setspecific != NULL) &&
|
||||||
(pthread_key_create != NULL) &&
|
(pthread_key_create != NULL) &&
|
||||||
(pthread_key_delete != NULL) &&
|
(pthread_key_delete != NULL) &&
|
||||||
@@ -750,38 +737,42 @@ xmlInitThreads(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* XML_PTHREAD_WEAK */
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlCleanupThreads:
|
* 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
|
* to free global state but see the warnings there. xmlCleanupParser
|
||||||
* should be only called once at program exit. In most cases, you don't
|
* should be only called once at program exit. In most cases, you don't
|
||||||
* have call cleanup functions at all.
|
* 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
|
void
|
||||||
xmlCleanupThreads(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
|
#ifdef HAVE_POSIX_THREADS
|
||||||
if (libxml_is_threaded != 0)
|
pthread_key_delete(globalkey);
|
||||||
pthread_key_delete(globalkey);
|
|
||||||
once_control = once_control_init;
|
|
||||||
#elif defined(HAVE_WIN32_THREADS)
|
#elif defined(HAVE_WIN32_THREADS)
|
||||||
#if !defined(HAVE_COMPILER_TLS)
|
#if !defined(HAVE_COMPILER_TLS)
|
||||||
if (globalkey != TLS_OUT_OF_INDEXES) {
|
if (globalkey != TLS_OUT_OF_INDEXES) {
|
||||||
@@ -807,52 +798,9 @@ xmlCleanupThreads(void)
|
|||||||
DeleteCriticalSection(&cleanup_helpers_cs);
|
DeleteCriticalSection(&cleanup_helpers_cs);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
run_once.done = 0;
|
|
||||||
run_once.control = 0;
|
|
||||||
#endif
|
#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:
|
* DllMain:
|
||||||
* @hinstDLL: handle to DLL instance
|
* @hinstDLL: handle to DLL instance
|
||||||
|
|||||||
Reference in New Issue
Block a user