aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/lib/delay_64.c
diff options
context:
space:
mode:
authorAndrew Morton <akpm@linux-foundation.org>2007-11-14 20:00:41 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-14 21:45:44 -0500
commit35d5d08a085c56f153458c3f5d8ce24123617faf (patch)
tree2db6e598e87809bc1ce7838861b2cff18e5fe60d /arch/x86/lib/delay_64.c
parent7eea436433b7b18045f272562e256976f593f7c0 (diff)
x86: disable preemption in delay_tsc()
Marin Mitov points out that delay_tsc() can misbehave if it is preempted and rescheduled on a different CPU which has a skewed TSC. Fix it by disabling preemption. (I assume that the worst-case behaviour here is a stall of 2^32 cycles) Cc: Andi Kleen <ak@suse.de> Cc: Marin Mitov <mitov@issp.bas.bg> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@elte.hu> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/x86/lib/delay_64.c')
-rw-r--r--arch/x86/lib/delay_64.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/arch/x86/lib/delay_64.c b/arch/x86/lib/delay_64.c
index 0ebbfb9e7c7f..45cdd3fbd91c 100644
--- a/arch/x86/lib/delay_64.c
+++ b/arch/x86/lib/delay_64.c
@@ -10,7 +10,9 @@
10 10
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/preempt.h>
13#include <linux/delay.h> 14#include <linux/delay.h>
15
14#include <asm/delay.h> 16#include <asm/delay.h>
15#include <asm/msr.h> 17#include <asm/msr.h>
16 18
@@ -27,14 +29,15 @@ int read_current_timer(unsigned long *timer_value)
27void __delay(unsigned long loops) 29void __delay(unsigned long loops)
28{ 30{
29 unsigned bclock, now; 31 unsigned bclock, now;
30 32
33 preempt_disable(); /* TSC's are pre-cpu */
31 rdtscl(bclock); 34 rdtscl(bclock);
32 do 35 do {
33 {
34 rep_nop(); 36 rep_nop();
35 rdtscl(now); 37 rdtscl(now);
36 } 38 }
37 while((now-bclock) < loops); 39 while ((now-bclock) < loops);
40 preempt_enable();
38} 41}
39EXPORT_SYMBOL(__delay); 42EXPORT_SYMBOL(__delay);
40 43