[ https://issues.apache.org/jira/browse/XERCESC-1762?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Boris Kolpackov closed XERCESC-1762. ------------------------------------ Resolution: Fixed This code is no longer in 3-series. > Tru64 PlatformUtils RecursiveMutex implementation is not thread-safe > -------------------------------------------------------------------- > > Key: XERCESC-1762 > URL: https://issues.apache.org/jira/browse/XERCESC-1762 > Project: Xerces-C++ > Issue Type: Improvement > Components: Miscellaneous > Affects Versions: 2.7.0, 2.8.0 > Environment: Tru64 5.1 > Reporter: Vladimir Lazarenko > Priority: Critical > > The way, how RecursiveMutex is implemented is not thread safe. We've come up > with a different implementation and herewith would like to share it with you, > with hope that it will make its way into the mainstream. > In essence the issue is that you can not check if you're the owner of the > thread until you lock. If you don't lock, the tid can be overwritten, and the > check will be bogus. Further on, gAtomicOpMutex could use > PTHREAD_MUTEX_INITIALIZER instead of custom initialization. > -bash-2.05b$ svn diff -r21597 Tru64PlatformUtils.cpp > Index: Tru64PlatformUtils.cpp > =================================================================== > --- Tru64PlatformUtils.cpp (revision 21597) > +++ Tru64PlatformUtils.cpp (working copy) > @@ -42,7 +42,10 @@ > #include <xercesc/util/XMLUniDefs.hpp> > #include <xercesc/util/PanicHandler.hpp> > #include <xercesc/util/OutOfMemoryException.hpp> > +#include <xercesc/util/XMemory.hpp> > +#include <assert.h> > + > // > // These control which transcoding service is used by the Tru64 version. > // They allow this to be controlled from the build process by just defining > @@ -397,9 +400,10 @@ > // XMLPlatformUtils: Platform init method > // > --------------------------------------------------------------------------- > -typedef XMLHolder<pthread_mutex_t> MutexHolderType; > +//typedef XMLHolder<pthread_mutex_t> MutexHolderType; > -static MutexHolderType* gAtomicOpMutex = 0; > +static pthread_mutex_t gAtomicOpMutex = PTHREAD_MUTEX_INITIALIZER; > +//static MutexHolderType* gAtomicOpMutex = 0; > void XMLPlatformUtils::platformInit() > { > @@ -411,14 +415,15 @@ > // circular dependency between compareAndExchange() and > // mutex creation that must be broken. > +#if 0 > gAtomicOpMutex = new (fgMemoryManager) MutexHolderType; > - > if (pthread_mutex_init(&gAtomicOpMutex->fInstance, NULL)) { > delete gAtomicOpMutex; > gAtomicOpMutex = 0; > panic( PanicHandler::Panic_SystemInit ); > } > +#endif > } > @@ -427,61 +432,81 @@ > // ----------------------------------------------------------------------- > -class RecursiveMutex > +class RecursiveMutex : public XMemory > { > -public: > - pthread_mutex_t mutex; > - int recursionCount; > - pthread_t tid; > - MemoryManager* const fMemoryManager; > +public : > - RecursiveMutex(MemoryManager* manager) : > - mutex(), > - recursionCount(0), > - tid(0), > - fMemoryManager(manager) > + RecursiveMutex() > + : mut(), > + cond(), > + count(0), > + owner() > { > - if (pthread_mutex_init(&mutex, NULL)) > - XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr); > + int r = pthread_mutex_init(&mut, 0); > + if (r != 0) { > + XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr); > + } > + r = pthread_cond_init(&cond, 0); > + if (r != 0) { > + pthread_mutex_destroy(&mut); > + XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr); > + } > } > - ~RecursiveMutex() > + void lock() > { > - if (pthread_mutex_destroy(&mutex)) > - ThrowXMLwithMemMgr(XMLPlatformUtilsException, > XMLExcepts::Mutex_CouldNotDestroy, fMemoryManager); > + pthread_t self = pthread_self(); > + > + int r = pthread_mutex_lock(&mut); > + assert(r == 0); > + > + while (count != 0 && ! pthread_equal(self, owner)) { > + r = pthread_cond_wait(&cond, &mut); > + assert(r == 0); > + } > + > + if (count++ == 0) { > + owner = self; > + } > + > + r = pthread_mutex_unlock(&mut); > + assert(r == 0); > } > - void lock() > + void unlock() > { > - if (pthread_equal(tid, pthread_self())) > - { > - recursionCount++; > - return; > + int r = pthread_mutex_lock(&mut); > + assert(r == 0); > + > + assert(pthread_equal(pthread_self(), owner)); > + > + if (--count == 0) { > + pthread_cond_signal(&cond); > } > - if (pthread_mutex_lock(&mutex) != 0) > - XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr); > - tid = pthread_self(); > - recursionCount = 1; > + > + r = pthread_mutex_unlock(&mut); > + assert(r == 0); > } > - > - void unlock() > + ~RecursiveMutex() > { > - if (--recursionCount > 0) > - return; > + assert(count == 0); > + pthread_cond_destroy(&cond); > + pthread_mutex_destroy(&mut); > + } > - if (pthread_mutex_unlock(&mutex) != 0) > - XMLPlatformUtils::panic(PanicHandler::Panic_MutexErr); > - tid = 0; > - } > +private : > + pthread_mutex_t mut; > + pthread_cond_t cond; > + unsigned int count; > + pthread_t owner; // valid if count != 0 > }; > void* XMLPlatformUtils::makeMutex(MemoryManager* manager) > { > - return new (manager) RecursiveMutex(manager); > + return new (manager) RecursiveMutex; > } > - > void XMLPlatformUtils::closeMutex(void* const mtxHandle) > { > if (mtxHandle == NULL) > @@ -522,14 +547,14 @@ > // the below calls are temporarily made till the above functions are part > of user library > // Currently its supported only in the kernel mode > - if (pthread_mutex_lock( &gAtomicOpMutex->fInstance)) > + if (pthread_mutex_lock( &gAtomicOpMutex)) > panic(PanicHandler::Panic_SynchronizationErr); > void *retVal = *toFill; > if (*toFill == toCompare) > *toFill = (void *)newValue; > - if (pthread_mutex_unlock( &gAtomicOpMutex->fInstance)) > + if (pthread_mutex_unlock( &gAtomicOpMutex)) > panic(PanicHandler::Panic_SynchronizationErr); > return retVal; > @@ -539,12 +564,12 @@ > { > //return (int)atomic_add_32_nv( (uint32_t*)&location, 1); > - if (pthread_mutex_lock( &gAtomicOpMutex->fInstance)) > + if (pthread_mutex_lock( &gAtomicOpMutex)) > panic(PanicHandler::Panic_SynchronizationErr); > int tmp = ++location; > - if (pthread_mutex_unlock( &gAtomicOpMutex->fInstance)) > + if (pthread_mutex_unlock( &gAtomicOpMutex)) > panic(PanicHandler::Panic_SynchronizationErr); > return tmp; > @@ -553,12 +578,12 @@ > { > //return (int)atomic_add_32_nv( (uint32_t*)&location, -1); > - if (pthread_mutex_lock( &gAtomicOpMutex->fInstance)) > + if (pthread_mutex_lock( &gAtomicOpMutex)) > panic(PanicHandler::Panic_SynchronizationErr); > int tmp = --location; > - if (pthread_mutex_unlock( &gAtomicOpMutex->fInstance)) > + if (pthread_mutex_unlock( &gAtomicOpMutex)) > panic(PanicHandler::Panic_SynchronizationErr); > return tmp; > @@ -619,11 +644,6 @@ > void XMLPlatformUtils::platformTerm() > { > -#if !defined (APP_NO_THREADS) > - pthread_mutex_destroy(&gAtomicOpMutex->fInstance); > - delete gAtomicOpMutex; > - gAtomicOpMutex = 0; > -#endif > } > #include <xercesc/util/LogicalPath.c> -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. --------------------------------------------------------------------- To unsubscribe, e-mail: c-dev-unsubscr...@xerces.apache.org For additional commands, e-mail: c-dev-h...@xerces.apache.org