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>
This commit is contained in:
Родитель
7eea436433
Коммит
35d5d08a08
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
|
@ -42,11 +43,13 @@ static void delay_tsc(unsigned long loops)
|
|||
{
|
||||
unsigned long bclock, now;
|
||||
|
||||
preempt_disable(); /* TSC's are per-cpu */
|
||||
rdtscl(bclock);
|
||||
do {
|
||||
rep_nop();
|
||||
rdtscl(now);
|
||||
} while ((now-bclock) < loops);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/delay.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
|
@ -27,14 +29,15 @@ int read_current_timer(unsigned long *timer_value)
|
|||
void __delay(unsigned long loops)
|
||||
{
|
||||
unsigned bclock, now;
|
||||
|
||||
|
||||
preempt_disable(); /* TSC's are pre-cpu */
|
||||
rdtscl(bclock);
|
||||
do
|
||||
{
|
||||
do {
|
||||
rep_nop();
|
||||
rdtscl(now);
|
||||
}
|
||||
while((now-bclock) < loops);
|
||||
while ((now-bclock) < loops);
|
||||
preempt_enable();
|
||||
}
|
||||
EXPORT_SYMBOL(__delay);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче