On Feb 12, 2013, at 12:45 PM, "Cohen, Eugene" <[email protected]> wrote:

> Ø  It seems like a tradeoff of masking interrupts for a very very long time 
> or realizing that you may delay an entire timer tick.
>  
> The window can probably be narrowed substantially by maintaining a global 
> like BOOLEAN gEventFired that you clear at the beginning of the loop and 
> check afterwards with interrupts off.  That way we can eliminate the race 
> condition without holding off interrupts longer than a few cycles.


It may be possible to track EFI System time and skip the CoreSignalEvent 
(gIdleLoopEvent); call if time updates during the loop. 

The EFI System time could be retrieved via CoreCurrentSystemTime(). This would 
remove the need to mask the interrupts and I guess this would be OK. 



>  
> Ø  The common case for WaitForEvent() would be sitting at the shell prompt
>  
> Agreed that this is the most common case but there’s no reason events can be 
> used for IO paths (at least for those protocols that make use of events).

Well generally it is the main thread or application that does the 
WaitForEvent(). 

Thanks,

Andrew Fish

>  
> Eugene
>  
>  
> From: Andrew Fish [mailto:[email protected]] 
> Sent: Tuesday, February 12, 2013 1:37 PM
> To: [email protected]
> Subject: Re: [edk2] WaitForEvent Idle Race Condition
>  
> Eugene, 
>  
> I think this is the way it works. CoreCheckEvent() and CoreSignalEven() both 
> have locks that raise to TPL_HIGH_LEVEL. But we never signal (call an events 
> Notify Function) an event at TPL_HIGH_LEVEL.
> 
> 
> What if NumberOfEvents > 1 and the 1st event is checked, and then a timer 
> tick happens that makes the 1st event complete? So your ">> what if a timer 
> tick happens here?? <<" window is quite large. It seems like a tradeoff of 
> masking interrupts for a very very long time or realizing that you may delay 
> an entire timer tick. Given the point is to save power waiting a little extra 
> time helps save power. There will always be a tradeoff between saving power 
> and performance.
> 
> 
> You could chose not to implement the gIdleLoopEventGuid for your platform if 
> you are concerned about high performance in a WaitForEvent(). You could also 
> crank up your timer period.
> 
> 
> The common case for WaitForEvent() would be sitting at the shell prompt (or 
> the message loop for some GUI UI). You burn a lot of power doing nothing 
> (running C code that will not accomplish anything until the next tick). Since 
> you are generally waiting for a human they generally will not notice that you 
> were in a lower power state for an extra tick. We are boot firmware and not 
> an RTOS after all ,and we have a signal model, not threads.
>  
> Andrew Fish
>  
> https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2/MdeModulePkg/Core/Dxe/Event/Event.c
>  
> On Feb 12, 2013, at 11:05 AM, "Cohen, Eugene" <[email protected]> wrote:
> 
> 
> 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 ).
>  
>  
> If you have more knowledge about the X64 processor you can do better than 
> Halt , also called C1 (C0 is running). That CPU specific driver can also set 
> up P states, basically how much power gets used in C0.  
> 
> 
> Eugene
>  
>  
> ------------------------------------------------------------------------------
> Free Next-Gen Firewall Hardware Offer
> Buy your Sophos next-gen firewall before the end March 2013 
> and get the hardware for free! Learn more.
> http://p.sf.net/sfu/sophos-d2d-feb_______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/edk2-devel

------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to