diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-06-16 11:28:04 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-06-16 11:28:04 +0200 |
commit | 7aaaec38fcd9ef3172e69f8c19f20113830a8498 (patch) | |
tree | b12a1c359ad53ae10601f77b3438bb27c3c8f337 /arch/x86/lib/delay_32.c | |
parent | 1ac97018169c5a13feaa90d9671f2d6ba2d9e86e (diff) | |
parent | 066519068ad2fbe98c7f45552b1f592903a9c8c8 (diff) |
Merge branch 'linus' into x86/kconfigtip-x86-kconfig-2008-06-16_09.28_Mon
Diffstat (limited to 'arch/x86/lib/delay_32.c')
-rw-r--r-- | arch/x86/lib/delay_32.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/arch/x86/lib/delay_32.c b/arch/x86/lib/delay_32.c index 4535e6d147ad..d710f2d167bb 100644 --- a/arch/x86/lib/delay_32.c +++ b/arch/x86/lib/delay_32.c @@ -44,13 +44,36 @@ static void delay_loop(unsigned long loops) static void delay_tsc(unsigned long loops) { unsigned long bclock, now; + int cpu; - preempt_disable(); /* TSC's are per-cpu */ + preempt_disable(); + cpu = smp_processor_id(); rdtscl(bclock); - do { - rep_nop(); + for (;;) { rdtscl(now); - } while ((now-bclock) < loops); + if ((now - bclock) >= loops) + break; + + /* Allow RT tasks to run */ + preempt_enable(); + rep_nop(); + preempt_disable(); + + /* + * It is possible that we moved to another CPU, and + * since TSC's are per-cpu we need to calculate + * that. The delay must guarantee that we wait "at + * least" the amount of time. Being moved to another + * CPU could make the wait longer but we just need to + * make sure we waited long enough. Rebalance the + * counter for this CPU. + */ + if (unlikely(cpu != smp_processor_id())) { + loops -= (now - bclock); + cpu = smp_processor_id(); + rdtscl(bclock); + } + } preempt_enable(); } |