ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

threads.c
Go to the documentation of this file.
00001 
00010 #define IN_LIBXML
00011 #include "libxml.h"
00012 
00013 #include <string.h>
00014 
00015 #include <libxml/threads.h>
00016 #include <libxml/globals.h>
00017 
00018 #ifdef HAVE_SYS_TYPES_H
00019 #include <sys/types.h>
00020 #endif
00021 #ifdef HAVE_UNISTD_H
00022 #include <unistd.h>
00023 #endif
00024 #ifdef HAVE_STDLIB_H
00025 #include <stdlib.h>
00026 #endif
00027 #ifdef HAVE_PTHREAD_H
00028 #include <pthread.h>
00029 #elif defined HAVE_WIN32_THREADS
00030 #include <windows.h>
00031 #ifndef HAVE_COMPILER_TLS
00032 #include <process.h>
00033 #endif
00034 #endif
00035 
00036 #ifdef HAVE_BEOS_THREADS
00037 #include <OS.h>
00038 #include <TLS.h>
00039 #endif
00040 
00041 #if defined(SOLARIS)
00042 #include <note.h>
00043 #endif
00044 
00045 /* #define DEBUG_THREADS */
00046 
00047 #ifdef HAVE_PTHREAD_H
00048 
00049 static int libxml_is_threaded = -1;
00050 #ifdef __GNUC__
00051 #ifdef linux
00052 #if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || (__GNUC__ > 3)
00053 extern int pthread_once (pthread_once_t *__once_control,
00054                          void (*__init_routine) (void))
00055        __attribute((weak));
00056 extern void *pthread_getspecific (pthread_key_t __key)
00057        __attribute((weak));
00058 extern int pthread_setspecific (pthread_key_t __key,
00059                                 __const void *__pointer)
00060        __attribute((weak));
00061 extern int pthread_key_create (pthread_key_t *__key,
00062                                void (*__destr_function) (void *))
00063        __attribute((weak));
00064 extern int pthread_key_delete (pthread_key_t __key)
00065        __attribute((weak));
00066 extern int pthread_mutex_init ()
00067        __attribute((weak));
00068 extern int pthread_mutex_destroy ()
00069        __attribute((weak));
00070 extern int pthread_mutex_lock ()
00071        __attribute((weak));
00072 extern int pthread_mutex_unlock ()
00073        __attribute((weak));
00074 extern int pthread_cond_init ()
00075        __attribute((weak));
00076 extern int pthread_cond_destroy ()
00077        __attribute((weak));
00078 extern int pthread_cond_wait ()
00079        __attribute((weak));
00080 extern int pthread_equal ()
00081        __attribute((weak));
00082 extern pthread_t pthread_self ()
00083        __attribute((weak));
00084 extern int pthread_key_create ()
00085        __attribute((weak));
00086 extern int pthread_key_delete ()
00087        __attribute((weak));
00088 extern int pthread_cond_signal ()
00089        __attribute((weak));
00090 #endif
00091 #endif /* linux */
00092 #endif /* __GNUC__ */
00093 #endif /* HAVE_PTHREAD_H */
00094 
00095 /*
00096  * TODO: this module still uses malloc/free and not xmlMalloc/xmlFree
00097  *       to avoid some crazyness since xmlMalloc/xmlFree may actually
00098  *       be hosted on allocated blocks needing them for the allocation ...
00099  */
00100 
00101 /*
00102  * xmlMutex are a simple mutual exception locks
00103  */
00104 struct _xmlMutex {
00105 #ifdef HAVE_PTHREAD_H
00106     pthread_mutex_t lock;
00107 #elif defined HAVE_WIN32_THREADS
00108     HANDLE mutex;
00109 #elif defined HAVE_BEOS_THREADS
00110     sem_id sem;
00111     thread_id tid;
00112 #else
00113     int empty;
00114 #endif
00115 };
00116 
00117 /*
00118  * xmlRMutex are reentrant mutual exception locks
00119  */
00120 struct _xmlRMutex {
00121 #ifdef HAVE_PTHREAD_H
00122     pthread_mutex_t lock;
00123     unsigned int held;
00124     unsigned int waiters;
00125     pthread_t tid;
00126     pthread_cond_t cv;
00127 #elif defined HAVE_WIN32_THREADS
00128     CRITICAL_SECTION cs;
00129     unsigned int count;
00130 #elif defined HAVE_BEOS_THREADS
00131     xmlMutexPtr lock;
00132     thread_id tid;
00133     int32 count;
00134 #else
00135     int empty;
00136 #endif
00137 };
00138 
00139 /*
00140  * This module still has some internal static data.
00141  *   - xmlLibraryLock a global lock
00142  *   - globalkey used for per-thread data
00143  */
00144 
00145 #ifdef HAVE_PTHREAD_H
00146 static pthread_key_t globalkey;
00147 static pthread_t mainthread;
00148 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
00149 static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
00150 #elif defined HAVE_WIN32_THREADS
00151 #if defined(HAVE_COMPILER_TLS)
00152 static __declspec(thread) xmlGlobalState tlstate;
00153 static __declspec(thread) int tlstate_inited = 0;
00154 #else /* HAVE_COMPILER_TLS */
00155 static DWORD globalkey = TLS_OUT_OF_INDEXES;
00156 #endif /* HAVE_COMPILER_TLS */
00157 static DWORD mainthread;
00158 static struct {
00159     DWORD done;
00160     DWORD control;
00161 } run_once = { 0, 0};
00162 static volatile LPCRITICAL_SECTION global_init_lock = NULL;
00163 
00164 /* endif HAVE_WIN32_THREADS */
00165 #elif defined HAVE_BEOS_THREADS
00166 int32 globalkey = 0;
00167 thread_id mainthread = 0;
00168 int32 run_once_init = 0;
00169 static int32 global_init_lock = -1;
00170 static vint32 global_init_count = 0;
00171 #endif
00172 
00173 static xmlRMutexPtr xmlLibraryLock = NULL;
00174 
00175 #ifdef LIBXML_THREAD_ENABLED
00176 static void xmlOnceInit(void);
00177 #endif
00178 
00187 xmlMutexPtr
00188 xmlNewMutex(void)
00189 {
00190     xmlMutexPtr tok;
00191 
00192     if ((tok = malloc(sizeof(xmlMutex))) == NULL)
00193         return (NULL);
00194 #ifdef HAVE_PTHREAD_H
00195     if (libxml_is_threaded != 0)
00196         pthread_mutex_init(&tok->lock, NULL);
00197 #elif defined HAVE_WIN32_THREADS
00198     tok->mutex = CreateMutex(NULL, FALSE, NULL);
00199 #elif defined HAVE_BEOS_THREADS
00200     if ((tok->sem = create_sem(1, "xmlMutex")) < B_OK) {
00201         free(tok);
00202         return NULL;
00203     }
00204     tok->tid = -1;
00205 #endif
00206     return (tok);
00207 }
00208 
00216 void
00217 xmlFreeMutex(xmlMutexPtr tok)
00218 {
00219     if (tok == NULL)
00220         return;
00221 
00222 #ifdef HAVE_PTHREAD_H
00223     if (libxml_is_threaded != 0)
00224         pthread_mutex_destroy(&tok->lock);
00225 #elif defined HAVE_WIN32_THREADS
00226     CloseHandle(tok->mutex);
00227 #elif defined HAVE_BEOS_THREADS
00228     delete_sem(tok->sem);
00229 #endif
00230     free(tok);
00231 }
00232 
00239 void
00240 xmlMutexLock(xmlMutexPtr tok)
00241 {
00242     if (tok == NULL)
00243         return;
00244 #ifdef HAVE_PTHREAD_H
00245     if (libxml_is_threaded != 0)
00246         pthread_mutex_lock(&tok->lock);
00247 #elif defined HAVE_WIN32_THREADS
00248     WaitForSingleObject(tok->mutex, INFINITE);
00249 #elif defined HAVE_BEOS_THREADS
00250     if (acquire_sem(tok->sem) != B_NO_ERROR) {
00251 #ifdef DEBUG_THREADS
00252         xmlGenericError(xmlGenericErrorContext,
00253                         "xmlMutexLock():BeOS:Couldn't aquire semaphore\n");
00254         exit();
00255 #endif
00256     }
00257     tok->tid = find_thread(NULL);
00258 #endif
00259 
00260 }
00261 
00268 void
00269 xmlMutexUnlock(xmlMutexPtr tok)
00270 {
00271     if (tok == NULL)
00272         return;
00273 #ifdef HAVE_PTHREAD_H
00274     if (libxml_is_threaded != 0)
00275         pthread_mutex_unlock(&tok->lock);
00276 #elif defined HAVE_WIN32_THREADS
00277     ReleaseMutex(tok->mutex);
00278 #elif defined HAVE_BEOS_THREADS
00279     if (tok->tid == find_thread(NULL)) {
00280         tok->tid = -1;
00281         release_sem(tok->sem);
00282     }
00283 #endif
00284 }
00285 
00296 xmlRMutexPtr
00297 xmlNewRMutex(void)
00298 {
00299     xmlRMutexPtr tok;
00300 
00301     if ((tok = malloc(sizeof(xmlRMutex))) == NULL)
00302         return (NULL);
00303 #ifdef HAVE_PTHREAD_H
00304     if (libxml_is_threaded != 0) {
00305         pthread_mutex_init(&tok->lock, NULL);
00306         tok->held = 0;
00307         tok->waiters = 0;
00308         pthread_cond_init(&tok->cv, NULL);
00309     }
00310 #elif defined HAVE_WIN32_THREADS
00311     InitializeCriticalSection(&tok->cs);
00312     tok->count = 0;
00313 #elif defined HAVE_BEOS_THREADS
00314     if ((tok->lock = xmlNewMutex()) == NULL) {
00315         free(tok);
00316         return NULL;
00317     }
00318     tok->count = 0;
00319 #endif
00320     return (tok);
00321 }
00322 
00330 void
00331 xmlFreeRMutex(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
00332 {
00333     if (tok == NULL)
00334         return;
00335 #ifdef HAVE_PTHREAD_H
00336     if (libxml_is_threaded != 0) {
00337         pthread_mutex_destroy(&tok->lock);
00338         pthread_cond_destroy(&tok->cv);
00339     }
00340 #elif defined HAVE_WIN32_THREADS
00341     DeleteCriticalSection(&tok->cs);
00342 #elif defined HAVE_BEOS_THREADS
00343     xmlFreeMutex(tok->lock);
00344 #endif
00345     free(tok);
00346 }
00347 
00354 void
00355 xmlRMutexLock(xmlRMutexPtr tok)
00356 {
00357     if (tok == NULL)
00358         return;
00359 #ifdef HAVE_PTHREAD_H
00360     if (libxml_is_threaded == 0)
00361         return;
00362 
00363     pthread_mutex_lock(&tok->lock);
00364     if (tok->held) {
00365         if (pthread_equal(tok->tid, pthread_self())) {
00366             tok->held++;
00367             pthread_mutex_unlock(&tok->lock);
00368             return;
00369         } else {
00370             tok->waiters++;
00371             while (tok->held)
00372                 pthread_cond_wait(&tok->cv, &tok->lock);
00373             tok->waiters--;
00374         }
00375     }
00376     tok->tid = pthread_self();
00377     tok->held = 1;
00378     pthread_mutex_unlock(&tok->lock);
00379 #elif defined HAVE_WIN32_THREADS
00380     EnterCriticalSection(&tok->cs);
00381     ++tok->count;
00382 #elif defined HAVE_BEOS_THREADS
00383     if (tok->lock->tid == find_thread(NULL)) {
00384         tok->count++;
00385         return;
00386     } else {
00387         xmlMutexLock(tok->lock);
00388         tok->count = 1;
00389     }
00390 #endif
00391 }
00392 
00399 void
00400 xmlRMutexUnlock(xmlRMutexPtr tok ATTRIBUTE_UNUSED)
00401 {
00402     if (tok == NULL)
00403         return;
00404 #ifdef HAVE_PTHREAD_H
00405     if (libxml_is_threaded == 0)
00406         return;
00407 
00408     pthread_mutex_lock(&tok->lock);
00409     tok->held--;
00410     if (tok->held == 0) {
00411         if (tok->waiters)
00412             pthread_cond_signal(&tok->cv);
00413         memset(&tok->tid, 0, sizeof(tok->tid));
00414     }
00415     pthread_mutex_unlock(&tok->lock);
00416 #elif defined HAVE_WIN32_THREADS
00417     if (!--tok->count)
00418         LeaveCriticalSection(&tok->cs);
00419 #elif defined HAVE_BEOS_THREADS
00420     if (tok->lock->tid == find_thread(NULL)) {
00421         tok->count--;
00422         if (tok->count == 0) {
00423             xmlMutexUnlock(tok->lock);
00424         }
00425         return;
00426     }
00427 #endif
00428 }
00429 
00436 void
00437 __xmlGlobalInitMutexLock(void)
00438 {
00439     /* Make sure the global init lock is initialized and then lock it. */
00440 #ifdef HAVE_PTHREAD_H
00441     /* The mutex is statically initialized, so we just lock it. */
00442     if (pthread_mutex_lock)
00443         pthread_mutex_lock(&global_init_lock);
00444 #elif defined HAVE_WIN32_THREADS
00445     LPCRITICAL_SECTION cs;
00446 
00447     /* Create a new critical section */
00448     if (global_init_lock == NULL) {
00449         cs = malloc(sizeof(CRITICAL_SECTION));
00450         if (cs == NULL) {
00451             xmlGenericError(xmlGenericErrorContext,
00452                             "xmlGlobalInitMutexLock: out of memory\n");
00453             return;
00454         }
00455         InitializeCriticalSection(cs);
00456 
00457         /* Swap it into the global_init_lock */
00458 #ifdef InterlockedCompareExchangePointer
00459         InterlockedCompareExchangePointer(&global_init_lock, cs, NULL);
00460 #else /* Use older void* version */
00461         InterlockedCompareExchange((void **) &global_init_lock,
00462                                    (void *) cs, NULL);
00463 #endif /* InterlockedCompareExchangePointer */
00464 
00465         /* If another thread successfully recorded its critical
00466          * section in the global_init_lock then discard the one
00467          * allocated by this thread. */
00468         if (global_init_lock != cs) {
00469             DeleteCriticalSection(cs);
00470             free(cs);
00471         }
00472     }
00473 
00474     /* Lock the chosen critical section */
00475     EnterCriticalSection(global_init_lock);
00476 #elif defined HAVE_BEOS_THREADS
00477     int32 sem;
00478 
00479     /* Allocate a new semaphore */
00480     sem = create_sem(1, "xmlGlobalinitMutex");
00481 
00482     while (global_init_lock == -1) {
00483         if (atomic_add(&global_init_count, 1) == 0) {
00484             global_init_lock = sem;
00485         } else {
00486             snooze(1);
00487             atomic_add(&global_init_count, -1);
00488         }
00489     }
00490 
00491     /* If another thread successfully recorded its critical
00492      * section in the global_init_lock then discard the one
00493      * allocated by this thread. */
00494     if (global_init_lock != sem)
00495         delete_sem(sem);
00496 
00497     /* Acquire the chosen semaphore */
00498     if (acquire_sem(global_init_lock) != B_NO_ERROR) {
00499 #ifdef DEBUG_THREADS
00500         xmlGenericError(xmlGenericErrorContext,
00501                         "xmlGlobalInitMutexLock():BeOS:Couldn't acquire semaphore\n");
00502         exit();
00503 #endif
00504     }
00505 #endif
00506 }
00507 
00508 void
00509 __xmlGlobalInitMutexUnlock(void)
00510 {
00511 #ifdef HAVE_PTHREAD_H
00512     if (pthread_mutex_unlock)
00513         pthread_mutex_unlock(&global_init_lock);
00514 #elif defined HAVE_WIN32_THREADS
00515     if (global_init_lock != NULL) {
00516     LeaveCriticalSection(global_init_lock);
00517     }
00518 #elif defined HAVE_BEOS_THREADS
00519     release_sem(global_init_lock);
00520 #endif
00521 }
00522 
00529 void
00530 __xmlGlobalInitMutexDestroy(void)
00531 {
00532 #ifdef HAVE_PTHREAD_H
00533 #elif defined HAVE_WIN32_THREADS
00534     if (global_init_lock != NULL) {
00535         DeleteCriticalSection(global_init_lock);
00536         free(global_init_lock);
00537         global_init_lock = NULL;
00538     }
00539 #endif
00540 }
00541 
00542 /************************************************************************
00543  *                                  *
00544  *          Per thread global state handling        *
00545  *                                  *
00546  ************************************************************************/
00547 
00548 #ifdef LIBXML_THREAD_ENABLED
00549 #ifdef xmlLastError
00550 #undef xmlLastError
00551 #endif
00552 
00560 static void
00561 xmlFreeGlobalState(void *state)
00562 {
00563     xmlGlobalState *gs = (xmlGlobalState *) state;
00564 
00565     /* free any memory allocated in the thread's xmlLastError */
00566     xmlResetError(&(gs->xmlLastError));
00567     free(state);
00568 }
00569 
00579 static xmlGlobalStatePtr
00580 xmlNewGlobalState(void)
00581 {
00582     xmlGlobalState *gs;
00583 
00584     gs = malloc(sizeof(xmlGlobalState));
00585     if (gs == NULL) {
00586     xmlGenericError(xmlGenericErrorContext,
00587             "xmlGetGlobalState: out of memory\n");
00588         return (NULL);
00589     }
00590 
00591     memset(gs, 0, sizeof(xmlGlobalState));
00592     xmlInitializeGlobalState(gs);
00593     return (gs);
00594 }
00595 #endif /* LIBXML_THREAD_ENABLED */
00596 
00597 #ifdef HAVE_PTHREAD_H
00598 #elif defined HAVE_WIN32_THREADS
00599 #if !defined(HAVE_COMPILER_TLS)
00600 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
00601 typedef struct _xmlGlobalStateCleanupHelperParams {
00602     HANDLE thread;
00603     void *memory;
00604 } xmlGlobalStateCleanupHelperParams;
00605 
00606 static void XMLCDECL
00607 xmlGlobalStateCleanupHelper(void *p)
00608 {
00609     xmlGlobalStateCleanupHelperParams *params =
00610         (xmlGlobalStateCleanupHelperParams *) p;
00611     WaitForSingleObject(params->thread, INFINITE);
00612     CloseHandle(params->thread);
00613     xmlFreeGlobalState(params->memory);
00614     free(params);
00615     _endthread();
00616 }
00617 #else /* LIBXML_STATIC && !LIBXML_STATIC_FOR_DLL */
00618 
00619 typedef struct _xmlGlobalStateCleanupHelperParams {
00620     void *memory;
00621     struct _xmlGlobalStateCleanupHelperParams *prev;
00622     struct _xmlGlobalStateCleanupHelperParams *next;
00623 } xmlGlobalStateCleanupHelperParams;
00624 
00625 static xmlGlobalStateCleanupHelperParams *cleanup_helpers_head = NULL;
00626 static CRITICAL_SECTION cleanup_helpers_cs;
00627 
00628 #endif /* LIBXMLSTATIC && !LIBXML_STATIC_FOR_DLL */
00629 #endif /* HAVE_COMPILER_TLS */
00630 #endif /* HAVE_WIN32_THREADS */
00631 
00632 #if defined HAVE_BEOS_THREADS
00633 
00640 void
00641 xmlGlobalStateCleanup(void *data)
00642 {
00643     void *globalval = tls_get(globalkey);
00644 
00645     if (globalval != NULL)
00646         xmlFreeGlobalState(globalval);
00647 }
00648 #endif
00649 
00657 xmlGlobalStatePtr
00658 xmlGetGlobalState(void)
00659 {
00660 #ifdef HAVE_PTHREAD_H
00661     xmlGlobalState *globalval;
00662 
00663     if (libxml_is_threaded == 0)
00664         return (NULL);
00665 
00666     pthread_once(&once_control, xmlOnceInit);
00667 
00668     if ((globalval = (xmlGlobalState *)
00669          pthread_getspecific(globalkey)) == NULL) {
00670         xmlGlobalState *tsd = xmlNewGlobalState();
00671     if (tsd == NULL)
00672         return(NULL);
00673 
00674         pthread_setspecific(globalkey, tsd);
00675         return (tsd);
00676     }
00677     return (globalval);
00678 #elif defined HAVE_WIN32_THREADS
00679 #if defined(HAVE_COMPILER_TLS)
00680     if (!tlstate_inited) {
00681         tlstate_inited = 1;
00682         xmlInitializeGlobalState(&tlstate);
00683     }
00684     return &tlstate;
00685 #else /* HAVE_COMPILER_TLS */
00686     xmlGlobalState *globalval;
00687     xmlGlobalStateCleanupHelperParams *p;
00688 
00689     xmlOnceInit();
00690 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
00691     globalval = (xmlGlobalState *) TlsGetValue(globalkey);
00692 #else
00693     p = (xmlGlobalStateCleanupHelperParams *) TlsGetValue(globalkey);
00694     globalval = (xmlGlobalState *) (p ? p->memory : NULL);
00695 #endif
00696     if (globalval == NULL) {
00697         xmlGlobalState *tsd = xmlNewGlobalState();
00698 
00699         if (tsd == NULL)
00700         return(NULL);
00701         p = (xmlGlobalStateCleanupHelperParams *)
00702             malloc(sizeof(xmlGlobalStateCleanupHelperParams));
00703     if (p == NULL) {
00704             xmlGenericError(xmlGenericErrorContext,
00705                             "xmlGetGlobalState: out of memory\n");
00706             xmlFreeGlobalState(tsd);
00707         return(NULL);
00708     }
00709         p->memory = tsd;
00710 #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
00711         DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
00712                         GetCurrentProcess(), &p->thread, 0, TRUE,
00713                         DUPLICATE_SAME_ACCESS);
00714         TlsSetValue(globalkey, tsd);
00715         _beginthread(xmlGlobalStateCleanupHelper, 0, p);
00716 #else
00717         EnterCriticalSection(&cleanup_helpers_cs);
00718         if (cleanup_helpers_head != NULL) {
00719             cleanup_helpers_head->prev = p;
00720         }
00721         p->next = cleanup_helpers_head;
00722         p->prev = NULL;
00723         cleanup_helpers_head = p;
00724         TlsSetValue(globalkey, p);
00725         LeaveCriticalSection(&cleanup_helpers_cs);
00726 #endif
00727 
00728         return (tsd);
00729     }
00730     return (globalval);
00731 #endif /* HAVE_COMPILER_TLS */
00732 #elif defined HAVE_BEOS_THREADS
00733     xmlGlobalState *globalval;
00734 
00735     xmlOnceInit();
00736 
00737     if ((globalval = (xmlGlobalState *) tls_get(globalkey)) == NULL) {
00738         xmlGlobalState *tsd = xmlNewGlobalState();
00739     if (tsd == NULL)
00740         return (NULL);
00741 
00742         tls_set(globalkey, tsd);
00743         on_exit_thread(xmlGlobalStateCleanup, NULL);
00744         return (tsd);
00745     }
00746     return (globalval);
00747 #else
00748     return (NULL);
00749 #endif
00750 }
00751 
00752 /************************************************************************
00753  *                                  *
00754  *          Library wide thread interfaces          *
00755  *                                  *
00756  ************************************************************************/
00757 
00767 int
00768 xmlGetThreadId(void)
00769 {
00770 #ifdef HAVE_PTHREAD_H
00771     pthread_t id;
00772     int ret;
00773 
00774     if (libxml_is_threaded == 0)
00775         return (0);
00776     id = pthread_self();
00777     /* horrible but preserves compat, see warning above */
00778     memcpy(&ret, &id, sizeof(ret));
00779     return (ret);
00780 #elif defined HAVE_WIN32_THREADS
00781     return GetCurrentThreadId();
00782 #elif defined HAVE_BEOS_THREADS
00783     return find_thread(NULL);
00784 #else
00785     return ((int) 0);
00786 #endif
00787 }
00788 
00796 int
00797 xmlIsMainThread(void)
00798 {
00799 #ifdef HAVE_PTHREAD_H
00800     if (libxml_is_threaded == -1)
00801         xmlInitThreads();
00802     if (libxml_is_threaded == 0)
00803         return (1);
00804     pthread_once(&once_control, xmlOnceInit);
00805 #elif defined HAVE_WIN32_THREADS
00806     xmlOnceInit();
00807 #elif defined HAVE_BEOS_THREADS
00808     xmlOnceInit();
00809 #endif
00810 
00811 #ifdef DEBUG_THREADS
00812     xmlGenericError(xmlGenericErrorContext, "xmlIsMainThread()\n");
00813 #endif
00814 #ifdef HAVE_PTHREAD_H
00815     return (pthread_equal(mainthread,pthread_self()));
00816 #elif defined HAVE_WIN32_THREADS
00817     return (mainthread == GetCurrentThreadId());
00818 #elif defined HAVE_BEOS_THREADS
00819     return (mainthread == find_thread(NULL));
00820 #else
00821     return (1);
00822 #endif
00823 }
00824 
00831 void
00832 xmlLockLibrary(void)
00833 {
00834 #ifdef DEBUG_THREADS
00835     xmlGenericError(xmlGenericErrorContext, "xmlLockLibrary()\n");
00836 #endif
00837     xmlRMutexLock(xmlLibraryLock);
00838 }
00839 
00846 void
00847 xmlUnlockLibrary(void)
00848 {
00849 #ifdef DEBUG_THREADS
00850     xmlGenericError(xmlGenericErrorContext, "xmlUnlockLibrary()\n");
00851 #endif
00852     xmlRMutexUnlock(xmlLibraryLock);
00853 }
00854 
00861 void
00862 xmlInitThreads(void)
00863 {
00864 #ifdef HAVE_PTHREAD_H
00865     if (libxml_is_threaded == -1) {
00866         if ((pthread_once != NULL) &&
00867             (pthread_getspecific != NULL) &&
00868             (pthread_setspecific != NULL) &&
00869             (pthread_key_create != NULL) &&
00870             (pthread_key_delete != NULL) &&
00871             (pthread_mutex_init != NULL) &&
00872             (pthread_mutex_destroy != NULL) &&
00873             (pthread_mutex_lock != NULL) &&
00874             (pthread_mutex_unlock != NULL) &&
00875             (pthread_cond_init != NULL) &&
00876             (pthread_cond_destroy != NULL) &&
00877             (pthread_cond_wait != NULL) &&
00878             (pthread_equal != NULL) &&
00879             (pthread_self != NULL) &&
00880             (pthread_cond_signal != NULL)) {
00881             libxml_is_threaded = 1;
00882 
00883 /* fprintf(stderr, "Running multithreaded\n"); */
00884         } else {
00885 
00886 /* fprintf(stderr, "Running without multithread\n"); */
00887             libxml_is_threaded = 0;
00888         }
00889     }
00890 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
00891     InitializeCriticalSection(&cleanup_helpers_cs);
00892 #endif
00893 }
00894 
00909 void
00910 xmlCleanupThreads(void)
00911 {
00912 #ifdef DEBUG_THREADS
00913     xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n");
00914 #endif
00915 #ifdef HAVE_PTHREAD_H
00916     if ((libxml_is_threaded)  && (pthread_key_delete != NULL))
00917         pthread_key_delete(globalkey);
00918 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
00919     if (globalkey != TLS_OUT_OF_INDEXES) {
00920         xmlGlobalStateCleanupHelperParams *p;
00921 
00922         EnterCriticalSection(&cleanup_helpers_cs);
00923         p = cleanup_helpers_head;
00924         while (p != NULL) {
00925             xmlGlobalStateCleanupHelperParams *temp = p;
00926 
00927             p = p->next;
00928             xmlFreeGlobalState(temp->memory);
00929             free(temp);
00930         }
00931         cleanup_helpers_head = 0;
00932         LeaveCriticalSection(&cleanup_helpers_cs);
00933         TlsFree(globalkey);
00934         globalkey = TLS_OUT_OF_INDEXES;
00935     }
00936     DeleteCriticalSection(&cleanup_helpers_cs);
00937 #endif
00938 }
00939 
00940 #ifdef LIBXML_THREAD_ENABLED
00941 
00951 static void
00952 xmlOnceInit(void)
00953 {
00954 #ifdef HAVE_PTHREAD_H
00955     (void) pthread_key_create(&globalkey, xmlFreeGlobalState);
00956     mainthread = pthread_self();
00957 #elif defined(HAVE_WIN32_THREADS)
00958     if (!run_once.done) {
00959         if (InterlockedIncrement(&run_once.control) == 1) {
00960 #if !defined(HAVE_COMPILER_TLS)
00961             globalkey = TlsAlloc();
00962 #endif
00963             mainthread = GetCurrentThreadId();
00964             run_once.done = 1;
00965         } else {
00966             /* Another thread is working; give up our slice and
00967              * wait until they're done. */
00968             while (!run_once.done)
00969                 Sleep(0);
00970         }
00971     }
00972 #elif defined HAVE_BEOS_THREADS
00973     if (atomic_add(&run_once_init, 1) == 0) {
00974         globalkey = tls_allocate();
00975         tls_set(globalkey, NULL);
00976         mainthread = find_thread(NULL);
00977     } else
00978         atomic_add(&run_once_init, -1);
00979 #endif
00980 }
00981 #endif
00982 
00994 #ifdef HAVE_PTHREAD_H
00995 #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
00996 #if defined(LIBXML_STATIC_FOR_DLL)
00997 BOOL XMLCALL
00998 xmlDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
00999 #else
01000 BOOL WINAPI
01001 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
01002 #endif
01003 {
01004     switch (fdwReason) {
01005         case DLL_THREAD_DETACH:
01006             if (globalkey != TLS_OUT_OF_INDEXES) {
01007                 xmlGlobalState *globalval = NULL;
01008                 xmlGlobalStateCleanupHelperParams *p =
01009                     (xmlGlobalStateCleanupHelperParams *)
01010                     TlsGetValue(globalkey);
01011                 globalval = (xmlGlobalState *) (p ? p->memory : NULL);
01012                 if (globalval) {
01013                     xmlFreeGlobalState(globalval);
01014                     TlsSetValue(globalkey, NULL);
01015                 }
01016                 if (p) {
01017                     EnterCriticalSection(&cleanup_helpers_cs);
01018                     if (p == cleanup_helpers_head)
01019                         cleanup_helpers_head = p->next;
01020                     else
01021                         p->prev->next = p->next;
01022                     if (p->next != NULL)
01023                         p->next->prev = p->prev;
01024                     LeaveCriticalSection(&cleanup_helpers_cs);
01025                     free(p);
01026                 }
01027             }
01028             break;
01029     }
01030     return TRUE;
01031 }
01032 #endif
01033 #define bottom_threads
01034 #include "elfgcchack.h"

Generated on Sat May 26 2012 04:33:33 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.