aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/lib/delay_64.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-07 02:07:35 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-07 02:07:35 -0400
commitd763d5edf945eec47bd443b699f174976f0afc13 (patch)
tree3e5cd46b9a783999716bf92176854f4f1215d930 /arch/x86/lib/delay_64.c
parent790e2a290b499b0400254e6870ec27969065d122 (diff)
parent1b40a895df6c7d5a80e71f65674060b03d84bbef (diff)
Merge branch 'linus' into tracing/mmiotrace
Diffstat (limited to 'arch/x86/lib/delay_64.c')
-rw-r--r--arch/x86/lib/delay_64.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/arch/x86/lib/delay_64.c b/arch/x86/lib/delay_64.c
index bbc610518516..4c441be92641 100644
--- a/arch/x86/lib/delay_64.c
+++ b/arch/x86/lib/delay_64.c
@@ -31,14 +31,36 @@ int __devinit read_current_timer(unsigned long *timer_value)
31void __delay(unsigned long loops) 31void __delay(unsigned long loops)
32{ 32{
33 unsigned bclock, now; 33 unsigned bclock, now;
34 int cpu;
34 35
35 preempt_disable(); /* TSC's are pre-cpu */ 36 preempt_disable();
37 cpu = smp_processor_id();
36 rdtscl(bclock); 38 rdtscl(bclock);
37 do { 39 for (;;) {
38 rep_nop();
39 rdtscl(now); 40 rdtscl(now);
41 if ((now - bclock) >= loops)
42 break;
43
44 /* Allow RT tasks to run */
45 preempt_enable();
46 rep_nop();
47 preempt_disable();
48
49 /*
50 * It is possible that we moved to another CPU, and
51 * since TSC's are per-cpu we need to calculate
52 * that. The delay must guarantee that we wait "at
53 * least" the amount of time. Being moved to another
54 * CPU could make the wait longer but we just need to
55 * make sure we waited long enough. Rebalance the
56 * counter for this CPU.
57 */
58 if (unlikely(cpu != smp_processor_id())) {
59 loops -= (now - bclock);
60 cpu = smp_processor_id();
61 rdtscl(bclock);
62 }
40 } 63 }
41 while ((now-bclock) < loops);
42 preempt_enable(); 64 preempt_enable();
43} 65}
44EXPORT_SYMBOL(__delay); 66EXPORT_SYMBOL(__delay);