From 889d8bc6c2ec7f7c3fb3f45f4ccb23aa7de9b510 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Thu, 23 Sep 2004 00:24:04 +0000 Subject: [PATCH] fixed potential race on SMP systems --- src/libCom/timer/timer.cpp | 64 ++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/src/libCom/timer/timer.cpp b/src/libCom/timer/timer.cpp index 0c17fd72f..dbbf7cb9d 100644 --- a/src/libCom/timer/timer.cpp +++ b/src/libCom/timer/timer.cpp @@ -136,43 +136,41 @@ void timer::privateStart ( epicsTimerNotify & notify, const epicsTime & expire ) void timer::cancel () { - if ( this->curState == statePending || this->curState == stateActive ) { - bool reschedual = false; - bool wakeupCancelBlockingThreads = false; - { - epicsGuard < epicsMutex > locker ( this->queue.mutex ); - this->pNotify = 0; - if ( this->curState == statePending ) { - this->queue.timerList.remove ( *this ); - this->curState = stateLimbo; - if ( this->queue.timerList.first() == this && - this->queue.timerList.count() > 0 ) { - reschedual = true; - } - } - else if ( this->curState == stateActive ) { - this->queue.cancelPending = true; - this->curState = timer::stateLimbo; - if ( this->queue.processThread != epicsThreadGetIdSelf() ) { - // make certain timer expire() does not run after cancel () returns, - // but dont require that lock is applied while calling expire() - while ( this->queue.cancelPending && - this->queue.pExpireTmr == this ) { - epicsGuardRelease < epicsMutex > autoRelease ( locker ); - this->queue.cancelBlockingEvent.wait (); - } - // in case other threads are waiting - wakeupCancelBlockingThreads = true; - } + bool reschedual = false; + bool wakeupCancelBlockingThreads = false; + { + epicsGuard < epicsMutex > locker ( this->queue.mutex ); + this->pNotify = 0; + if ( this->curState == statePending ) { + this->queue.timerList.remove ( *this ); + this->curState = stateLimbo; + if ( this->queue.timerList.first() == this && + this->queue.timerList.count() > 0 ) { + reschedual = true; } } - if ( reschedual ) { - this->queue.notify.reschedule (); - } - if ( wakeupCancelBlockingThreads ) { - this->queue.cancelBlockingEvent.signal (); + else if ( this->curState == stateActive ) { + this->queue.cancelPending = true; + this->curState = timer::stateLimbo; + if ( this->queue.processThread != epicsThreadGetIdSelf() ) { + // make certain timer expire() does not run after cancel () returns, + // but dont require that lock is applied while calling expire() + while ( this->queue.cancelPending && + this->queue.pExpireTmr == this ) { + epicsGuardRelease < epicsMutex > autoRelease ( locker ); + this->queue.cancelBlockingEvent.wait (); + } + // in case other threads are waiting + wakeupCancelBlockingThreads = true; + } } } + if ( reschedual ) { + this->queue.notify.reschedule (); + } + if ( wakeupCancelBlockingThreads ) { + this->queue.cancelBlockingEvent.signal (); + } } epicsTimer::expireInfo timer::getExpireInfo () const