Hi,

On Tue, Jan 10, 2006 at 12:12:56PM +0800, Shaohua Li wrote:
> Enhancements:
> 1. it does all policy calculation before going into idle, so other tasks
> can be quickly scheduled after idle.

This is much more tricky:

if CONFIG_PREEMPTION isn't set, this is (mostly) correct.

IDLE:
        acpi_processor_idle()
        {
                local_irq_disable()
                ... -> pre_cx()
                ? need_resched()
                ENTER_CSTATE
                local_irq_enable()
                ... -> post_cx()
        }

However: all calculations are done with IRQs -- needlessly -- off. All IRQs
appearing between local_irq_disable() and ENTER_CSTATE will cause a failed
transition, and only be handled afterwards. And that's bad for two reasons:
firstly it took some time until we handled the IRQ, secondly because failed
transitions into C-States cost time and power and thus energy. Therefore,
the span between the putting IRQs off and entering the C-State must be quite
small.

Also, if CONFIG_PREEMTPION is set, something else happens: the idle task's
instruction pointer points right after the "local_irq_enable()" call. As
once we enabled IRQs, we also allowed the lowest-priority idle thread to be
preempted by any other process wanting to run. Therefore, once the system
becomes idle, we'll first do the "->post_cx()" calculation (with IRQs
off!) before going back to the loop which calls acpi_processor_idle()
again, and only then IRQs are disabled, "->pre_cx()" is called, and so on.

As the behaviour is so totally different whether CONFIG_PREEMPTION is set or
not, I'd suggest the following (untested): add a "schedule()" right after
"local_irq_enable()". This will force the same behaviour as
CONFIG_PREEMPTION does currently also for the !CONFIG_PREEMTPION case.

> It's still not very good. Comments/suggestions are highly appreciated.
Take a look at my four patches, please, and all the tricks and tweaks they
do ;-)

> +     while (diff) {
> +             /* if we didn't get called, assume there was busmaster activity 
> */
... this turned out to be a bad  idea, especially with dyn ticks enabled.

> +             diff --;
> +             if (diff)
> +                     pr->power.bm_activity |= 0x1;
> +             pr->power.bm_activity <<= 1;
> +     }
> +
> +     if (bm_status) {
> +             pr->power.bm_activity++;
|= 0x1 not ++;


Also, the actual checking for bm_activity should be common code, e.g.

int acpi_processor_is_there_bm_activity()
{
        if (...)
                return 1;
        return 0;
}


Thanks,
        Dominik
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to