2001-10-12 17:29:10 +00:00
/**
2008-04-11 12:58:43 +00:00
* threads . c : set of generic threading related routines
2001-10-12 17:29:10 +00:00
*
* See Copyright for the status of this software .
*
* Gary Pennington < Gary . Pennington @ uk . sun . com >
* daniel @ veillard . com
*/
2002-03-18 19:37:11 +00:00
# define IN_LIBXML
2001-10-12 17:29:10 +00:00
# include "libxml.h"
# include <string.h>
# include <libxml/threads.h>
# include <libxml/globals.h>
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
# ifdef HAVE_PTHREAD_H
# include <pthread.h>
2009-10-01 00:13:07 +02:00
# elif defined HAVE_WIN32_THREADS
2017-10-09 00:20:01 +02:00
# define WIN32_LEAN_AND_MEAN
2002-01-13 13:35:00 +00:00
# include <windows.h>
2002-10-31 15:58:42 +00:00
# ifndef HAVE_COMPILER_TLS
2002-01-13 13:35:00 +00:00
# include <process.h>
# endif
# endif
2001-10-12 17:29:10 +00:00
2003-10-29 13:39:15 +00:00
# ifdef HAVE_BEOS_THREADS
# include <OS.h>
# include <TLS.h>
# endif
2001-10-12 17:29:10 +00:00
# if defined(SOLARIS)
# include <note.h>
# endif
2001-10-14 09:56:15 +00:00
/* #define DEBUG_THREADS */
2001-10-12 17:29:10 +00:00
2005-05-04 09:18:00 +00:00
# ifdef HAVE_PTHREAD_H
static int libxml_is_threaded = - 1 ;
2014-12-22 11:12:12 +08:00
# if defined(__GNUC__) && defined(__GLIBC__)
2017-09-14 21:30:51 +02:00
# ifdef __linux__
2005-05-04 09:18:00 +00:00
# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ > 3)
2017-06-17 15:05:34 +02:00
# pragma weak pthread_once
# pragma weak pthread_getspecific
# pragma weak pthread_setspecific
# pragma weak pthread_key_create
# pragma weak pthread_key_delete
# pragma weak pthread_mutex_init
# pragma weak pthread_mutex_destroy
# pragma weak pthread_mutex_lock
# pragma weak pthread_mutex_unlock
# pragma weak pthread_cond_init
# pragma weak pthread_cond_destroy
# pragma weak pthread_cond_wait
# pragma weak pthread_equal
# pragma weak pthread_self
# pragma weak pthread_key_create
# pragma weak pthread_key_delete
# pragma weak pthread_cond_signal
2005-05-04 09:18:00 +00:00
# endif
2017-09-14 21:30:51 +02:00
# endif /* __linux__ */
2014-12-22 11:12:12 +08:00
# endif /* defined(__GNUC__) && defined(__GLIBC__) */
2005-05-04 09:18:00 +00:00
# endif /* HAVE_PTHREAD_H */
2001-10-12 17:29:10 +00:00
/*
* TODO : this module still uses malloc / free and not xmlMalloc / xmlFree
* to avoid some crazyness since xmlMalloc / xmlFree may actually
* be hosted on allocated blocks needing them for the allocation . . .
*/
/*
* xmlMutex are a simple mutual exception locks
*/
struct _xmlMutex {
# ifdef HAVE_PTHREAD_H
pthread_mutex_t lock ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
HANDLE mutex ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
sem_id sem ;
thread_id tid ;
2001-10-12 17:29:10 +00:00
# else
int empty ;
# endif
} ;
/*
* xmlRMutex are reentrant mutual exception locks
*/
struct _xmlRMutex {
# ifdef HAVE_PTHREAD_H
pthread_mutex_t lock ;
2008-03-18 08:24:25 +00:00
unsigned int held ;
unsigned int waiters ;
pthread_t tid ;
pthread_cond_t cv ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
CRITICAL_SECTION cs ;
unsigned int count ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
xmlMutexPtr lock ;
thread_id tid ;
int32 count ;
2001-10-12 17:29:10 +00:00
# else
int empty ;
# endif
} ;
2008-03-18 08:24:25 +00:00
2001-10-12 17:29:10 +00:00
/*
* This module still has some internal static data .
* - xmlLibraryLock a global lock
* - globalkey used for per - thread data
*/
2001-10-14 09:56:15 +00:00
2001-10-12 17:29:10 +00:00
# ifdef HAVE_PTHREAD_H
2008-03-18 08:24:25 +00:00
static pthread_key_t globalkey ;
static pthread_t mainthread ;
2001-12-06 14:08:31 +00:00
static pthread_once_t once_control = PTHREAD_ONCE_INIT ;
2012-09-12 17:34:53 +02:00
static pthread_once_t once_control_init = PTHREAD_ONCE_INIT ;
2007-02-12 17:31:53 +00:00
static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
# if defined(HAVE_COMPILER_TLS)
static __declspec ( thread ) xmlGlobalState tlstate ;
static __declspec ( thread ) int tlstate_inited = 0 ;
# else /* HAVE_COMPILER_TLS */
2003-05-17 10:55:15 +00:00
static DWORD globalkey = TLS_OUT_OF_INDEXES ;
2002-10-31 15:58:42 +00:00
# endif /* HAVE_COMPILER_TLS */
2002-01-13 13:35:00 +00:00
static DWORD mainthread ;
2008-03-18 08:24:25 +00:00
static struct {
2005-02-25 07:31:49 +00:00
DWORD done ;
2017-10-09 16:50:57 +02:00
LONG control ;
2008-03-18 08:24:25 +00:00
} run_once = { 0 , 0 } ;
2007-02-12 17:31:53 +00:00
static volatile LPCRITICAL_SECTION global_init_lock = NULL ;
2008-03-18 08:24:25 +00:00
2003-10-29 13:39:15 +00:00
/* endif HAVE_WIN32_THREADS */
# elif defined HAVE_BEOS_THREADS
int32 globalkey = 0 ;
thread_id mainthread = 0 ;
int32 run_once_init = 0 ;
2007-02-12 17:31:53 +00:00
static int32 global_init_lock = - 1 ;
static vint32 global_init_count = 0 ;
2003-10-29 13:39:15 +00:00
# endif
2002-10-31 15:58:42 +00:00
2008-03-18 08:24:25 +00:00
static xmlRMutexPtr xmlLibraryLock = NULL ;
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_THREAD_ENABLED
2001-12-06 14:08:31 +00:00
static void xmlOnceInit ( void ) ;
2003-09-29 13:20:24 +00:00
# endif
2001-10-12 17:29:10 +00:00
/**
2002-12-10 15:19:08 +00:00
* xmlNewMutex :
2001-10-12 17:29:10 +00:00
*
* xmlNewMutex ( ) is used to allocate a libxml2 token struct for use in
* synchronizing access to data .
*
* Returns a new simple mutex pointer or NULL in case of error
*/
xmlMutexPtr
xmlNewMutex ( void )
{
xmlMutexPtr tok ;
if ( ( tok = malloc ( sizeof ( xmlMutex ) ) ) = = NULL )
return ( NULL ) ;
# ifdef HAVE_PTHREAD_H
2005-05-04 09:18:00 +00:00
if ( libxml_is_threaded ! = 0 )
2008-03-18 08:24:25 +00:00
pthread_mutex_init ( & tok - > lock , NULL ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
tok - > mutex = CreateMutex ( NULL , FALSE , NULL ) ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
if ( ( tok - > sem = create_sem ( 1 , " xmlMutex " ) ) < B_OK ) {
free ( tok ) ;
return NULL ;
}
tok - > tid = - 1 ;
2001-10-12 17:29:10 +00:00
# endif
return ( tok ) ;
}
/**
* xmlFreeMutex :
* @ tok : the simple mutex
*
* xmlFreeMutex ( ) is used to reclaim resources associated with a libxml2 token
* struct .
*/
void
xmlFreeMutex ( xmlMutexPtr tok )
{
2008-03-18 08:24:25 +00:00
if ( tok = = NULL )
return ;
2003-07-08 14:03:36 +00:00
2001-10-12 17:29:10 +00:00
# ifdef HAVE_PTHREAD_H
2005-05-04 09:18:00 +00:00
if ( libxml_is_threaded ! = 0 )
2008-03-18 08:24:25 +00:00
pthread_mutex_destroy ( & tok - > lock ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
CloseHandle ( tok - > mutex ) ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
delete_sem ( tok - > sem ) ;
2001-10-12 17:29:10 +00:00
# endif
free ( tok ) ;
}
/**
* xmlMutexLock :
* @ tok : the simple mutex
*
* xmlMutexLock ( ) is used to lock a libxml2 token .
*/
void
2003-08-08 14:00:28 +00:00
xmlMutexLock ( xmlMutexPtr tok )
2001-10-12 17:29:10 +00:00
{
2003-08-08 14:00:28 +00:00
if ( tok = = NULL )
return ;
2001-10-12 17:29:10 +00:00
# ifdef HAVE_PTHREAD_H
2005-05-04 09:18:00 +00:00
if ( libxml_is_threaded ! = 0 )
2008-03-18 08:24:25 +00:00
pthread_mutex_lock ( & tok - > lock ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
WaitForSingleObject ( tok - > mutex , INFINITE ) ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
if ( acquire_sem ( tok - > sem ) ! = B_NO_ERROR ) {
2003-10-29 13:39:15 +00:00
# ifdef DEBUG_THREADS
2008-03-18 08:24:25 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" xmlMutexLock():BeOS:Couldn't aquire semaphore \n " ) ;
2003-10-29 13:39:15 +00:00
# endif
2008-03-18 08:24:25 +00:00
}
tok - > tid = find_thread ( NULL ) ;
2001-10-12 17:29:10 +00:00
# endif
}
/**
* xmlMutexUnlock :
* @ tok : the simple mutex
*
* xmlMutexUnlock ( ) is used to unlock a libxml2 token .
*/
void
2003-08-28 08:03:23 +00:00
xmlMutexUnlock ( xmlMutexPtr tok )
2001-10-12 17:29:10 +00:00
{
2003-08-28 08:03:23 +00:00
if ( tok = = NULL )
return ;
2001-10-12 17:29:10 +00:00
# ifdef HAVE_PTHREAD_H
2005-05-04 09:18:00 +00:00
if ( libxml_is_threaded ! = 0 )
2008-03-18 08:24:25 +00:00
pthread_mutex_unlock ( & tok - > lock ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
ReleaseMutex ( tok - > mutex ) ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
if ( tok - > tid = = find_thread ( NULL ) ) {
tok - > tid = - 1 ;
release_sem ( tok - > sem ) ;
}
2001-10-12 17:29:10 +00:00
# endif
}
/**
2002-12-10 15:19:08 +00:00
* xmlNewRMutex :
2001-10-12 17:29:10 +00:00
*
* xmlRNewMutex ( ) is used to allocate a reentrant mutex for use in
* synchronizing access to data . token_r is a re - entrant lock and thus useful
* for synchronizing access to data structures that may be manipulated in a
* recursive fashion .
*
* Returns the new reentrant mutex pointer or NULL in case of error
*/
xmlRMutexPtr
xmlNewRMutex ( void )
{
xmlRMutexPtr tok ;
if ( ( tok = malloc ( sizeof ( xmlRMutex ) ) ) = = NULL )
return ( NULL ) ;
# ifdef HAVE_PTHREAD_H
2005-05-04 09:18:00 +00:00
if ( libxml_is_threaded ! = 0 ) {
2008-03-18 08:24:25 +00:00
pthread_mutex_init ( & tok - > lock , NULL ) ;
tok - > held = 0 ;
tok - > waiters = 0 ;
pthread_cond_init ( & tok - > cv , NULL ) ;
2005-05-04 09:18:00 +00:00
}
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
InitializeCriticalSection ( & tok - > cs ) ;
tok - > count = 0 ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
if ( ( tok - > lock = xmlNewMutex ( ) ) = = NULL ) {
free ( tok ) ;
return NULL ;
}
tok - > count = 0 ;
2001-10-12 17:29:10 +00:00
# endif
return ( tok ) ;
}
/**
2002-12-10 15:19:08 +00:00
* xmlFreeRMutex :
2001-10-12 17:29:10 +00:00
* @ tok : the reentrant mutex
*
* xmlRFreeMutex ( ) is used to reclaim resources associated with a
* reentrant mutex .
*/
void
2002-02-10 13:20:39 +00:00
xmlFreeRMutex ( xmlRMutexPtr tok ATTRIBUTE_UNUSED )
2001-10-12 17:29:10 +00:00
{
2005-05-04 09:18:00 +00:00
if ( tok = = NULL )
return ;
2001-10-12 17:29:10 +00:00
# ifdef HAVE_PTHREAD_H
2006-06-29 11:50:18 +00:00
if ( libxml_is_threaded ! = 0 ) {
2008-03-18 08:24:25 +00:00
pthread_mutex_destroy ( & tok - > lock ) ;
pthread_cond_destroy ( & tok - > cv ) ;
2006-06-29 11:50:18 +00:00
}
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
DeleteCriticalSection ( & tok - > cs ) ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
xmlFreeMutex ( tok - > lock ) ;
2001-10-12 17:29:10 +00:00
# endif
free ( tok ) ;
}
/**
* xmlRMutexLock :
* @ tok : the reentrant mutex
*
* xmlRMutexLock ( ) is used to lock a libxml2 token_r .
*/
void
2003-09-11 23:35:09 +00:00
xmlRMutexLock ( xmlRMutexPtr tok )
2001-10-12 17:29:10 +00:00
{
2003-09-11 23:35:09 +00:00
if ( tok = = NULL )
return ;
2001-10-12 17:29:10 +00:00
# ifdef HAVE_PTHREAD_H
2005-05-04 09:18:00 +00:00
if ( libxml_is_threaded = = 0 )
return ;
2001-10-12 17:29:10 +00:00
pthread_mutex_lock ( & tok - > lock ) ;
if ( tok - > held ) {
if ( pthread_equal ( tok - > tid , pthread_self ( ) ) ) {
tok - > held + + ;
pthread_mutex_unlock ( & tok - > lock ) ;
return ;
} else {
tok - > waiters + + ;
while ( tok - > held )
pthread_cond_wait ( & tok - > cv , & tok - > lock ) ;
tok - > waiters - - ;
}
}
tok - > tid = pthread_self ( ) ;
tok - > held = 1 ;
pthread_mutex_unlock ( & tok - > lock ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
EnterCriticalSection ( & tok - > cs ) ;
2014-10-13 15:03:58 +08:00
tok - > count + + ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
if ( tok - > lock - > tid = = find_thread ( NULL ) ) {
tok - > count + + ;
return ;
} else {
xmlMutexLock ( tok - > lock ) ;
tok - > count = 1 ;
}
2001-10-12 17:29:10 +00:00
# endif
}
/**
* xmlRMutexUnlock :
* @ tok : the reentrant mutex
*
* xmlRMutexUnlock ( ) is used to unlock a libxml2 token_r .
*/
void
2002-02-10 13:20:39 +00:00
xmlRMutexUnlock ( xmlRMutexPtr tok ATTRIBUTE_UNUSED )
2001-10-12 17:29:10 +00:00
{
2003-09-11 23:35:09 +00:00
if ( tok = = NULL )
return ;
2001-10-12 17:29:10 +00:00
# ifdef HAVE_PTHREAD_H
2005-05-04 09:18:00 +00:00
if ( libxml_is_threaded = = 0 )
return ;
2008-03-18 08:24:25 +00:00
2001-10-12 17:29:10 +00:00
pthread_mutex_lock ( & tok - > lock ) ;
tok - > held - - ;
if ( tok - > held = = 0 ) {
if ( tok - > waiters )
pthread_cond_signal ( & tok - > cv ) ;
2009-09-10 17:46:07 +02:00
memset ( & tok - > tid , 0 , sizeof ( tok - > tid ) ) ;
2001-10-12 17:29:10 +00:00
}
pthread_mutex_unlock ( & tok - > lock ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2014-10-13 15:03:58 +08:00
if ( tok - > count > 0 ) {
tok - > count - - ;
2015-03-03 19:40:06 +08:00
LeaveCriticalSection ( & tok - > cs ) ;
2014-10-13 15:03:58 +08:00
}
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
if ( tok - > lock - > tid = = find_thread ( NULL ) ) {
tok - > count - - ;
if ( tok - > count = = 0 ) {
xmlMutexUnlock ( tok - > lock ) ;
}
return ;
}
2001-10-12 17:29:10 +00:00
# endif
}
2007-02-12 17:31:53 +00:00
/**
* xmlGlobalInitMutexLock
*
* Makes sure that the global initialization mutex is initialized and
* locks it .
*/
void
__xmlGlobalInitMutexLock ( void )
{
/* Make sure the global init lock is initialized and then lock it. */
# ifdef HAVE_PTHREAD_H
/* The mutex is statically initialized, so we just lock it. */
Various "make distcheck" and portability fixups
Makefile.am:
* Don't use @VAR@, use $(VAR). Autoconf's AC_SUBST provides us the Make
variable, it allows overriding the value at the command line, and
(notably) it avoids a Make parse error in the libxml2_la_LDFLAGS
assignment when @MODULE_PLATFORM_LIBS@ is empty
* Changed how the THREADS_W32 mechanism switches the build between
testThreads.c and testThreadsWin32.c as appropriate; using AM_CONDITIONAL
allows this to work cleanly and plays well with dependencies
* testapi.c should be specified as BUILT_SOURCES
* Create symlinks to the test/ and result/ subdirs so that the runtests
target is usable in out-of-source-tree builds
* Don't do MAKEFLAGS+=--silent as this is not portable to non-GNU Makes
* Fixed incorrect find(1) syntax in the "cleanup" rule, and doing "rm -f"
instead of just "rm" is good form
* (DIST)CLEANFILES needed a bit more coverage to allow "make distcheck" to
pass
configure.in:
* Need AC_PROG_LN_S to create test/ and result/ symlinks in Makefile.am
* AC_LIBTOOL_WIN32_DLL and AM_PROG_LIBTOOL are obsolete; these have been
superceded by LT_INIT
* Don't rebuild docs by default, as this requires GNU Make (as
implemented)
* Check for uint32_t as some platforms don't provide it
* Check for some more functions, and undefine HAVE_MMAP if we don't also
HAVE_MUNMAP (one system I tested on actually needed this)
* Changed THREADS_W32 from a filename insert into an Automake conditional
* The "Copyright" file will not be in the current directory if builddir !=
srcdir
doc/Makefile.am:
* EXTRA_DIST cannot use wildcards when they refer to generated files; this
breaks dependencies. What I did was define EXTRA_DIST_wc, which uses GNU
Make $(wildcard) directives to build up a list of files, and EXTRA_DIST,
as a literal expansion of EXTRA_DIST_wc. I also added a new rule,
"check-extra-dist", to simplify checking that the two variables are
equivalent. (Note that this works only when builddir == srcdir)
(I can implement this differently if desired; this is just one way of
doing it)
* Don't define an "all" target; this steps on Automake's toes
* Fixed up the "libxml2-api.xml ..." rule by using $(wildcard) for
dependencies (as Make doesn't process the wildcards otherwise) and
qualifying appropriate files with $(srcdir)
(Note that $(srcdir) is not needed in the dependencies, thanks to VPATH,
which we can count on as this is GNU-Make-only code anyway)
doc/devhelp/Makefile.am:
* Qualified appropriate files with $(srcdir)
* Added an "uninstall-local" rule so that "make distcheck" passes
doc/examples/Makefile.am:
* Rather than use a wildcard that doesn't work, use a substitution that
most Make programs can handle
doc/examples/index.py:
* Do the same here
include/libxml/nanoftp.h:
* Some platforms (e.g. MSVC 6) already #define INVALID_SOCKET:
user@host:/cygdrive/c/Program Files/Microsoft Visual Studio/VC98/\
Include$ grep -R INVALID_SOCKET .
./WINSOCK.H:#define INVALID_SOCKET (SOCKET)(~0)
./WINSOCK2.H:#define INVALID_SOCKET (SOCKET)(~0)
include/libxml/xmlversion.h.in:
* Support ancient GCCs (I was actually able to build the library with 2.5
but for this bit)
python/Makefile.am:
* Expanded CLEANFILES to allow "make distcheck" to pass
python/tests/Makefile.am:
* Define CLEANFILES instead of a "clean" rule, and added tmp.xml to allow
"make distcheck" to pass
testRelax.c:
* Use HAVE_MMAP instead of the less explicit HAVE_SYS_MMAN_H (as some
systems have the header but not the function)
testSchemas.c:
* Use HAVE_MMAP instead of the less explicit HAVE_SYS_MMAN_H
testapi.c:
* Don't use putenv() if it's not available
threads.c:
* This fixes the following build error on Solaris 8:
libtool: compile: cc -DHAVE_CONFIG_H -I. -I./include -I./include \
-D_REENTRANT -D__EXTENSIONS__ -D_REENTRANT -Dsparc -Xa -mt -v \
-xarch=v9 -xcrossfile -xO5 -c threads.c -KPIC -DPIC -o threads.o
"threads.c", line 442: controlling expressions must have scalar type
"threads.c", line 512: controlling expressions must have scalar type
cc: acomp failed for threads.c
*** Error code 1
trio.c:
* Define isascii() if the system doesn't provide it
trio.h:
* The trio library's HAVE_CONFIG_H header is not the same as LibXML2's
HAVE_CONFIG_H header; this change is needed to avoid a double-inclusion
win32/configure.js:
* Added support for the LZMA compression option
win32/Makefile.{bcb,mingw,msvc}:
* Added appropriate bits to support WITH_LZMA=1
* Install the header files under $(INCPREFIX)\libxml2\libxml instead of
$(INCPREFIX)\libxml, to mirror the install location on Unix+Autotools
xml2-config.in:
* @MODULE_PLATFORM_LIBS@ (usually "-ldl") needs to be in there in order for
`xml2-config --libs` to provide a complete set of dependencies
xmllint.c:
* Use HAVE_MMAP instead of the less-explicit HAVE_SYS_MMAN_H
2012-08-06 11:32:54 +08:00
if ( pthread_mutex_lock ! = NULL )
2010-10-15 19:50:03 +02:00
pthread_mutex_lock ( & global_init_lock ) ;
2007-02-12 17:31:53 +00:00
# elif defined HAVE_WIN32_THREADS
LPCRITICAL_SECTION cs ;
/* Create a new critical section */
if ( global_init_lock = = NULL ) {
2008-03-18 08:24:25 +00:00
cs = malloc ( sizeof ( CRITICAL_SECTION ) ) ;
if ( cs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlGlobalInitMutexLock: out of memory \n " ) ;
return ;
}
InitializeCriticalSection ( cs ) ;
2007-02-12 17:31:53 +00:00
2008-03-18 08:24:25 +00:00
/* Swap it into the global_init_lock */
2007-06-08 19:36:04 +00:00
# ifdef InterlockedCompareExchangePointer
2017-10-09 16:50:57 +02:00
InterlockedCompareExchangePointer ( ( void * * ) & global_init_lock ,
cs , NULL ) ;
2008-03-18 08:24:25 +00:00
# else /* Use older void* version */
InterlockedCompareExchange ( ( void * * ) & global_init_lock ,
( void * ) cs , NULL ) ;
2007-06-08 19:36:04 +00:00
# endif /* InterlockedCompareExchangePointer */
2007-02-12 17:31:53 +00:00
2008-03-18 08:24:25 +00:00
/* If another thread successfully recorded its critical
* section in the global_init_lock then discard the one
* allocated by this thread . */
if ( global_init_lock ! = cs ) {
DeleteCriticalSection ( cs ) ;
free ( cs ) ;
}
2007-02-12 17:31:53 +00:00
}
/* Lock the chosen critical section */
EnterCriticalSection ( global_init_lock ) ;
# elif defined HAVE_BEOS_THREADS
int32 sem ;
/* Allocate a new semaphore */
sem = create_sem ( 1 , " xmlGlobalinitMutex " ) ;
while ( global_init_lock = = - 1 ) {
2008-03-18 08:24:25 +00:00
if ( atomic_add ( & global_init_count , 1 ) = = 0 ) {
global_init_lock = sem ;
} else {
snooze ( 1 ) ;
atomic_add ( & global_init_count , - 1 ) ;
}
2007-02-12 17:31:53 +00:00
}
/* If another thread successfully recorded its critical
* section in the global_init_lock then discard the one
* allocated by this thread . */
if ( global_init_lock ! = sem )
2008-03-18 08:24:25 +00:00
delete_sem ( sem ) ;
2007-02-12 17:31:53 +00:00
/* Acquire the chosen semaphore */
if ( acquire_sem ( global_init_lock ) ! = B_NO_ERROR ) {
# ifdef DEBUG_THREADS
2008-03-18 08:24:25 +00:00
xmlGenericError ( xmlGenericErrorContext ,
" xmlGlobalInitMutexLock():BeOS:Couldn't acquire semaphore \n " ) ;
2007-02-12 17:31:53 +00:00
# endif
}
# endif
}
void
__xmlGlobalInitMutexUnlock ( void )
{
# ifdef HAVE_PTHREAD_H
Various "make distcheck" and portability fixups
Makefile.am:
* Don't use @VAR@, use $(VAR). Autoconf's AC_SUBST provides us the Make
variable, it allows overriding the value at the command line, and
(notably) it avoids a Make parse error in the libxml2_la_LDFLAGS
assignment when @MODULE_PLATFORM_LIBS@ is empty
* Changed how the THREADS_W32 mechanism switches the build between
testThreads.c and testThreadsWin32.c as appropriate; using AM_CONDITIONAL
allows this to work cleanly and plays well with dependencies
* testapi.c should be specified as BUILT_SOURCES
* Create symlinks to the test/ and result/ subdirs so that the runtests
target is usable in out-of-source-tree builds
* Don't do MAKEFLAGS+=--silent as this is not portable to non-GNU Makes
* Fixed incorrect find(1) syntax in the "cleanup" rule, and doing "rm -f"
instead of just "rm" is good form
* (DIST)CLEANFILES needed a bit more coverage to allow "make distcheck" to
pass
configure.in:
* Need AC_PROG_LN_S to create test/ and result/ symlinks in Makefile.am
* AC_LIBTOOL_WIN32_DLL and AM_PROG_LIBTOOL are obsolete; these have been
superceded by LT_INIT
* Don't rebuild docs by default, as this requires GNU Make (as
implemented)
* Check for uint32_t as some platforms don't provide it
* Check for some more functions, and undefine HAVE_MMAP if we don't also
HAVE_MUNMAP (one system I tested on actually needed this)
* Changed THREADS_W32 from a filename insert into an Automake conditional
* The "Copyright" file will not be in the current directory if builddir !=
srcdir
doc/Makefile.am:
* EXTRA_DIST cannot use wildcards when they refer to generated files; this
breaks dependencies. What I did was define EXTRA_DIST_wc, which uses GNU
Make $(wildcard) directives to build up a list of files, and EXTRA_DIST,
as a literal expansion of EXTRA_DIST_wc. I also added a new rule,
"check-extra-dist", to simplify checking that the two variables are
equivalent. (Note that this works only when builddir == srcdir)
(I can implement this differently if desired; this is just one way of
doing it)
* Don't define an "all" target; this steps on Automake's toes
* Fixed up the "libxml2-api.xml ..." rule by using $(wildcard) for
dependencies (as Make doesn't process the wildcards otherwise) and
qualifying appropriate files with $(srcdir)
(Note that $(srcdir) is not needed in the dependencies, thanks to VPATH,
which we can count on as this is GNU-Make-only code anyway)
doc/devhelp/Makefile.am:
* Qualified appropriate files with $(srcdir)
* Added an "uninstall-local" rule so that "make distcheck" passes
doc/examples/Makefile.am:
* Rather than use a wildcard that doesn't work, use a substitution that
most Make programs can handle
doc/examples/index.py:
* Do the same here
include/libxml/nanoftp.h:
* Some platforms (e.g. MSVC 6) already #define INVALID_SOCKET:
user@host:/cygdrive/c/Program Files/Microsoft Visual Studio/VC98/\
Include$ grep -R INVALID_SOCKET .
./WINSOCK.H:#define INVALID_SOCKET (SOCKET)(~0)
./WINSOCK2.H:#define INVALID_SOCKET (SOCKET)(~0)
include/libxml/xmlversion.h.in:
* Support ancient GCCs (I was actually able to build the library with 2.5
but for this bit)
python/Makefile.am:
* Expanded CLEANFILES to allow "make distcheck" to pass
python/tests/Makefile.am:
* Define CLEANFILES instead of a "clean" rule, and added tmp.xml to allow
"make distcheck" to pass
testRelax.c:
* Use HAVE_MMAP instead of the less explicit HAVE_SYS_MMAN_H (as some
systems have the header but not the function)
testSchemas.c:
* Use HAVE_MMAP instead of the less explicit HAVE_SYS_MMAN_H
testapi.c:
* Don't use putenv() if it's not available
threads.c:
* This fixes the following build error on Solaris 8:
libtool: compile: cc -DHAVE_CONFIG_H -I. -I./include -I./include \
-D_REENTRANT -D__EXTENSIONS__ -D_REENTRANT -Dsparc -Xa -mt -v \
-xarch=v9 -xcrossfile -xO5 -c threads.c -KPIC -DPIC -o threads.o
"threads.c", line 442: controlling expressions must have scalar type
"threads.c", line 512: controlling expressions must have scalar type
cc: acomp failed for threads.c
*** Error code 1
trio.c:
* Define isascii() if the system doesn't provide it
trio.h:
* The trio library's HAVE_CONFIG_H header is not the same as LibXML2's
HAVE_CONFIG_H header; this change is needed to avoid a double-inclusion
win32/configure.js:
* Added support for the LZMA compression option
win32/Makefile.{bcb,mingw,msvc}:
* Added appropriate bits to support WITH_LZMA=1
* Install the header files under $(INCPREFIX)\libxml2\libxml instead of
$(INCPREFIX)\libxml, to mirror the install location on Unix+Autotools
xml2-config.in:
* @MODULE_PLATFORM_LIBS@ (usually "-ldl") needs to be in there in order for
`xml2-config --libs` to provide a complete set of dependencies
xmllint.c:
* Use HAVE_MMAP instead of the less-explicit HAVE_SYS_MMAN_H
2012-08-06 11:32:54 +08:00
if ( pthread_mutex_unlock ! = NULL )
2010-10-15 19:50:03 +02:00
pthread_mutex_unlock ( & global_init_lock ) ;
2007-02-12 17:31:53 +00:00
# elif defined HAVE_WIN32_THREADS
2008-03-24 11:12:55 +00:00
if ( global_init_lock ! = NULL ) {
LeaveCriticalSection ( global_init_lock ) ;
}
2007-02-12 17:31:53 +00:00
# elif defined HAVE_BEOS_THREADS
release_sem ( global_init_lock ) ;
# endif
}
2007-11-16 10:54:59 +00:00
/**
* xmlGlobalInitMutexDestroy
*
* Makes sure that the global initialization mutex is destroyed before
* application termination .
*/
2008-03-18 08:24:25 +00:00
void
__xmlGlobalInitMutexDestroy ( void )
2007-11-16 10:54:59 +00:00
{
2009-09-10 17:46:07 +02:00
# ifdef HAVE_PTHREAD_H
# elif defined HAVE_WIN32_THREADS
2008-03-18 08:24:25 +00:00
if ( global_init_lock ! = NULL ) {
DeleteCriticalSection ( global_init_lock ) ;
free ( global_init_lock ) ;
global_init_lock = NULL ;
2007-11-16 10:54:59 +00:00
}
# endif
}
2001-10-12 17:29:10 +00:00
/************************************************************************
* *
* Per thread global state handling *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-31 17:52:43 +00:00
# ifdef LIBXML_THREAD_ENABLED
2004-10-22 13:16:10 +00:00
# ifdef xmlLastError
# undef xmlLastError
# endif
2008-03-18 08:24:25 +00:00
2001-10-12 17:29:10 +00:00
/**
* xmlFreeGlobalState :
* @ state : a thread global state
*
* xmlFreeGlobalState ( ) is called when a thread terminates with a non - NULL
* global state . It is is used here to reclaim memory resources .
*/
static void
xmlFreeGlobalState ( void * state )
{
2004-10-22 13:16:10 +00:00
xmlGlobalState * gs = ( xmlGlobalState * ) state ;
/* free any memory allocated in the thread's xmlLastError */
xmlResetError ( & ( gs - > xmlLastError ) ) ;
2001-10-12 17:29:10 +00:00
free ( state ) ;
}
/**
* xmlNewGlobalState :
*
* xmlNewGlobalState ( ) allocates a global state . This structure is used to
* hold all data for use by a thread when supporting backwards compatibility
2001-12-31 16:16:02 +00:00
* of libxml2 to pre - thread - safe behaviour .
2001-10-12 17:29:10 +00:00
*
* Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
*/
static xmlGlobalStatePtr
xmlNewGlobalState ( void )
{
xmlGlobalState * gs ;
2008-03-18 08:24:25 +00:00
2001-10-12 17:29:10 +00:00
gs = malloc ( sizeof ( xmlGlobalState ) ) ;
2008-03-18 08:24:25 +00:00
if ( gs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlGetGlobalState: out of memory \n " ) ;
return ( NULL ) ;
}
2001-10-12 17:29:10 +00:00
2002-11-22 05:07:29 +00:00
memset ( gs , 0 , sizeof ( xmlGlobalState ) ) ;
2001-10-12 17:29:10 +00:00
xmlInitializeGlobalState ( gs ) ;
return ( gs ) ;
}
2001-10-31 17:52:43 +00:00
# endif /* LIBXML_THREAD_ENABLED */
2001-10-12 17:29:10 +00:00
2009-09-10 17:46:07 +02:00
# ifdef HAVE_PTHREAD_H
2009-10-01 00:13:07 +02:00
# elif defined HAVE_WIN32_THREADS
2003-10-07 21:25:12 +00:00
# if !defined(HAVE_COMPILER_TLS)
# if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
2008-03-18 08:24:25 +00:00
typedef struct _xmlGlobalStateCleanupHelperParams {
2002-10-31 15:58:42 +00:00
HANDLE thread ;
void * memory ;
2002-01-13 13:35:00 +00:00
} xmlGlobalStateCleanupHelperParams ;
2008-03-18 08:24:25 +00:00
static void XMLCDECL
xmlGlobalStateCleanupHelper ( void * p )
2002-01-13 13:35:00 +00:00
{
2008-03-18 08:24:25 +00:00
xmlGlobalStateCleanupHelperParams * params =
( xmlGlobalStateCleanupHelperParams * ) p ;
2002-10-31 15:58:42 +00:00
WaitForSingleObject ( params - > thread , INFINITE ) ;
CloseHandle ( params - > thread ) ;
xmlFreeGlobalState ( params - > memory ) ;
free ( params ) ;
_endthread ( ) ;
2002-01-13 13:35:00 +00:00
}
2003-10-07 21:25:12 +00:00
# else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */
2008-03-18 08:24:25 +00:00
typedef struct _xmlGlobalStateCleanupHelperParams {
2003-10-07 21:25:12 +00:00
void * memory ;
2008-03-18 08:24:25 +00:00
struct _xmlGlobalStateCleanupHelperParams * prev ;
struct _xmlGlobalStateCleanupHelperParams * next ;
2003-10-07 21:25:12 +00:00
} xmlGlobalStateCleanupHelperParams ;
2008-03-18 08:24:25 +00:00
static xmlGlobalStateCleanupHelperParams * cleanup_helpers_head = NULL ;
2003-10-07 21:25:12 +00:00
static CRITICAL_SECTION cleanup_helpers_cs ;
# endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */
# endif /* HAVE_COMPILER_TLS */
2002-01-13 13:35:00 +00:00
# endif /* HAVE_WIN32_THREADS */
2003-10-29 13:39:15 +00:00
# if defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
2003-11-18 06:54:40 +00:00
/**
* xmlGlobalStateCleanup :
* @ data : unused parameter
*
* Used for Beos only
*/
2008-03-18 08:24:25 +00:00
void
xmlGlobalStateCleanup ( void * data )
2003-10-29 13:39:15 +00:00
{
2008-03-18 08:24:25 +00:00
void * globalval = tls_get ( globalkey ) ;
if ( globalval ! = NULL )
xmlFreeGlobalState ( globalval ) ;
2003-10-29 13:39:15 +00:00
}
# endif
2002-12-10 15:19:08 +00:00
/**
* xmlGetGlobalState :
*
* xmlGetGlobalState ( ) is called to retrieve the global state for a thread .
*
* Returns the thread global state or NULL in case of error
*/
2001-10-12 17:29:10 +00:00
xmlGlobalStatePtr
xmlGetGlobalState ( void )
{
# ifdef HAVE_PTHREAD_H
xmlGlobalState * globalval ;
2005-05-04 09:18:00 +00:00
if ( libxml_is_threaded = = 0 )
2008-03-18 08:24:25 +00:00
return ( NULL ) ;
2005-05-04 09:18:00 +00:00
2001-12-06 14:08:31 +00:00
pthread_once ( & once_control , xmlOnceInit ) ;
2001-10-12 17:29:10 +00:00
if ( ( globalval = ( xmlGlobalState * )
2008-03-18 08:24:25 +00:00
pthread_getspecific ( globalkey ) ) = = NULL ) {
2001-10-12 17:29:10 +00:00
xmlGlobalState * tsd = xmlNewGlobalState ( ) ;
2008-03-24 11:12:55 +00:00
if ( tsd = = NULL )
return ( NULL ) ;
2001-10-12 17:29:10 +00:00
pthread_setspecific ( globalkey , tsd ) ;
return ( tsd ) ;
2001-10-14 09:56:15 +00:00
}
return ( globalval ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
# if defined(HAVE_COMPILER_TLS)
if ( ! tlstate_inited ) {
2008-03-18 08:24:25 +00:00
tlstate_inited = 1 ;
xmlInitializeGlobalState ( & tlstate ) ;
2002-10-31 15:58:42 +00:00
}
return & tlstate ;
# else /* HAVE_COMPILER_TLS */
xmlGlobalState * globalval ;
2008-03-18 08:24:25 +00:00
xmlGlobalStateCleanupHelperParams * p ;
2002-10-31 15:58:42 +00:00
2005-02-24 15:38:52 +00:00
xmlOnceInit ( ) ;
2003-10-07 21:25:12 +00:00
# if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
2008-03-18 08:24:25 +00:00
globalval = ( xmlGlobalState * ) TlsGetValue ( globalkey ) ;
2003-10-07 21:25:12 +00:00
# else
2008-03-18 08:24:25 +00:00
p = ( xmlGlobalStateCleanupHelperParams * ) TlsGetValue ( globalkey ) ;
globalval = ( xmlGlobalState * ) ( p ? p - > memory : NULL ) ;
2003-10-07 21:25:12 +00:00
# endif
if ( globalval = = NULL ) {
2008-03-18 08:24:25 +00:00
xmlGlobalState * tsd = xmlNewGlobalState ( ) ;
if ( tsd = = NULL )
return ( NULL ) ;
p = ( xmlGlobalStateCleanupHelperParams * )
malloc ( sizeof ( xmlGlobalStateCleanupHelperParams ) ) ;
if ( p = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlGetGlobalState: out of memory \n " ) ;
2009-01-18 14:57:04 +00:00
xmlFreeGlobalState ( tsd ) ;
2008-03-18 08:24:25 +00:00
return ( NULL ) ;
}
p - > memory = tsd ;
2003-10-07 21:25:12 +00:00
# if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
2008-03-18 08:24:25 +00:00
DuplicateHandle ( GetCurrentProcess ( ) , GetCurrentThread ( ) ,
GetCurrentProcess ( ) , & p - > thread , 0 , TRUE ,
DUPLICATE_SAME_ACCESS ) ;
TlsSetValue ( globalkey , tsd ) ;
_beginthread ( xmlGlobalStateCleanupHelper , 0 , p ) ;
2003-10-07 21:25:12 +00:00
# else
2008-03-18 08:24:25 +00:00
EnterCriticalSection ( & cleanup_helpers_cs ) ;
2003-10-07 21:25:12 +00:00
if ( cleanup_helpers_head ! = NULL ) {
cleanup_helpers_head - > prev = p ;
}
2008-03-18 08:24:25 +00:00
p - > next = cleanup_helpers_head ;
p - > prev = NULL ;
cleanup_helpers_head = p ;
TlsSetValue ( globalkey , p ) ;
LeaveCriticalSection ( & cleanup_helpers_cs ) ;
2003-05-17 10:55:15 +00:00
# endif
2002-10-31 15:58:42 +00:00
2008-03-18 08:24:25 +00:00
return ( tsd ) ;
2002-10-31 15:58:42 +00:00
}
return ( globalval ) ;
# endif /* HAVE_COMPILER_TLS */
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
xmlGlobalState * globalval ;
xmlOnceInit ( ) ;
2008-03-24 11:12:55 +00:00
if ( ( globalval = ( xmlGlobalState * ) tls_get ( globalkey ) ) = = NULL ) {
2003-10-29 13:39:15 +00:00
xmlGlobalState * tsd = xmlNewGlobalState ( ) ;
2008-03-24 11:12:55 +00:00
if ( tsd = = NULL )
return ( NULL ) ;
2003-10-29 13:39:15 +00:00
tls_set ( globalkey , tsd ) ;
on_exit_thread ( xmlGlobalStateCleanup , NULL ) ;
return ( tsd ) ;
}
return ( globalval ) ;
2001-10-14 09:56:15 +00:00
# else
2008-03-18 08:24:25 +00:00
return ( NULL ) ;
2001-10-12 17:29:10 +00:00
# endif
}
/************************************************************************
* *
* Library wide thread interfaces *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-17 15:58:35 +00:00
/**
* xmlGetThreadId :
*
* xmlGetThreadId ( ) find the current thread ID number
2009-09-10 17:46:07 +02:00
* 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
2001-10-17 15:58:35 +00:00
*
* Returns the current thread ID number
*/
int
xmlGetThreadId ( void )
{
# ifdef HAVE_PTHREAD_H
2009-09-10 17:46:07 +02:00
pthread_t id ;
int ret ;
2005-05-04 09:18:00 +00:00
if ( libxml_is_threaded = = 0 )
2008-03-18 08:24:25 +00:00
return ( 0 ) ;
2009-09-10 17:46:07 +02:00
id = pthread_self ( ) ;
/* horrible but preserves compat, see warning above */
memcpy ( & ret , & id , sizeof ( ret ) ) ;
return ( ret ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 15:58:42 +00:00
return GetCurrentThreadId ( ) ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
return find_thread ( NULL ) ;
2001-10-17 15:58:35 +00:00
# else
2008-03-18 08:24:25 +00:00
return ( ( int ) 0 ) ;
2001-10-17 15:58:35 +00:00
# endif
}
2001-10-14 09:56:15 +00:00
/**
* xmlIsMainThread :
*
2001-12-31 16:16:02 +00:00
* xmlIsMainThread ( ) check whether the current thread is the main thread .
2001-10-14 09:56:15 +00:00
*
* Returns 1 if the current thread is the main thread , 0 otherwise
*/
int
xmlIsMainThread ( void )
{
2001-12-06 14:08:31 +00:00
# ifdef HAVE_PTHREAD_H
2005-05-04 09:18:00 +00:00
if ( libxml_is_threaded = = - 1 )
xmlInitThreads ( ) ;
if ( libxml_is_threaded = = 0 )
2008-03-18 08:24:25 +00:00
return ( 1 ) ;
2001-12-06 14:08:31 +00:00
pthread_once ( & once_control , xmlOnceInit ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2008-03-18 08:24:25 +00:00
xmlOnceInit ( ) ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2005-02-24 15:38:52 +00:00
xmlOnceInit ( ) ;
2001-12-06 14:08:31 +00:00
# endif
2008-03-18 08:24:25 +00:00
2001-10-14 09:56:15 +00:00
# ifdef DEBUG_THREADS
xmlGenericError ( xmlGenericErrorContext , " xmlIsMainThread() \n " ) ;
# endif
# ifdef HAVE_PTHREAD_H
2009-09-10 17:46:07 +02:00
return ( pthread_equal ( mainthread , pthread_self ( ) ) ) ;
2002-01-13 13:35:00 +00:00
# elif defined HAVE_WIN32_THREADS
2008-03-18 08:24:25 +00:00
return ( mainthread = = GetCurrentThreadId ( ) ) ;
2003-10-29 13:39:15 +00:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
return ( mainthread = = find_thread ( NULL ) ) ;
2001-10-14 09:56:15 +00:00
# else
2008-03-18 08:24:25 +00:00
return ( 1 ) ;
2001-10-14 09:56:15 +00:00
# endif
}
2001-10-12 17:29:10 +00:00
/**
* xmlLockLibrary :
*
* xmlLockLibrary ( ) is used to take out a re - entrant lock on the libxml2
* library .
*/
void
xmlLockLibrary ( void )
{
2001-10-14 09:56:15 +00:00
# ifdef DEBUG_THREADS
xmlGenericError ( xmlGenericErrorContext , " xmlLockLibrary() \n " ) ;
# endif
2001-10-12 17:29:10 +00:00
xmlRMutexLock ( xmlLibraryLock ) ;
}
/**
* xmlUnlockLibrary :
*
* xmlUnlockLibrary ( ) is used to release a re - entrant lock on the libxml2
* library .
*/
void
xmlUnlockLibrary ( void )
{
2001-10-14 09:56:15 +00:00
# ifdef DEBUG_THREADS
xmlGenericError ( xmlGenericErrorContext , " xmlUnlockLibrary() \n " ) ;
# endif
2001-10-12 17:29:10 +00:00
xmlRMutexUnlock ( xmlLibraryLock ) ;
}
/**
* xmlInitThreads :
*
* xmlInitThreads ( ) is used to to initialize all the thread related
* data of the libxml2 library .
*/
void
xmlInitThreads ( void )
{
2005-05-04 09:18:00 +00:00
# ifdef HAVE_PTHREAD_H
if ( libxml_is_threaded = = - 1 ) {
if ( ( pthread_once ! = NULL ) & &
2008-03-18 08:24:25 +00:00
( pthread_getspecific ! = NULL ) & &
( pthread_setspecific ! = NULL ) & &
( pthread_key_create ! = NULL ) & &
2009-01-18 15:41:30 +00:00
( pthread_key_delete ! = NULL ) & &
2008-03-18 08:24:25 +00:00
( pthread_mutex_init ! = NULL ) & &
( pthread_mutex_destroy ! = NULL ) & &
( pthread_mutex_lock ! = NULL ) & &
( pthread_mutex_unlock ! = NULL ) & &
( pthread_cond_init ! = NULL ) & &
2008-08-27 11:45:41 +00:00
( pthread_cond_destroy ! = NULL ) & &
( pthread_cond_wait ! = NULL ) & &
2008-03-18 08:24:25 +00:00
( pthread_equal ! = NULL ) & &
( pthread_self ! = NULL ) & &
( pthread_cond_signal ! = NULL ) ) {
libxml_is_threaded = 1 ;
2005-05-04 09:18:00 +00:00
/* fprintf(stderr, "Running multithreaded\n"); */
2008-03-18 08:24:25 +00:00
} else {
2005-05-04 09:18:00 +00:00
/* fprintf(stderr, "Running without multithread\n"); */
2008-03-18 08:24:25 +00:00
libxml_is_threaded = 0 ;
}
2005-05-04 09:18:00 +00:00
}
2009-09-10 17:46:07 +02:00
# elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
InitializeCriticalSection ( & cleanup_helpers_cs ) ;
2005-05-04 09:18:00 +00:00
# endif
2001-10-12 17:29:10 +00:00
}
/**
* xmlCleanupThreads :
*
* xmlCleanupThreads ( ) is used to to cleanup all the thread related
* data of the libxml2 library once processing has ended .
2009-02-21 09:22:04 +00:00
*
* 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 !
2001-10-12 17:29:10 +00:00
*/
void
xmlCleanupThreads ( void )
{
2001-10-14 09:56:15 +00:00
# ifdef DEBUG_THREADS
xmlGenericError ( xmlGenericErrorContext , " xmlCleanupThreads() \n " ) ;
# endif
2009-09-10 17:46:07 +02:00
# ifdef HAVE_PTHREAD_H
if ( ( libxml_is_threaded ) & & ( pthread_key_delete ! = NULL ) )
pthread_key_delete ( globalkey ) ;
2012-09-12 17:34:53 +02:00
once_control = once_control_init ;
2009-09-10 17:46:07 +02:00
# elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
2003-10-07 21:25:12 +00:00
if ( globalkey ! = TLS_OUT_OF_INDEXES ) {
2008-03-18 08:24:25 +00:00
xmlGlobalStateCleanupHelperParams * p ;
EnterCriticalSection ( & cleanup_helpers_cs ) ;
p = cleanup_helpers_head ;
while ( p ! = NULL ) {
xmlGlobalStateCleanupHelperParams * temp = p ;
p = p - > next ;
xmlFreeGlobalState ( temp - > memory ) ;
free ( temp ) ;
}
cleanup_helpers_head = 0 ;
LeaveCriticalSection ( & cleanup_helpers_cs ) ;
TlsFree ( globalkey ) ;
globalkey = TLS_OUT_OF_INDEXES ;
2003-10-07 21:25:12 +00:00
}
DeleteCriticalSection ( & cleanup_helpers_cs ) ;
# endif
2001-12-06 14:08:31 +00:00
}
2001-10-14 09:56:15 +00:00
2003-09-29 13:20:24 +00:00
# ifdef LIBXML_THREAD_ENABLED
2008-03-18 08:24:25 +00:00
2001-12-06 14:08:31 +00:00
/**
* 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
2008-03-18 08:24:25 +00:00
xmlOnceInit ( void )
{
2001-12-06 14:08:31 +00:00
# ifdef HAVE_PTHREAD_H
2002-10-31 15:58:42 +00:00
( void ) pthread_key_create ( & globalkey , xmlFreeGlobalState ) ;
2001-12-06 14:08:31 +00:00
mainthread = pthread_self ( ) ;
2013-04-05 23:10:41 +08:00
__xmlInitializeDict ( ) ;
2009-09-10 17:46:07 +02:00
# elif defined(HAVE_WIN32_THREADS)
2005-02-24 15:38:52 +00:00
if ( ! run_once . done ) {
2008-03-18 08:24:25 +00:00
if ( InterlockedIncrement ( & run_once . control ) = = 1 ) {
2002-10-31 15:58:42 +00:00
# if !defined(HAVE_COMPILER_TLS)
2005-02-24 15:38:52 +00:00
globalkey = TlsAlloc ( ) ;
2002-10-31 15:58:42 +00:00
# endif
2005-02-24 15:38:52 +00:00
mainthread = GetCurrentThreadId ( ) ;
2013-04-05 23:10:41 +08:00
__xmlInitializeDict ( ) ;
2005-02-24 15:38:52 +00:00
run_once . done = 1 ;
2008-03-18 08:24:25 +00:00
} else {
2005-02-24 15:38:52 +00:00
/* Another thread is working; give up our slice and
* wait until they ' re done . */
while ( ! run_once . done )
Sleep ( 0 ) ;
}
}
2009-10-01 00:13:07 +02:00
# elif defined HAVE_BEOS_THREADS
2008-03-18 08:24:25 +00:00
if ( atomic_add ( & run_once_init , 1 ) = = 0 ) {
globalkey = tls_allocate ( ) ;
tls_set ( globalkey , NULL ) ;
mainthread = find_thread ( NULL ) ;
2013-04-05 23:10:41 +08:00
__xmlInitializeDict ( ) ;
2008-03-18 08:24:25 +00:00
} else
atomic_add ( & run_once_init , - 1 ) ;
2003-10-29 13:39:15 +00:00
# endif
2001-10-12 17:29:10 +00:00
}
2003-09-29 13:20:24 +00:00
# endif
2003-05-17 10:55:15 +00:00
/**
2003-08-15 07:27:40 +00:00
* DllMain :
* @ hinstDLL : handle to DLL instance
* @ fdwReason : Reason code for entry
* @ lpvReserved : generic pointer ( depends upon reason code )
2003-05-17 10:55:15 +00:00
*
* Entry point for Windows library . It is being used to free thread - specific
* storage .
2003-08-15 07:27:40 +00:00
*
* Returns TRUE always
2003-05-17 10:55:15 +00:00
*/
2009-09-10 17:46:07 +02:00
# ifdef HAVE_PTHREAD_H
# elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
2003-10-07 21:25:12 +00:00
# if defined(LIBXML_STATIC_FOR_DLL)
2017-10-21 14:04:20 +02:00
int XMLCALL
xmlDllMain ( ATTRIBUTE_UNUSED void * hinstDLL , unsigned long fdwReason ,
ATTRIBUTE_UNUSED void * lpvReserved )
2003-10-07 21:25:12 +00:00
# else
2017-10-21 14:09:16 +02:00
/* declare to avoid "no previous prototype for 'DllMain'" warning */
/* Note that we do NOT want to include this function declaration in
a public header because it ' s meant to be called by Windows itself ,
not a program that uses this library . This also has to be exported . */
XMLPUBFUN BOOL WINAPI
DllMain ( HINSTANCE hinstDLL ,
DWORD fdwReason ,
LPVOID lpvReserved ) ;
2008-03-18 08:24:25 +00:00
BOOL WINAPI
2017-10-09 16:50:57 +02:00
DllMain ( ATTRIBUTE_UNUSED HINSTANCE hinstDLL , DWORD fdwReason ,
ATTRIBUTE_UNUSED LPVOID lpvReserved )
2003-10-07 21:25:12 +00:00
# endif
2003-05-17 10:55:15 +00:00
{
2008-03-18 08:24:25 +00:00
switch ( fdwReason ) {
case DLL_THREAD_DETACH :
if ( globalkey ! = TLS_OUT_OF_INDEXES ) {
xmlGlobalState * globalval = NULL ;
xmlGlobalStateCleanupHelperParams * p =
( xmlGlobalStateCleanupHelperParams * )
TlsGetValue ( globalkey ) ;
globalval = ( xmlGlobalState * ) ( p ? p - > memory : NULL ) ;
if ( globalval ) {
xmlFreeGlobalState ( globalval ) ;
TlsSetValue ( globalkey , NULL ) ;
}
if ( p ) {
EnterCriticalSection ( & cleanup_helpers_cs ) ;
if ( p = = cleanup_helpers_head )
cleanup_helpers_head = p - > next ;
else
p - > prev - > next = p - > next ;
if ( p - > next ! = NULL )
p - > next - > prev = p - > prev ;
LeaveCriticalSection ( & cleanup_helpers_cs ) ;
free ( p ) ;
}
2003-10-07 21:25:12 +00:00
}
2008-03-18 08:24:25 +00:00
break ;
2003-05-17 10:55:15 +00:00
}
return TRUE ;
}
# endif
2005-04-01 13:11:58 +00:00
# define bottom_threads
# include "elfgcchack.h"