fixed potential race on SMP systems

This commit is contained in:
Jeff Hill
2004-09-23 00:24:04 +00:00
parent 1584471439
commit 889d8bc6c2

View File

@@ -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