diff --git a/src/db/dbChannelIO.cpp b/src/db/dbChannelIO.cpp index bd01f7e49..907b9d653 100644 --- a/src/db/dbChannelIO.cpp +++ b/src/db/dbChannelIO.cpp @@ -29,6 +29,7 @@ #include "dbNotifyBlockerIL.h" tsFreeList < dbChannelIO > dbChannelIO::freeList; +epicsMutex dbChannelIO::freeListMutex; dbChannelIO::dbChannelIO ( cacChannelNotify ¬ify, const dbAddr &addrIn, dbServiceIO &serviceIO ) : @@ -45,16 +46,16 @@ void dbChannelIO::initiateConnect () dbChannelIO::~dbChannelIO () { - this->lock (); + dbAutoScanLock ( *this->addr.precord ); /* * remove any subscriptions attached to this channel */ - tsDLIterBD iter = this->eventq.firstIter (); + tsDLIterBD < dbSubscriptionIO > iter = this->eventq.firstIter (); while ( iter.valid () ) { tsDLIterBD next = iter; next++; - iter->destroy (); + iter->cancel (); iter = next; } @@ -65,8 +66,6 @@ dbChannelIO::~dbChannelIO () if ( this->pGetCallbackCache ) { delete [] this->pGetCallbackCache; } - - this->unlock (); } int dbChannelIO::read ( unsigned type, unsigned long count, void *pValue ) @@ -97,29 +96,29 @@ int dbChannelIO::read ( unsigned type, unsigned long count, cacNotify ¬ify ) return ECA_BADCOUNT; } - this->lock (); - if ( this->getCallbackCacheSize < size) { - if ( this->pGetCallbackCache ) { - delete [] this->pGetCallbackCache; + { + dbAutoScanLock ( *this->addr.precord ); + if ( this->getCallbackCacheSize < size) { + if ( this->pGetCallbackCache ) { + delete [] this->pGetCallbackCache; + } + this->pGetCallbackCache = new char [size]; + if ( ! this->pGetCallbackCache ) { + this->getCallbackCacheSize = 0ul; + return ECA_ALLOCMEM; + } + this->getCallbackCacheSize = size; } - this->pGetCallbackCache = new char [size]; - if ( ! this->pGetCallbackCache ) { - this->getCallbackCacheSize = 0ul; - this->unlock (); - return ECA_ALLOCMEM; + int status = db_get_field ( &this->addr, static_cast ( type ), + this->pGetCallbackCache, static_cast ( count ), 0); + if ( status ) { + notify.exceptionNotify ( *this, ECA_GETFAIL, + "db_get_field () completed unsuccessfuly" ); + } + else { + notify.completionNotify ( *this, type, count, this->pGetCallbackCache ); } - this->getCallbackCacheSize = size; } - int status = db_get_field ( &this->addr, static_cast ( type ), - this->pGetCallbackCache, static_cast ( count ), 0); - if ( status ) { - notify.exceptionNotify ( *this, ECA_GETFAIL, - "db_get_field () completed unsuccessfuly" ); - } - else { - notify.completionNotify ( *this, type, count, this->pGetCallbackCache ); - } - this->unlock (); notify.release (); return ECA_NORMAL; } @@ -147,15 +146,13 @@ int dbChannelIO::write ( unsigned type, unsigned long count, } if ( ! this->pBlocker ) { - this->lock (); + dbAutoScanLock ( *this->addr.precord ); if ( ! this->pBlocker ) { this->pBlocker = new dbPutNotifyBlocker ( *this ); if ( ! this->pBlocker ) { - this->unlock (); return ECA_ALLOCMEM; } } - this->unlock (); } // must release the lock here so that this can block @@ -179,22 +176,14 @@ int dbChannelIO::subscribe ( unsigned type, unsigned long count, pReturnIO = pIO; } else { - pIO->destroy (); + pIO->cancel (); } return status; } -void dbChannelIO::lockOutstandingIO () const -{ -} - -void dbChannelIO::unlockOutstandingIO () const -{ -} - void dbChannelIO::show ( unsigned level ) const { - this->lock (); + dbAutoScanLock ( *this->addr.precord ); printf ("channel at %p attached to local database record %s\n", static_cast ( this ), this->addr.precord->name ); @@ -216,5 +205,4 @@ void dbChannelIO::show ( unsigned level ) const this->pBlocker->show ( level - 2u ); } } - this->unlock (); } diff --git a/src/db/dbChannelIOIL.h b/src/db/dbChannelIOIL.h index d646688df..944af5b1e 100644 --- a/src/db/dbChannelIOIL.h +++ b/src/db/dbChannelIOIL.h @@ -34,11 +34,13 @@ inline void dbChannelIO::destroy () inline void * dbChannelIO::operator new ( size_t size ) { + epicsAutoMutex locker ( dbChannelIO::freeListMutex ); return dbChannelIO::freeList.allocate ( size ); } inline void dbChannelIO::operator delete ( void *pCadaver, size_t size ) { + epicsAutoMutex locker ( dbChannelIO::freeListMutex ); dbChannelIO::freeList.release ( pCadaver, size ); } @@ -58,16 +60,6 @@ inline void dbChannelIO::subscriptionUpdate ( unsigned type, unsigned long count this->serviceIO.subscriptionUpdate ( this->addr, type, count, pfl, notify ); } -inline void dbChannelIO::lock () const -{ - dbScanLock ( this->addr.precord ); -} - -inline void dbChannelIO::unlock () const -{ - dbScanUnlock ( this->addr.precord ); -} - inline dbEventSubscription dbChannelIO::subscribe ( dbSubscriptionIO &subscr, unsigned mask ) { return this->serviceIO.subscribe ( this->addr, subscr, mask ); diff --git a/src/db/dbNotifyBlockerIL.h b/src/db/dbNotifyBlockerIL.h index af8a82d4c..e38dabdf8 100644 --- a/src/db/dbNotifyBlockerIL.h +++ b/src/db/dbNotifyBlockerIL.h @@ -15,16 +15,6 @@ * 505 665 1831 */ -inline void dbPutNotifyBlocker::lock () const -{ - this->chan.lock (); -} - -inline void dbPutNotifyBlocker::unlock () const -{ - this->chan.unlock (); -} - inline void dbPutNotifyBlocker::destroy () { delete this; @@ -32,10 +22,12 @@ inline void dbPutNotifyBlocker::destroy () inline void * dbPutNotifyBlocker::operator new ( size_t size ) { + epicsAutoMutex locker ( dbPutNotifyBlocker::freeListMutex ); return dbPutNotifyBlocker::freeList.allocate ( size ); } inline void dbPutNotifyBlocker::operator delete ( void *pCadaver, size_t size ) { + epicsAutoMutex locker ( dbPutNotifyBlocker::freeListMutex ); dbPutNotifyBlocker::freeList.release ( pCadaver, size ); } diff --git a/src/db/dbPutNotifyBlocker.cpp b/src/db/dbPutNotifyBlocker.cpp index d735c3e40..2538a23fb 100644 --- a/src/db/dbPutNotifyBlocker.cpp +++ b/src/db/dbPutNotifyBlocker.cpp @@ -37,6 +37,7 @@ #define S_db_Pending (M_dbAccess|37) tsFreeList dbPutNotifyBlocker::freeList; +epicsMutex dbPutNotifyBlocker::freeListMutex; dbPutNotifyBlocker::dbPutNotifyBlocker ( dbChannelIO &chanIn ) : pPN (0), chan ( chanIn ) @@ -45,18 +46,16 @@ dbPutNotifyBlocker::dbPutNotifyBlocker ( dbChannelIO &chanIn ) : dbPutNotifyBlocker::~dbPutNotifyBlocker () { - this->lock (); + dbAutoScanLockCA ( this->chan ); if ( this->pPN ) { - this->pPN->destroy (); + this->pPN->cancel (); } - this->unlock (); } void dbPutNotifyBlocker::putNotifyDestroyNotify () { - this->lock (); + dbAutoScanLockCA ( this->chan ); this->pPN = 0; - this->unlock (); } dbChannelIO & dbPutNotifyBlocker::channel () const @@ -73,38 +72,38 @@ int dbPutNotifyBlocker::initiatePutNotify ( cacNotify ¬ify, return ECA_ALLOCMEM; } - // wait for current put notify to complete - this->lock (); - if ( this->pPN ) { - epicsTime begin = epicsTime::getCurrent (); - do { - this->unlock (); - this->block.wait ( 1.0 ); - if ( epicsTime::getCurrent () - begin > 30.0 ) { - pIO->destroy (); - return ECA_PUTCBINPROG; + while ( true ) { + { + dbAutoScanLockCA ( this->chan ); + if ( ! this->pPN ) { + this->pPN = pIO; + int status = this->pPN->initiate ( addr, type, count, pValue ); + if ( status != ECA_NORMAL ) { + pIO->cancel (); + this->pPN = 0; + } + return status; } - this->lock (); - } while ( this->pPN ); + } + // wait for put notify in progress to complete + this->block.wait ( 1.0 ); + epicsTime begin = epicsTime::getCurrent (); + if ( epicsTime::getCurrent () - begin > 30.0 ) { + pIO->cancel (); + return ECA_PUTCBINPROG; + } } - this->pPN = pIO; - int status = this->pPN->initiate ( addr, type, count, pValue ); - if ( status != ECA_NORMAL ) { - this->pPN->destroy (); - this->pPN = 0; - } - this->unlock (); - return status; } extern "C" void putNotifyCompletion ( putNotify *ppn ) { dbPutNotifyBlocker *pBlocker = static_cast < dbPutNotifyBlocker * > ( ppn->usrPvt ); - pBlocker->lock (); - pBlocker->pPN->completion (); - pBlocker->pPN->destroy (); - pBlocker->pPN = 0; - pBlocker->unlock (); + { + dbAutoScanLockCA ( pBlocker->chan ); + pBlocker->pPN->completion (); + pBlocker->pPN->cancel (); + pBlocker->pPN = 0; + } pBlocker->block.signal (); }