Re: [PATCH] scheduler: fix x86 regression in native_sched_clock

From: Ingo Molnar
Date: Fri Dec 07 2007 - 07:12:05 EST



* stefano.brivio@xxxxxxxxx <stefano.brivio@xxxxxxxxx> wrote:

>> It's a single CPU box, so sched_clock() jumping would still be
>> problematic, no?
>
> I guess so. Definitely, it didn't look like a printk issue. Drivers
> don't read logs, usually. But they got confused anyway (it seems that
> udelay's get scaled or fail or somesuch - I can't test it right now,
> will provide more feedback in a few hours).

no, i think it's just another aspect of the broken TSC on that hardware.
Does the patch below improve things?

Ingo

------------------->
Subject: x86: cpu_clock() based udelay
From: Ingo Molnar <mingo@xxxxxxx>

use cpu_clock() for TSC based udelay - it's more reliable than raw
TSC based delay loops.

Signed-off-by: Ingo Molnar <mingo@xxxxxxx>
---
arch/x86/lib/delay_32.c | 20 ++++++++++++--------
arch/x86/lib/delay_64.c | 27 ++++++++++++++++++---------
2 files changed, 30 insertions(+), 17 deletions(-)

Index: linux/arch/x86/lib/delay_32.c
===================================================================
--- linux.orig/arch/x86/lib/delay_32.c
+++ linux/arch/x86/lib/delay_32.c
@@ -38,17 +38,21 @@ static void delay_loop(unsigned long loo
:"0" (loops));
}

-/* TSC based delay: */
+/* cpu_clock() [TSC] based delay: */
static void delay_tsc(unsigned long loops)
{
- unsigned long bclock, now;
+ unsigned long long start, stop, now;
+ int this_cpu;
+
+ preempt_disable();
+
+ this_cpu = smp_processor_id();
+ start = now = cpu_clock(this_cpu);
+ stop = start + loops;
+
+ while ((long long)(stop - now) > 0)
+ now = cpu_clock(this_cpu);

- preempt_disable(); /* TSC's are per-cpu */
- rdtscl(bclock);
- do {
- rep_nop();
- rdtscl(now);
- } while ((now-bclock) < loops);
preempt_enable();
}

Index: linux/arch/x86/lib/delay_64.c
===================================================================
--- linux.orig/arch/x86/lib/delay_64.c
+++ linux/arch/x86/lib/delay_64.c
@@ -26,19 +26,28 @@ int read_current_timer(unsigned long *ti
return 0;
}

-void __delay(unsigned long loops)
+/* cpu_clock() [TSC] based delay: */
+static void delay_tsc(unsigned long loops)
{
- unsigned bclock, now;
+ unsigned long long start, stop, now;
+ int this_cpu;
+
+ preempt_disable();
+
+ this_cpu = smp_processor_id();
+ start = now = cpu_clock(this_cpu);
+ stop = start + loops;
+
+ while ((long long)(stop - now) > 0)
+ now = cpu_clock(this_cpu);

- preempt_disable(); /* TSC's are pre-cpu */
- rdtscl(bclock);
- do {
- rep_nop();
- rdtscl(now);
- }
- while ((now-bclock) < loops);
preempt_enable();
}
+
+void __delay(unsigned long loops)
+{
+ delay_tsc(loops);
+}
EXPORT_SYMBOL(__delay);

inline void __const_udelay(unsigned long xloops)
--
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/