2001-10-12 21:29:10 +04:00
/**
* threads . c : set of generic threading related routines
*
* See Copyright for the status of this software .
*
* Gary Pennington < Gary . Pennington @ uk . sun . com >
* daniel @ veillard . com
*/
2002-03-18 22:37:11 +03:00
# define IN_LIBXML
2001-10-12 21:29:10 +04: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>
# endif
2002-10-31 18:58:42 +03:00
2002-01-13 16:35:00 +03:00
# ifdef HAVE_WIN32_THREADS
# include <windows.h>
2002-10-31 18:58:42 +03:00
# ifndef HAVE_COMPILER_TLS
2002-01-13 16:35:00 +03:00
# include <process.h>
# endif
# endif
2001-10-12 21:29:10 +04:00
2003-10-29 16:39:15 +03:00
# ifdef HAVE_BEOS_THREADS
# include <OS.h>
# include <TLS.h>
# endif
2001-10-12 21:29:10 +04:00
# if defined(SOLARIS)
# include <note.h>
# endif
2001-10-14 13:56:15 +04:00
/* #define DEBUG_THREADS */
2001-10-12 21:29:10 +04: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 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
HANDLE mutex ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
sem_id sem ;
2003-11-01 20:04:58 +03:00
thread_id tid ;
2001-10-12 21:29:10 +04:00
# else
int empty ;
# endif
} ;
/*
* xmlRMutex are reentrant mutual exception locks
*/
struct _xmlRMutex {
# ifdef HAVE_PTHREAD_H
pthread_mutex_t lock ;
unsigned int held ;
unsigned int waiters ;
pthread_t tid ;
pthread_cond_t cv ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
CRITICAL_SECTION cs ;
unsigned int count ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
xmlMutexPtr lock ;
thread_id tid ;
int32 count ;
2001-10-12 21:29:10 +04:00
# else
int empty ;
# endif
} ;
/*
* This module still has some internal static data .
* - xmlLibraryLock a global lock
* - globalkey used for per - thread data
*/
2001-10-14 13:56:15 +04:00
2001-10-12 21:29:10 +04:00
# ifdef HAVE_PTHREAD_H
static pthread_key_t globalkey ;
2001-10-14 13:56:15 +04:00
static pthread_t mainthread ;
2001-12-06 17:08:31 +03:00
static pthread_once_t once_control = PTHREAD_ONCE_INIT ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03: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 14:55:15 +04:00
static DWORD globalkey = TLS_OUT_OF_INDEXES ;
2002-10-31 18:58:42 +03:00
# endif /* HAVE_COMPILER_TLS */
2002-01-13 16:35:00 +03:00
static DWORD mainthread ;
static int run_once_init = 1 ;
2003-10-29 16:39:15 +03:00
/* endif HAVE_WIN32_THREADS */
# elif defined HAVE_BEOS_THREADS
int32 globalkey = 0 ;
thread_id mainthread = 0 ;
int32 run_once_init = 0 ;
# endif
2002-10-31 18:58:42 +03:00
2001-10-12 21:29:10 +04:00
static xmlRMutexPtr xmlLibraryLock = NULL ;
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_THREAD_ENABLED
2001-12-06 17:08:31 +03:00
static void xmlOnceInit ( void ) ;
2003-09-29 17:20:24 +04:00
# endif
2001-10-12 21:29:10 +04:00
/**
2002-12-10 18:19:08 +03:00
* xmlNewMutex :
2001-10-12 21:29:10 +04: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
pthread_mutex_init ( & tok - > lock , NULL ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
tok - > mutex = CreateMutex ( NULL , FALSE , NULL ) ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
if ( ( tok - > sem = create_sem ( 1 , " xmlMutex " ) ) < B_OK ) {
free ( tok ) ;
return NULL ;
}
2003-11-01 20:04:58 +03:00
tok - > tid = - 1 ;
2001-10-12 21:29:10 +04: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 )
{
2003-07-08 18:03:36 +04:00
if ( tok = = NULL ) return ;
2001-10-12 21:29:10 +04:00
# ifdef HAVE_PTHREAD_H
pthread_mutex_destroy ( & tok - > lock ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
CloseHandle ( tok - > mutex ) ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
delete_sem ( tok - > sem ) ;
2001-10-12 21:29:10 +04:00
# endif
free ( tok ) ;
}
/**
* xmlMutexLock :
* @ tok : the simple mutex
*
* xmlMutexLock ( ) is used to lock a libxml2 token .
*/
void
2003-08-08 18:00:28 +04:00
xmlMutexLock ( xmlMutexPtr tok )
2001-10-12 21:29:10 +04:00
{
2003-08-08 18:00:28 +04:00
if ( tok = = NULL )
return ;
2001-10-12 21:29:10 +04:00
# ifdef HAVE_PTHREAD_H
pthread_mutex_lock ( & tok - > lock ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
WaitForSingleObject ( tok - > mutex , INFINITE ) ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
if ( acquire_sem ( tok - > sem ) ! = B_NO_ERROR ) {
# ifdef DEBUG_THREADS
xmlGenericError ( xmlGenericErrorContext , " xmlMutexLock():BeOS:Couldn't aquire semaphore \n " ) ;
exit ( ) ;
# endif
}
2003-11-01 20:04:58 +03:00
tok - > tid = find_thread ( NULL ) ;
2001-10-12 21:29:10 +04:00
# endif
}
/**
* xmlMutexUnlock :
* @ tok : the simple mutex
*
* xmlMutexUnlock ( ) is used to unlock a libxml2 token .
*/
void
2003-08-28 12:03:23 +04:00
xmlMutexUnlock ( xmlMutexPtr tok )
2001-10-12 21:29:10 +04:00
{
2003-08-28 12:03:23 +04:00
if ( tok = = NULL )
return ;
2001-10-12 21:29:10 +04:00
# ifdef HAVE_PTHREAD_H
pthread_mutex_unlock ( & tok - > lock ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
ReleaseMutex ( tok - > mutex ) ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
2003-11-01 20:04:58 +03:00
if ( tok - > tid = = find_thread ( NULL ) ) {
tok - > tid = - 1 ;
release_sem ( tok - > sem ) ;
}
2001-10-12 21:29:10 +04:00
# endif
}
/**
2002-12-10 18:19:08 +03:00
* xmlNewRMutex :
2001-10-12 21:29:10 +04: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
pthread_mutex_init ( & tok - > lock , NULL ) ;
tok - > held = 0 ;
tok - > waiters = 0 ;
2003-07-04 21:01:59 +04:00
pthread_cond_init ( & tok - > cv , NULL ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
InitializeCriticalSection ( & tok - > cs ) ;
tok - > count = 0 ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
if ( ( tok - > lock = xmlNewMutex ( ) ) = = NULL ) {
free ( tok ) ;
return NULL ;
}
tok - > count = 0 ;
2001-10-12 21:29:10 +04:00
# endif
return ( tok ) ;
}
/**
2002-12-10 18:19:08 +03:00
* xmlFreeRMutex :
2001-10-12 21:29:10 +04:00
* @ tok : the reentrant mutex
*
* xmlRFreeMutex ( ) is used to reclaim resources associated with a
* reentrant mutex .
*/
void
2002-02-10 16:20:39 +03:00
xmlFreeRMutex ( xmlRMutexPtr tok ATTRIBUTE_UNUSED )
2001-10-12 21:29:10 +04:00
{
# ifdef HAVE_PTHREAD_H
pthread_mutex_destroy ( & tok - > lock ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
DeleteCriticalSection ( & tok - > cs ) ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
xmlFreeMutex ( tok - > lock ) ;
2001-10-12 21:29:10 +04:00
# endif
free ( tok ) ;
}
/**
* xmlRMutexLock :
* @ tok : the reentrant mutex
*
* xmlRMutexLock ( ) is used to lock a libxml2 token_r .
*/
void
2003-09-12 03:35:09 +04:00
xmlRMutexLock ( xmlRMutexPtr tok )
2001-10-12 21:29:10 +04:00
{
2003-09-12 03:35:09 +04:00
if ( tok = = NULL )
return ;
2001-10-12 21:29:10 +04:00
# ifdef HAVE_PTHREAD_H
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 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
EnterCriticalSection ( & tok - > cs ) ;
+ + tok - > count ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
2003-11-01 20:04:58 +03:00
if ( tok - > lock - > tid = = find_thread ( NULL ) ) {
2003-10-29 16:39:15 +03:00
tok - > count + + ;
return ;
} else {
xmlMutexLock ( tok - > lock ) ;
tok - > count = 1 ;
}
2001-10-12 21:29:10 +04:00
# endif
}
/**
* xmlRMutexUnlock :
* @ tok : the reentrant mutex
*
* xmlRMutexUnlock ( ) is used to unlock a libxml2 token_r .
*/
void
2002-02-10 16:20:39 +03:00
xmlRMutexUnlock ( xmlRMutexPtr tok ATTRIBUTE_UNUSED )
2001-10-12 21:29:10 +04:00
{
2003-09-12 03:35:09 +04:00
if ( tok = = NULL )
return ;
2001-10-12 21:29:10 +04:00
# ifdef HAVE_PTHREAD_H
pthread_mutex_lock ( & tok - > lock ) ;
tok - > held - - ;
if ( tok - > held = = 0 ) {
if ( tok - > waiters )
pthread_cond_signal ( & tok - > cv ) ;
tok - > tid = 0 ;
}
pthread_mutex_unlock ( & tok - > lock ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
if ( ! - - tok - > count )
LeaveCriticalSection ( & tok - > cs ) ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
2003-11-01 20:04:58 +03:00
if ( tok - > lock - > tid = = find_thread ( NULL ) ) {
2003-10-29 16:39:15 +03:00
tok - > count - - ;
if ( tok - > count = = 0 ) {
xmlMutexUnlock ( tok - > lock ) ;
}
return ;
}
2001-10-12 21:29:10 +04:00
# endif
}
/************************************************************************
* *
* Per thread global state handling *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-31 20:52:43 +03:00
# ifdef LIBXML_THREAD_ENABLED
2001-10-12 21:29:10 +04: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 )
{
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 19:16:02 +03:00
* of libxml2 to pre - thread - safe behaviour .
2001-10-12 21:29:10 +04:00
*
* Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
*/
static xmlGlobalStatePtr
xmlNewGlobalState ( void )
{
xmlGlobalState * gs ;
gs = malloc ( sizeof ( xmlGlobalState ) ) ;
if ( gs = = NULL )
return ( NULL ) ;
2002-11-22 08:07:29 +03:00
memset ( gs , 0 , sizeof ( xmlGlobalState ) ) ;
2001-10-12 21:29:10 +04:00
xmlInitializeGlobalState ( gs ) ;
return ( gs ) ;
}
2001-10-31 20:52:43 +03:00
# endif /* LIBXML_THREAD_ENABLED */
2001-10-12 21:29:10 +04:00
2002-01-13 16:35:00 +03:00
# ifdef HAVE_WIN32_THREADS
2003-10-08 01:25:12 +04:00
# if !defined(HAVE_COMPILER_TLS)
# if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
2002-01-13 16:35:00 +03:00
typedef struct _xmlGlobalStateCleanupHelperParams
{
2002-10-31 18:58:42 +03:00
HANDLE thread ;
void * memory ;
2002-01-13 16:35:00 +03:00
} xmlGlobalStateCleanupHelperParams ;
2002-12-10 18:19:08 +03:00
static void xmlGlobalStateCleanupHelper ( void * p )
2002-01-13 16:35:00 +03:00
{
2002-10-31 18:58:42 +03:00
xmlGlobalStateCleanupHelperParams * params = ( xmlGlobalStateCleanupHelperParams * ) p ;
WaitForSingleObject ( params - > thread , INFINITE ) ;
CloseHandle ( params - > thread ) ;
xmlFreeGlobalState ( params - > memory ) ;
free ( params ) ;
_endthread ( ) ;
2002-01-13 16:35:00 +03:00
}
2003-10-08 01:25:12 +04:00
# else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */
typedef struct _xmlGlobalStateCleanupHelperParams
{
void * memory ;
struct _xmlGlobalStateCleanupHelperParams * prev ;
struct _xmlGlobalStateCleanupHelperParams * next ;
} xmlGlobalStateCleanupHelperParams ;
static xmlGlobalStateCleanupHelperParams * cleanup_helpers_head = NULL ;
static CRITICAL_SECTION cleanup_helpers_cs ;
# endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */
# endif /* HAVE_COMPILER_TLS */
2002-01-13 16:35:00 +03:00
# endif /* HAVE_WIN32_THREADS */
2003-10-29 16:39:15 +03:00
# if defined HAVE_BEOS_THREADS
2003-11-18 09:54:40 +03:00
/**
* xmlGlobalStateCleanup :
* @ data : unused parameter
*
* Used for Beos only
*/
2003-10-29 16:39:15 +03:00
void xmlGlobalStateCleanup ( void * data )
{
void * globalval = tls_get ( globalkey ) ;
if ( globalval ! = NULL )
xmlFreeGlobalState ( globalval ) ;
}
# endif
2002-12-10 18:19:08 +03: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 21:29:10 +04:00
xmlGlobalStatePtr
xmlGetGlobalState ( void )
{
# ifdef HAVE_PTHREAD_H
xmlGlobalState * globalval ;
2001-12-06 17:08:31 +03:00
pthread_once ( & once_control , xmlOnceInit ) ;
2001-10-12 21:29:10 +04:00
if ( ( globalval = ( xmlGlobalState * )
2002-10-31 18:58:42 +03:00
pthread_getspecific ( globalkey ) ) = = NULL ) {
2001-10-12 21:29:10 +04:00
xmlGlobalState * tsd = xmlNewGlobalState ( ) ;
pthread_setspecific ( globalkey , tsd ) ;
return ( tsd ) ;
2001-10-14 13:56:15 +04:00
}
return ( globalval ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
# if defined(HAVE_COMPILER_TLS)
if ( ! tlstate_inited ) {
tlstate_inited = 1 ;
xmlInitializeGlobalState ( & tlstate ) ;
}
return & tlstate ;
# else /* HAVE_COMPILER_TLS */
xmlGlobalState * globalval ;
2003-10-08 01:25:12 +04:00
xmlGlobalStateCleanupHelperParams * p ;
2002-10-31 18:58:42 +03:00
if ( run_once_init ) {
run_once_init = 0 ;
xmlOnceInit ( ) ;
}
2003-10-08 01:25:12 +04:00
# if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
globalval = ( xmlGlobalState * ) TlsGetValue ( globalkey ) ;
# else
p = ( xmlGlobalStateCleanupHelperParams * ) TlsGetValue ( globalkey ) ;
globalval = ( xmlGlobalState * ) ( p ? p - > memory : NULL ) ;
# endif
if ( globalval = = NULL ) {
2002-10-31 18:58:42 +03:00
xmlGlobalState * tsd = xmlNewGlobalState ( ) ;
2003-10-08 01:25:12 +04:00
p = ( xmlGlobalStateCleanupHelperParams * ) malloc ( sizeof ( xmlGlobalStateCleanupHelperParams ) ) ;
2002-10-31 18:58:42 +03:00
p - > memory = tsd ;
2003-10-08 01:25:12 +04:00
# if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
2002-10-31 18:58:42 +03:00
DuplicateHandle ( GetCurrentProcess ( ) , GetCurrentThread ( ) ,
GetCurrentProcess ( ) , & p - > thread , 0 , TRUE , DUPLICATE_SAME_ACCESS ) ;
TlsSetValue ( globalkey , tsd ) ;
_beginthread ( xmlGlobalStateCleanupHelper , 0 , p ) ;
2003-10-08 01:25:12 +04:00
# else
EnterCriticalSection ( & cleanup_helpers_cs ) ;
if ( cleanup_helpers_head ! = NULL ) {
cleanup_helpers_head - > prev = p ;
}
p - > next = cleanup_helpers_head ;
p - > prev = NULL ;
cleanup_helpers_head = p ;
TlsSetValue ( globalkey , p ) ;
LeaveCriticalSection ( & cleanup_helpers_cs ) ;
2003-05-17 14:55:15 +04:00
# endif
2002-10-31 18:58:42 +03:00
return ( tsd ) ;
}
return ( globalval ) ;
# endif /* HAVE_COMPILER_TLS */
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
xmlGlobalState * globalval ;
xmlOnceInit ( ) ;
if ( ( globalval = ( xmlGlobalState * )
tls_get ( globalkey ) ) = = NULL ) {
xmlGlobalState * tsd = xmlNewGlobalState ( ) ;
tls_set ( globalkey , tsd ) ;
on_exit_thread ( xmlGlobalStateCleanup , NULL ) ;
return ( tsd ) ;
}
return ( globalval ) ;
2001-10-14 13:56:15 +04:00
# else
return ( NULL ) ;
2001-10-12 21:29:10 +04:00
# endif
}
/************************************************************************
* *
* Library wide thread interfaces *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-17 19:58:35 +04:00
/**
* xmlGetThreadId :
*
* xmlGetThreadId ( ) find the current thread ID number
*
* Returns the current thread ID number
*/
int
xmlGetThreadId ( void )
{
# ifdef HAVE_PTHREAD_H
return ( ( int ) pthread_self ( ) ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
return GetCurrentThreadId ( ) ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
return find_thread ( NULL ) ;
2001-10-17 19:58:35 +04:00
# else
return ( ( int ) 0 ) ;
# endif
}
2001-10-14 13:56:15 +04:00
/**
* xmlIsMainThread :
*
2001-12-31 19:16:02 +03:00
* xmlIsMainThread ( ) check whether the current thread is the main thread .
2001-10-14 13:56:15 +04:00
*
* Returns 1 if the current thread is the main thread , 0 otherwise
*/
int
xmlIsMainThread ( void )
{
2001-12-06 17:08:31 +03:00
# ifdef HAVE_PTHREAD_H
pthread_once ( & once_control , xmlOnceInit ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
if ( run_once_init ) {
run_once_init = 0 ;
xmlOnceInit ( ) ;
}
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
xmlOnceInit ( ) ;
2001-12-06 17:08:31 +03:00
# endif
2001-10-14 13:56:15 +04:00
# ifdef DEBUG_THREADS
xmlGenericError ( xmlGenericErrorContext , " xmlIsMainThread() \n " ) ;
# endif
# ifdef HAVE_PTHREAD_H
return ( mainthread = = pthread_self ( ) ) ;
2002-01-13 16:35:00 +03:00
# elif defined HAVE_WIN32_THREADS
2002-10-31 18:58:42 +03:00
return ( mainthread = = GetCurrentThreadId ( ) ) ;
2003-10-29 16:39:15 +03:00
# elif defined HAVE_BEOS_THREADS
return ( mainthread = = find_thread ( NULL ) ) ;
2001-10-14 13:56:15 +04:00
# else
return ( 1 ) ;
# endif
}
2001-10-12 21:29:10 +04:00
/**
* xmlLockLibrary :
*
* xmlLockLibrary ( ) is used to take out a re - entrant lock on the libxml2
* library .
*/
void
xmlLockLibrary ( void )
{
2001-10-14 13:56:15 +04:00
# ifdef DEBUG_THREADS
xmlGenericError ( xmlGenericErrorContext , " xmlLockLibrary() \n " ) ;
# endif
2001-10-12 21:29:10 +04:00
xmlRMutexLock ( xmlLibraryLock ) ;
}
/**
* xmlUnlockLibrary :
*
* xmlUnlockLibrary ( ) is used to release a re - entrant lock on the libxml2
* library .
*/
void
xmlUnlockLibrary ( void )
{
2001-10-14 13:56:15 +04:00
# ifdef DEBUG_THREADS
xmlGenericError ( xmlGenericErrorContext , " xmlUnlockLibrary() \n " ) ;
# endif
2001-10-12 21:29:10 +04:00
xmlRMutexUnlock ( xmlLibraryLock ) ;
}
/**
* xmlInitThreads :
*
* xmlInitThreads ( ) is used to to initialize all the thread related
* data of the libxml2 library .
*/
void
xmlInitThreads ( void )
{
2001-10-14 13:56:15 +04:00
# ifdef DEBUG_THREADS
xmlGenericError ( xmlGenericErrorContext , " xmlInitThreads() \n " ) ;
# endif
2003-10-11 14:50:10 +04:00
# if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
2003-10-08 01:25:12 +04:00
InitializeCriticalSection ( & cleanup_helpers_cs ) ;
# endif
2001-10-12 21:29:10 +04:00
}
/**
* xmlCleanupThreads :
*
* xmlCleanupThreads ( ) is used to to cleanup all the thread related
* data of the libxml2 library once processing has ended .
*/
void
xmlCleanupThreads ( void )
{
2001-10-14 13:56:15 +04:00
# ifdef DEBUG_THREADS
xmlGenericError ( xmlGenericErrorContext , " xmlCleanupThreads() \n " ) ;
# endif
2003-10-11 14:50:10 +04:00
# if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
2003-10-08 01:25:12 +04:00
if ( globalkey ! = TLS_OUT_OF_INDEXES ) {
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 ;
}
DeleteCriticalSection ( & cleanup_helpers_cs ) ;
# endif
2001-12-06 17:08:31 +03:00
}
2001-10-14 13:56:15 +04:00
2003-09-29 17:20:24 +04:00
# ifdef LIBXML_THREAD_ENABLED
2001-12-06 17:08:31 +03: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
xmlOnceInit ( void ) {
# ifdef HAVE_PTHREAD_H
2002-10-31 18:58:42 +03:00
( void ) pthread_key_create ( & globalkey , xmlFreeGlobalState ) ;
2001-12-06 17:08:31 +03:00
mainthread = pthread_self ( ) ;
2002-10-31 18:58:42 +03:00
# endif
# if defined(HAVE_WIN32_THREADS)
# if !defined(HAVE_COMPILER_TLS)
globalkey = TlsAlloc ( ) ;
# endif
mainthread = GetCurrentThreadId ( ) ;
2001-12-06 17:08:31 +03:00
# endif
2003-10-29 16:39:15 +03:00
# ifdef HAVE_BEOS_THREADS
if ( atomic_add ( & run_once_init , 1 ) = = 0 ) {
globalkey = tls_allocate ( ) ;
tls_set ( globalkey , NULL ) ;
mainthread = find_thread ( NULL ) ;
} else
atomic_add ( & run_once_init , - 1 ) ;
# endif
2001-10-12 21:29:10 +04:00
}
2003-09-29 17:20:24 +04:00
# endif
2003-05-17 14:55:15 +04:00
/**
2003-08-15 11:27:40 +04:00
* DllMain :
* @ hinstDLL : handle to DLL instance
* @ fdwReason : Reason code for entry
* @ lpvReserved : generic pointer ( depends upon reason code )
2003-05-17 14:55:15 +04:00
*
* Entry point for Windows library . It is being used to free thread - specific
* storage .
2003-08-15 11:27:40 +04:00
*
* Returns TRUE always
2003-05-17 14:55:15 +04:00
*/
2003-10-08 01:25:12 +04:00
# if defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
# if defined(LIBXML_STATIC_FOR_DLL)
BOOL WINAPI xmlDllMain ( HINSTANCE hinstDLL , DWORD fdwReason , LPVOID lpvReserved )
# else
2003-05-17 14:55:15 +04:00
BOOL WINAPI DllMain ( HINSTANCE hinstDLL , DWORD fdwReason , LPVOID lpvReserved )
2003-10-08 01:25:12 +04:00
# endif
2003-05-17 14:55:15 +04:00
{
switch ( fdwReason ) {
case DLL_THREAD_DETACH :
if ( globalkey ! = TLS_OUT_OF_INDEXES ) {
2003-10-08 01:25:12 +04:00
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-05-17 14:55:15 +04:00
}
}
break ;
}
return TRUE ;
}
# endif