1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-02-04 01:47:02 +03:00

globals: Use thread-local storage if available

Also use thread-local storage to store globals on POSIX platforms.

Most importantly, this makes sure that global variable access can't fail
when allocating the global state struct.
This commit is contained in:
Nick Wellnhofer 2023-09-19 13:17:00 +02:00
parent e7b6ca156f
commit b173b724d1
4 changed files with 40 additions and 38 deletions

View File

@ -43,6 +43,8 @@ static xmlMutex xmlThrDefMutex;
type gs_##name;
struct _xmlGlobalState {
int initialized;
#if defined(HAVE_WIN32_THREADS) && \
defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
void *threadHandle;
@ -54,6 +56,12 @@ XML_GLOBALS
#undef XML_OP
};
#ifdef LIBXML_THREAD_ENABLED
#ifdef XML_THREAD_LOCAL
static XML_THREAD_LOCAL xmlGlobalState globalState;
#endif
#ifdef HAVE_POSIX_THREADS
/*
@ -73,23 +81,16 @@ static pthread_key_t globalkey;
#elif defined HAVE_WIN32_THREADS
#if defined(HAVE_COMPILER_TLS)
static __declspec(thread) xmlGlobalState tlstate;
static __declspec(thread) int tlstate_inited = 0;
#else /* HAVE_COMPILER_TLS */
#ifndef XML_THREAD_LOCAL
static DWORD globalkey = TLS_OUT_OF_INDEXES;
#endif /* HAVE_COMPILER_TLS */
#endif
#endif /* HAVE_WIN32_THREADS */
#ifdef LIBXML_THREAD_ENABLED
static void
xmlFreeGlobalState(void *state);
#endif
#endif /* LIBXML_THREAD_ENABLED */
/************************************************************************
* *
@ -522,7 +523,7 @@ void xmlInitGlobalsInternal(void) {
#endif /* XML_PTHREAD_WEAK */
pthread_key_create(&globalkey, xmlFreeGlobalState);
#elif defined(HAVE_WIN32_THREADS)
#if !defined(HAVE_COMPILER_TLS)
#ifndef XML_THREAD_LOCAL
globalkey = TlsAlloc();
#endif
#endif
@ -556,7 +557,7 @@ void xmlCleanupGlobalsInternal(void) {
#endif /* XML_PTHREAD_WEAK */
pthread_key_delete(globalkey);
#elif defined(HAVE_WIN32_THREADS)
#if !defined(HAVE_COMPILER_TLS)
#ifndef XML_THREAD_LOCAL
if (globalkey != TLS_OUT_OF_INDEXES) {
TlsFree(globalkey);
globalkey = TLS_OUT_OF_INDEXES;
@ -602,7 +603,7 @@ xmlFreeGlobalState(void *state)
/* free any memory allocated in the thread's xmlLastError */
xmlResetError(&(gs->gs_xmlLastError));
#if !defined(HAVE_WIN32_THREADS) || !defined(HAVE_COMPILER_TLS)
#ifndef XML_THREAD_LOCAL
free(state);
#endif
}
@ -699,15 +700,18 @@ xmlInitGlobalState(xmlGlobalStatePtr gs) {
#ifdef HAVE_POSIX_THREADS
pthread_setspecific(globalkey, gs);
#elif defined HAVE_WIN32_THREADS
#ifndef HAVE_COMPILER_TLS
#ifndef XML_THREAD_LOCAL
TlsSetValue(globalkey, gs);
#endif
#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
xmlRegisterGlobalStateDtor(gs);
#endif
#endif
gs->initialized = 1;
}
#ifndef XML_THREAD_LOCAL
/**
* xmlNewGlobalState:
*
@ -730,32 +734,29 @@ xmlNewGlobalState(void)
xmlInitGlobalState(gs);
return (gs);
}
#endif
static xmlGlobalStatePtr
xmlGetThreadLocalStorage(void) {
#ifdef HAVE_POSIX_THREADS
xmlGlobalState *gs;
#ifdef XML_THREAD_LOCAL
gs = &globalState;
if (gs->initialized == 0)
xmlInitGlobalState(gs);
#elif defined(HAVE_POSIX_THREADS)
gs = (xmlGlobalState *) pthread_getspecific(globalkey);
if (gs == NULL)
gs = xmlNewGlobalState();
return (gs);
#elif defined HAVE_WIN32_THREADS
#if defined(HAVE_COMPILER_TLS)
if (!tlstate_inited) {
tlstate_inited = 1;
xmlInitGlobalState(&tlstate);
}
return &tlstate;
#else /* HAVE_COMPILER_TLS */
xmlGlobalState *gs;
#elif defined(HAVE_WIN32_THREADS)
gs = (xmlGlobalState *) TlsGetValue(globalkey);
if (gs == NULL)
gs = xmlNewGlobalState();
return (gs);
#endif /* HAVE_COMPILER_TLS */
#else
return (NULL);
gs = NULL;
#endif
return(gs);
}
#endif /* LIBXML_THREAD_ENABLED */
@ -779,7 +780,7 @@ xmlGetThreadLocalStorage(void) {
*/
int
xmlCheckThreadLocalStorage(void) {
#ifdef LIBXML_THREAD_ENABLED
#if defined(LIBXML_THREAD_ENABLED) && !defined(XML_THREAD_LOCAL_STORAGE)
if ((!xmlIsMainThread()) && (xmlGetThreadLocalStorage() == NULL))
return(-1);
#endif
@ -821,6 +822,9 @@ DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
{
switch (fdwReason) {
case DLL_THREAD_DETACH:
#ifdef XML_THREAD_LOCAL
xmlFreeGlobalState(&globalState);
#else
if (globalkey != TLS_OUT_OF_INDEXES) {
xmlGlobalState *globalval;
@ -830,6 +834,7 @@ DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
TlsSetValue(globalkey, NULL);
}
}
#endif
break;
}
return TRUE;

View File

@ -57,8 +57,8 @@ CFLAGS = $(CFLAGS) -D_REENTRANT -tWM
!if "$(DYNRUNTIME)" == "1"
CFLAGS = $(CFLAGS) -tWR
!endif
!if "$(WITH_THREADS)" == "yes" || "$(WITH_THREADS)" == "ctls"
CFLAGS = $(CFLAGS) -DHAVE_COMPILER_TLS
!if "$(WITH_THREADS)" == "ctls"
CFLAGS = $(CFLAGS) "-DXML_THREAD_LOCAL=__declspec(thread)"
!else if "$(WITH_THREADS)" == "posix"
CFLAGS = $(CFLAGS) -DHAVE_PTHREAD_H
!endif

View File

@ -45,11 +45,8 @@ CFLAGS += -I$(XML_SRCDIR) -I$(XML_SRCDIR)/include -I$(INCPREFIX) $(INCLUDE)
ifneq ($(WITH_THREADS),no)
CFLAGS += -D_REENTRANT
endif
ifeq ($(WITH_THREADS),yes)
CFLAGS += -DHAVE_COMPILER_TLS
endif
ifeq ($(WITH_THREADS),ctls)
CFLAGS += -DHAVE_COMPILER_TLS
CFLAGS += "-DXML_THREAD_LOCAL=__declspec(thread)"
endif
ifeq ($(WITH_THREADS),posix)
CFLAGS += -DHAVE_PTHREAD_H

View File

@ -48,8 +48,8 @@ CFLAGS = $(CFLAGS) /I$(XML_SRCDIR) /I$(XML_SRCDIR)\include /I$(INCPREFIX)
!if "$(WITH_THREADS)" != "no"
CFLAGS = $(CFLAGS) /D "_REENTRANT"
!endif
!if "$(WITH_THREADS)" == "yes" || "$(WITH_THREADS)" == "ctls"
CFLAGS = $(CFLAGS) /D "HAVE_COMPILER_TLS"
!if "$(WITH_THREADS)" == "ctls"
CFLAGS = $(CFLAGS) /D "XML_THREAD_LOCAL=__declspec(thread)"
!else if "$(WITH_THREADS)" == "posix"
CFLAGS = $(CFLAGS) /D "HAVE_PTHREAD_H"
!endif