Re: [PATCH] No idle HZ aka dynticks i386 for 2.6.16-rc4

From: Benjamin LaHaise
Date: Sat Feb 25 2006 - 09:23:40 EST


On Sat, Feb 25, 2006 at 03:30:57PM +1100, Con Kolivas wrote:
> +struct dyntick_timer {
> + spinlock_t lock;
> +
> + /* dyntick init */
> + int (*arch_init)(void);
> + /* Enables dynamic tick */
> + int (*arch_enable)(void);
> + /* Disables dynamic tick */
> + int (*arch_disable)(void);
> + /* Reprograms the timer */
> + void (*arch_reprogram)(unsigned long);
> + /* Function called when all cpus are idle, passing the idle duration */
> + void (*arch_all_cpus_idle)(unsigned int);
> +
> + unsigned short state; /* Current state */
> + unsigned int min_skip; /* Min number of ticks to skip */
> + unsigned int max_skip; /* Max number of ticks to skip */
> + unsigned long tick; /* The next earliest tick */
> +};

If you make min_skip a short here, the structure will pack nicely and
save 6 bytes of padding on 64 bit machines. Alternatively, keep it an
int and put it in the padding following the spinlock to save the whole
8 bytes.

> +int dyntick_skipping(void)
> +{
> + int ret = (get_cpu_var(dyn_cpu).next_tick > jiffies);
> +
> + put_cpu_var(dyn_cpu);
> + return ret;
>

This looks wrong... Shouldn't it be time_after()? Otherwise it seems to
not work when jiffies wraps.

> +int dyntick_current_skip(void)
> +{
> + int ret = 0;
> +
> + if (get_cpu_var(dyn_cpu).next_tick > jiffies)
> + ret = __get_cpu_var(dyn_cpu).skip;
> + put_cpu_var(dyn_cpu);
> + return ret;
> +}

Ditto.


> +/*
> + * Returns the next scheduled dyntick if we are skipping ticks.
> + */
> +unsigned long dyntick_next_tick(void)
> +{
> + unsigned long next = 0;
> +
> + if (get_cpu_var(dyn_cpu).next_tick > jiffies)
> + next = __get_cpu_var(dyn_cpu).next_tick;
> + put_cpu_var(dyn_cpu);
> + return next;
> +}

Ditto.

> +/*
> + * dyn_early_reprogram is used to reprogram an earlier tick than is currently
> + * set by timer_dyn_reprogram.
> + * dyn_early_reprogram allows other code such as the acpi idle code to
> + * program an earlier tick than the one already chosen by timer_dyn_reprogram.
> + * It only reprograms it if the tick is earlier than the next one planned.
> + */
> +void dyn_early_reprogram(unsigned int delta)
> +{
> + unsigned long flags, tick = jiffies + delta;
> +
> + if (tick >= get_cpu_var(dyn_cpu).next_tick &&
> + __get_cpu_var(dyn_cpu).next_tick > jiffies)
> + goto put_out;

Ditto.

The SMP case requires a bit more thorough reading... It seems there
are a few places that call test_nohz_cpu() without taking the spinlock.
That could be the race causing missed ticks on smp. Cheers,

-ben
--
"Ladies and gentlemen, I'm sorry to interrupt, but the police are here
and they've asked us to stop the party." Don't Email: <dont@xxxxxxxxx>.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/