mirror of
				https://gitlab.gnome.org/GNOME/libxml2.git
				synced 2025-10-30 10:45:36 +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; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										122
									
								
								threads.c
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								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