how are callouts handled in cpu_idle() ?

Alexander Motin mav at
Sat Oct 1 09:52:14 UTC 2011


Adrian Chadd wrote:
> What happens if this occurs:
> * cpu_idle() is entered
> * you enter critical_enter() and call cpu_idleclock()
> * an interrupt occurs, scheduling an immediate callout
> * .. but you've already set the clock register, so it won't be
> serviced until the wait returns.
> Perhaps interrupts have to be disabled before critical_enter() and
> cpu_idletick() to ensure an interrupt-driven callout doesn't get
> delayed?

Use of critical section in cpu_idle() from the beginning was based on
number of assumptions about filter interrupt handler's limitations.
These handlers are not guarantied to get updated system time/ticks and
they are discouraged to use callouts. If callout scheduled from
interrupt filter during system wake up, system has no ticks counter
updated yet and you may get callout scheduled into the past (it will be
run immediately) or at least much earlier (up to 250ms) then requested.
In your case callout indeed may get delayed (up to the same 250ms). All
that is not a problem for regular interrupt threaded interrupts --
interrupt thread execution will be delayed until all stuff get updated.

On some platforms and CPUs it is possible to enter/exit sleep with
interrupts disabled. That would allow to cover all kinds of problems,
but that support is very selective, so it is not used for this purpose
now. We may want to get cpu_idle() rewritten again at some time to
handle that and possibly make code choosing sleep state and measuring
sleep time more MI, like Linux does it, but that is another project.

So, if you really need to use callout() in interrupt filter, we could
disable interrupts before calling cpu_idleclock(), as you have told. But
that is only a partial solution and you should be ready for the second
half of the problems. Depending on your needs I am not sure it will
satisfy you.

Alexander Motin

More information about the freebsd-hackers mailing list