[if gte mso 9]>

[edk2] WaitForEvent Idle Race Condition

Subject: [edk2] WaitForEvent Idle Race Condition

From: "Cohen, Eugene" <eugene@hp.com>

To: "edk2-devel@lists.sourceforge.net" <edk2-devel@lists.sourceforge.net>

Date: 2013-02-13 03:05:06

It appears that there is a race condition in WaitForEvent... after all events are checked the idle event is signaled.  But if a timer tick interrupt comes in and schedules work (SignalEvent) after the loop is done but before the event is signaled, we will delay unnecessarily for an additional timer tick interrupt (due to an HLT or WFI) before the event is recognized.  This could have a performance impact if WaitForEvent is used in a tight loop waiting for IO.

 

  for(;;) {

 

    for(Index = 0; Index < NumberOfEvents; Index++) {

 

      Status = CoreCheckEvent (UserEvents[Index]);

 

      //

      // provide index of event that caused problem

      //

      if (Status != EFI_NOT_READY) {

        *UserIndex = Index;

        return Status;

      }

    }

 

     >> what if a timer tick happens here?? <<

 

    //

    // Signal the Idle event

    //

    CoreSignalEvent (gIdleLoopEvent);

  }

}

 

I think the solution is that interrupts must be disabled while deciding if there is work to do.  It looks like ARM, IA32, and X64 architectures have this exposure.

 

I researched if it possible to do WFI/HLT with interrupts masked off.  On ARM it is valid to issue a WFI with IRQ and FIQ masked off since it will unblock with pending (but masked interrupts).  On IA it’s a bit trickier since HLT will hang forever if interrupts are masked off.  From what I’ve read (although I could not find an authoritative statement in the IA documentation), the solution is that an ‘STI; HLT’ together will allow the halt to be bypassed if an interrupt is pending (see http://lists.freebsd.org/pipermail/freebsd-current/2004-June/029369.html ).

 

Eugene