diff --git a/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp b/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp index f89d7c0a7..b1057884d 100644 --- a/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp +++ b/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp @@ -36,14 +36,15 @@ ipAddrToAsciiEngine::~ipAddrToAsciiEngine () this->threadExit.wait (); // force IO completion for any items that remain - ipAddrToAsciiEngine::mutex.lock (); - while ( ( pItem = this->labor.first () ) ) { - pItem->pEngine = 0u; - sockAddrToA ( &pItem->addr.sa, this->nameTmp, - sizeof ( this->nameTmp ) ); - pItem->ioCompletionNotify ( this->nameTmp ); + { + epicsAutoMutex locker ( ipAddrToAsciiEngine::mutex ); + while ( ( pItem = this->labor.first () ) ) { + pItem->pEngine = 0u; + sockAddrToA ( &pItem->addr.sa, this->nameTmp, + sizeof ( this->nameTmp ) ); + pItem->ioCompletionNotify ( this->nameTmp ); + } } - ipAddrToAsciiEngine::mutex.unlock (); delete &thread; } @@ -54,37 +55,37 @@ void ipAddrToAsciiEngine::run () while ( ! this->exitFlag ) { while ( true ) { - ipAddrToAsciiEngine::mutex.lock (); - ipAddrToAsciiAsynchronous * pItem = this->labor.first (); - if ( pItem ) { - addr = pItem->addr; - tmpId = pItem->id; + { + epicsAutoMutex locker ( ipAddrToAsciiEngine::mutex ); + ipAddrToAsciiAsynchronous * pItem = this->labor.first (); + if ( pItem ) { + addr = pItem->addr; + tmpId = pItem->id; + } + else { + break; + } } - else { - this->mutex.unlock (); - break; - } - ipAddrToAsciiEngine::mutex.unlock (); // knowing DNS, this could take a very long time sockAddrToA ( &addr.sa, this->nameTmp, sizeof ( this->nameTmp ) ); - ipAddrToAsciiEngine::mutex.lock (); - pItem = this->labor.get (); - if ( pItem ) { - if ( tmpId == pItem->id ) { - pItem->ioCompletionNotify ( this->nameTmp ); - pItem->pEngine = 0u; + { + epicsAutoMutex locker ( ipAddrToAsciiEngine::mutex ); + ipAddrToAsciiAsynchronous * pItem = this->labor.get (); + if ( pItem ) { + if ( tmpId == pItem->id ) { + pItem->ioCompletionNotify ( this->nameTmp ); + pItem->pEngine = 0u; + } + else { + this->labor.push ( *pItem ); + } } else { - this->labor.push ( *pItem ); + break; } } - else { - ipAddrToAsciiEngine::mutex.unlock (); - break; - } - ipAddrToAsciiEngine::mutex.unlock (); } this->event.wait (); } @@ -93,7 +94,7 @@ void ipAddrToAsciiEngine::run () void ipAddrToAsciiEngine::show ( unsigned level ) const { - this->mutex.lock (); + epicsAutoMutex locker ( ipAddrToAsciiEngine::mutex ); printf ( "ipAddrToAsciiEngine at %p with %u requests pendingh\n", static_cast (this), this->labor.count () ); if ( level > 0u ) { @@ -113,7 +114,6 @@ void ipAddrToAsciiEngine::show ( unsigned level ) const printf ( "exit event:\n" ); this->threadExit.show ( level - 2u ); } - this->mutex.unlock (); } ipAddrToAsciiAsynchronous::ipAddrToAsciiAsynchronous @@ -124,29 +124,29 @@ ipAddrToAsciiAsynchronous::ipAddrToAsciiAsynchronous ipAddrToAsciiAsynchronous::~ipAddrToAsciiAsynchronous () { - ipAddrToAsciiEngine::mutex.lock (); + epicsAutoMutex locker ( ipAddrToAsciiEngine::mutex ); if ( this->pEngine ) { this->pEngine->labor.remove ( *this ); } - ipAddrToAsciiEngine::mutex.unlock (); } epicsShareFunc bool ipAddrToAsciiAsynchronous::ioInitiate ( ipAddrToAsciiEngine &engine ) { bool success; - ipAddrToAsciiEngine::mutex.lock (); - // put some reasonable limit on queue expansion - if ( engine.labor.count () < 16u ) { - this->id = engine.nextId++; - this->pEngine = &engine; - engine.labor.add ( *this ); - success = true; + { + epicsAutoMutex locker ( ipAddrToAsciiEngine::mutex ); + // put some reasonable limit on queue expansion + if ( engine.labor.count () < 16u ) { + this->id = engine.nextId++; + this->pEngine = &engine; + engine.labor.add ( *this ); + success = true; + } + else { + success = false; + } } - else { - success = false; - } - ipAddrToAsciiEngine::mutex.unlock (); if ( success ) { engine.event.signal (); @@ -159,12 +159,11 @@ void ipAddrToAsciiAsynchronous::show ( unsigned level ) const { char ipAddr [64]; - ipAddrToAsciiEngine::mutex.lock (); + epicsAutoMutex locker ( ipAddrToAsciiEngine::mutex ); sockAddrToA ( &this->addr.sa, ipAddr, sizeof ( ipAddr ) ); printf ( "ipAddrToAsciiAsynchronous for address %s\n", ipAddr ); if ( level > 0u ) { printf ( "\tidentifier %u, engine %p\n", this->id, static_cast (this->pEngine) ); } - ipAddrToAsciiEngine::mutex.unlock (); } diff --git a/src/libCom/timer/epicsTimer.cpp b/src/libCom/timer/epicsTimer.cpp index 5082c5bd7..793dc3be9 100644 --- a/src/libCom/timer/epicsTimer.cpp +++ b/src/libCom/timer/epicsTimer.cpp @@ -45,6 +45,7 @@ private: void * pPrivate; expireStatus expire (); static tsFreeList < epicsTimerForC > freeList; + static epicsMutex freeListMutex; }; struct epicsTimerQueuePassiveForC : public epicsTimerQueueNotify, public timerQueuePassive { @@ -60,11 +61,13 @@ private: void *pPrivate; void reschedule (); static tsFreeList < epicsTimerQueuePassiveForC > freeList; + static epicsMutex freeListMutex; }; void epicsTimerNotify::show ( unsigned /* level */ ) const {} tsFreeList < epicsTimerForC > epicsTimerForC::freeList; +epicsMutex epicsTimerForC::freeListMutex; epicsTimerForC::epicsTimerForC ( timerQueue &queue, epicsTimerCallback pCBIn, void *pPrivateIn ) : timer ( *this, queue ), pCallBack ( pCBIn ), pPrivate ( pPrivateIn ) @@ -82,11 +85,13 @@ inline void epicsTimerForC::destroy () inline void * epicsTimerForC::operator new ( size_t size ) { + epicsAutoMutex locker ( epicsTimerForC::freeListMutex ); return epicsTimerForC::freeList.allocate ( size ); } inline void epicsTimerForC::operator delete ( void *pCadaver, size_t size ) { + epicsAutoMutex locker ( epicsTimerForC::freeListMutex ); epicsTimerForC::freeList.release ( pCadaver, size ); } @@ -97,6 +102,7 @@ epicsTimerNotify::expireStatus epicsTimerForC::expire () } tsFreeList < epicsTimerQueueForC > epicsTimerQueueForC::freeList; +epicsMutex epicsTimerQueueForC::freeListMutex; epicsTimerQueueForC::epicsTimerQueueForC ( bool okToShare, unsigned priority ) : timerQueueActive ( okToShare, priority ) @@ -113,14 +119,17 @@ void epicsTimerQueueForC::release () } tsFreeList < epicsTimerQueuePassiveForC > epicsTimerQueuePassiveForC::freeList; +epicsMutex epicsTimerQueuePassiveForC::freeListMutex; inline void * epicsTimerQueuePassiveForC::operator new ( size_t size ) { + epicsAutoMutex locker ( epicsTimerQueuePassiveForC::freeListMutex ); return epicsTimerQueuePassiveForC::freeList.allocate ( size ); } inline void epicsTimerQueuePassiveForC::operator delete ( void *pCadaver, size_t size ) { + epicsAutoMutex locker ( epicsTimerQueuePassiveForC::freeListMutex ); epicsTimerQueuePassiveForC::freeList.release ( pCadaver, size ); } diff --git a/src/libCom/timer/osiTimer.cpp b/src/libCom/timer/osiTimer.cpp index a323e069b..b29e3e1d6 100644 --- a/src/libCom/timer/osiTimer.cpp +++ b/src/libCom/timer/osiTimer.cpp @@ -87,9 +87,8 @@ osiTimer::osiTimer (double delay) : osiTimer::osiTimer (osiTimerQueue & queueIn) : curState (osiTimer::stateIdle), queue (queueIn) { - this->queue.mutex.lock (); + epicsAutoMutex ( this->queue.mutex ); this->queue.timerLists[stateIdle].add (*this); - this->queue.mutex.unlock (); } // @@ -100,9 +99,8 @@ curState (osiTimer::stateIdle), queue (queueIn) osiTimer::osiTimer () : curState (osiTimer::stateIdle), queue (osiDefaultTimerQueue) { - this->queue.mutex.lock (); + epicsAutoMutex ( this->queue.mutex ); this->queue.timerLists[stateIdle].add (*this); - this->queue.mutex.unlock (); } // @@ -114,7 +112,7 @@ osiTimer::~osiTimer() return; // queue was destroyed } - this->queue.mutex.lock (); + epicsAutoMutex ( this->queue.mutex ); // // signal the timer queue if this // occurring during the expire call @@ -125,7 +123,6 @@ osiTimer::~osiTimer() } this->queue.timerLists[this->curState].remove(*this); this->curState = stateLimbo; - this->queue.mutex.unlock (); } // @@ -137,22 +134,22 @@ void osiTimer::cancel () return; // queue was destroyed } - this->queue.mutex.lock (); + { + epicsAutoMutex ( this->queue.mutex ); - // - // signal the timer queue if this - // occurring during the expire call - // back - // - if (this == this->queue.pExpireTmr) { - this->queue.pExpireTmr = 0; - } + // + // signal the timer queue if this + // occurring during the expire call + // back + // + if (this == this->queue.pExpireTmr) { + this->queue.pExpireTmr = 0; + } - this->queue.timerLists[this->curState].remove (*this); - this->curState = stateIdle; - this->queue.timerLists[stateIdle].add (*this); - - this->queue.mutex.unlock (); + this->queue.timerLists[this->curState].remove (*this); + this->curState = stateIdle; + this->queue.timerLists[stateIdle].add (*this); + } this->destroy (); } @@ -180,7 +177,7 @@ void osiTimer::reschedule (double newDelay) return; // queue was destroyed } - this->queue.mutex.lock (); + epicsAutoMutex ( this->queue.mutex ); // // signal the timer queue if this @@ -193,8 +190,6 @@ void osiTimer::reschedule (double newDelay) this->queue.timerLists[this->curState].remove (*this); this->curState = stateLimbo; this->arm (newDelay); - - this->queue.mutex.unlock (); } // @@ -214,7 +209,7 @@ epicsShareFunc void osiTimer::activate ( double newDelay ) return; // queue was destroyed } - this->queue.mutex.lock (); + epicsAutoMutex ( this->queue.mutex ); if ( this->curState == stateIdle ) { // @@ -229,8 +224,6 @@ epicsShareFunc void osiTimer::activate ( double newDelay ) this->curState = stateLimbo; this->arm (newDelay); } - - this->queue.mutex.unlock (); } // @@ -241,78 +234,77 @@ void osiTimer::arm (double initialDelay) bool first; # ifdef DEBUG - unsigned preemptCount=0u; + unsigned preemptCount = 0u; # endif - this->queue.mutex.lock (); + { + epicsAutoMutex ( this->queue.mutex ); - // - // create manager thread on demand so we dont have threads hanging - // around that are not used - // - if ( ! this->queue.terminateFlag && this->queue.pMgrThread == NULL ) { - this->queue.pMgrThread = new osiTimerThread (this->queue, this->queue.mgrThreadPriority); - if ( this->queue.pMgrThread == NULL ) { - this->queue.mutex.unlock (); - throwWithLocation ( noMemory () ); + // + // create manager thread on demand so we dont have threads hanging + // around that are not used + // + if ( ! this->queue.terminateFlag && this->queue.pMgrThread == NULL ) { + this->queue.pMgrThread = new osiTimerThread (this->queue, this->queue.mgrThreadPriority); + if ( this->queue.pMgrThread == NULL ) { + throwWithLocation ( noMemory () ); + } } + + // + // calculate absolute expiration time + // + this->exp = epicsTime::getCurrent () + initialDelay; + + // + // insert into the pending queue + // + // Finds proper time sorted location using + // a linear search. + // + // **** this should use a binary tree ???? + // + tsDLIterBD iter = this->queue.timerLists[statePending].lastIter (); + while (1) { + if ( ! iter.valid () ) { + // + // add to the beginning of the list + // + this->queue.timerLists[statePending].push (*this); + first = true; + break; + } + if ( iter->exp <= this->exp ) { + // + // add after the item found that expires earlier + // + this->queue.timerLists[statePending].insertAfter (*this, *iter); + first = false; + break; + } +# ifdef DEBUG + preemptCount++; +# endif + --iter; + } + + this->curState = osiTimer::statePending; + +# ifdef DEBUG + this->show (10u); +# endif + +# ifdef DEBUG + // + // name virtual function isnt always useful here because this is + // often called inside the constructor (unless we are + // rearming the same timer) + // + printf ("Arm of \"%s\" with delay %f at %lx preempting %u\n", + this->name(), initialDelay, (unsigned long)this, preemptCount); + # endif } - // - // calculate absolute expiration time - // - this->exp = epicsTime::getCurrent () + initialDelay; - - // - // insert into the pending queue - // - // Finds proper time sorted location using - // a linear search. - // - // **** this should use a binary tree ???? - // - tsDLIterBD iter = this->queue.timerLists[statePending].lastIter (); - while (1) { - if ( ! iter.valid () ) { - // - // add to the beginning of the list - // - this->queue.timerLists[statePending].push (*this); - first = true; - break; - } - if ( iter->exp <= this->exp ) { - // - // add after the item found that expires earlier - // - this->queue.timerLists[statePending].insertAfter (*this, *iter); - first = false; - break; - } -# ifdef DEBUG - preemptCount++; -# endif - --iter; - } - - this->curState = osiTimer::statePending; - -# ifdef DEBUG - this->show (10u); -# endif - -# ifdef DEBUG - // - // name virtual function isnt always useful here because this is - // often called inside the constructor (unless we are - // rearming the same timer) - // - printf ("Arm of \"%s\" with delay %f at %lx preempting %u\n", - this->name(), initialDelay, (unsigned long)this, preemptCount); -# endif - - this->queue.mutex.unlock (); - if (first) { this->queue.rescheduleEvent.signal (); } @@ -380,8 +372,8 @@ double osiTimer::timeRemaining () const { double delay; + epicsAutoMutex ( this->queue.mutex ); - this->queue.mutex.lock (); switch (this->curState) { case statePending: delay = this->exp - epicsTime::getCurrent(); @@ -408,7 +400,6 @@ double osiTimer::timeRemaining () const delay = DBL_MAX; break; } - this->queue.mutex.unlock (); return delay; } @@ -468,12 +459,13 @@ void osiTimerQueue::terminateManagerThread () this->exitEvent.wait ( 1.0 ); } - this->mutex.lock (); - if ( this->pMgrThread ) { - delete this->pMgrThread; - this->pMgrThread = 0; + { + epicsAutoMutex ( this->mutex ); + if ( this->pMgrThread ) { + delete this->pMgrThread; + this->pMgrThread = 0; + } } - this->mutex.unlock (); // in case other threads are waiting here also this->exitEvent.signal (); @@ -516,7 +508,7 @@ double osiTimerQueue::delayToFirstExpire () const osiTimer *pTmr; double delay; - this->mutex.lock (); + epicsAutoMutex locker ( this->mutex ); pTmr = this->timerLists[osiTimer::statePending].first (); if (pTmr) { @@ -532,8 +524,6 @@ double osiTimerQueue::delayToFirstExpire () const delay = 30u * epicsTime::secPerMin; } - this->mutex.unlock (); - return delay; // seconds } @@ -632,7 +622,7 @@ void osiTimerQueue::privateProcess () // void osiTimerQueue::show(unsigned level) const { - this->mutex.lock(); + epicsAutoMutex locker ( this->mutex ); printf("osiTimerQueue with %u items pending and %u items expired\n", this->timerLists[osiTimer::statePending].count(), this->timerLists[osiTimer::stateExpired].count()); @@ -641,7 +631,6 @@ void osiTimerQueue::show(unsigned level) const iter->show(level); ++iter; } - this->mutex.unlock(); } extern "C" epicsShareFunc osiTimerQueueId epicsShareAPI osiTimerQueueCreate ( unsigned managerThreadPriority ) diff --git a/src/libCom/timer/osiTimer.h b/src/libCom/timer/osiTimer.h index a00d43f92..375bb8b09 100644 --- a/src/libCom/timer/osiTimer.h +++ b/src/libCom/timer/osiTimer.h @@ -189,7 +189,7 @@ public: epicsShareFunc void process (); epicsShareFunc void show (unsigned level) const; private: - epicsMutex mutex; + mutable epicsMutex mutex; epicsEvent rescheduleEvent; epicsEvent exitEvent; tsDLList timerLists [osiTimer::numberOfTimerLists]; diff --git a/src/libCom/timer/timer.cpp b/src/libCom/timer/timer.cpp index bfd69cd09..867b702cf 100644 --- a/src/libCom/timer/timer.cpp +++ b/src/libCom/timer/timer.cpp @@ -33,6 +33,7 @@ #include "timerPrivate.h" tsFreeList < class timer, 0x20 > timer::freeList; +epicsMutex timer::freeListMutex; epicsTimer::~epicsTimer () {} diff --git a/src/libCom/timer/timerPrivate.h b/src/libCom/timer/timerPrivate.h index 9a7335862..af5023bc8 100644 --- a/src/libCom/timer/timerPrivate.h +++ b/src/libCom/timer/timerPrivate.h @@ -64,6 +64,7 @@ private: void privateCancel (); double privateDelayToFirstExpire () const; static tsFreeList < class timer, 0x20 > freeList; + static epicsMutex freeListMutex; friend class timerQueue; }; @@ -129,6 +130,7 @@ protected: virtual ~epicsTimerQueueForC (); private: static tsFreeList < epicsTimerQueueForC > freeList; + static epicsMutex freeListMutex; }; class timerQueueActiveMgr { @@ -160,15 +162,18 @@ protected: private: timerQueue queue; static tsFreeList < class timerQueuePassive, 0x8 > freeList; + static epicsMutex freeListMutex; }; inline void * timer::operator new ( size_t size ) { + epicsAutoMutex locker ( timer::freeListMutex ); return timer::freeList.allocate ( size ); } inline void timer::operator delete ( void *pCadaver, size_t size ) { + epicsAutoMutex locker ( timer::freeListMutex ); timer::freeList.release ( pCadaver, size ); } @@ -203,11 +208,13 @@ inline timerQueue & timerQueueActive::getTimerQueue () inline void * timerQueuePassive::operator new ( size_t size ) { + epicsAutoMutex locker ( timerQueuePassive::freeListMutex ); return timerQueuePassive::freeList.allocate ( size ); } inline void timerQueuePassive::operator delete ( void *pCadaver, size_t size ) { + epicsAutoMutex locker ( timerQueuePassive::freeListMutex ); timerQueuePassive::freeList.release ( pCadaver, size ); } @@ -218,11 +225,13 @@ inline timerQueue & timerQueuePassive::getTimerQueue () inline void * epicsTimerQueueForC::operator new ( size_t size ) { + epicsAutoMutex locker ( epicsTimerQueueForC::freeListMutex ); return epicsTimerQueueForC::freeList.allocate ( size ); } inline void epicsTimerQueueForC::operator delete ( void *pCadaver, size_t size ) { + epicsAutoMutex locker ( epicsTimerQueueForC::freeListMutex ); epicsTimerQueueForC::freeList.release ( pCadaver, size ); } diff --git a/src/libCom/timer/timerQueuePassive.cpp b/src/libCom/timer/timerQueuePassive.cpp index d8ed2ddd1..dec565992 100644 --- a/src/libCom/timer/timerQueuePassive.cpp +++ b/src/libCom/timer/timerQueuePassive.cpp @@ -32,6 +32,7 @@ #include "timerPrivate.h" tsFreeList < class timerQueuePassive, 0x8 > timerQueuePassive::freeList; +epicsMutex timerQueuePassive::freeListMutex; epicsTimerQueuePassive::~epicsTimerQueuePassive () {}