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/module.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/preempt.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
@ -42,11 +43,13 @@ static void delay_tsc(unsigned long loops)
|
||||||
{
|
{
|
||||||
unsigned long bclock, now;
|
unsigned long bclock, now;
|
||||||
|
|
||||||
|
preempt_disable(); /* TSC's are per-cpu */
|
||||||
rdtscl(bclock);
|
rdtscl(bclock);
|
||||||
do {
|
do {
|
||||||
rep_nop();
|
rep_nop();
|
||||||
rdtscl(now);
|
rdtscl(now);
|
||||||
} while ((now-bclock) < loops);
|
} while ((now-bclock) < loops);
|
||||||
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/preempt.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
|
||||||
#include <asm/delay.h>
|
#include <asm/delay.h>
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
|
|
||||||
|
@ -28,13 +30,14 @@ void __delay(unsigned long loops)
|
||||||
{
|
{
|
||||||
unsigned bclock, now;
|
unsigned bclock, now;
|
||||||
|
|
||||||
|
preempt_disable(); /* TSC's are pre-cpu */
|
||||||
rdtscl(bclock);
|
rdtscl(bclock);
|
||||||
do
|
do {
|
||||||
{
|
|
||||||
rep_nop();
|
rep_nop();
|
||||||
rdtscl(now);
|
rdtscl(now);
|
||||||
}
|
}
|
||||||
while((now-bclock) < loops);
|
while ((now-bclock) < loops);
|
||||||
|
preempt_enable();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__delay);
|
EXPORT_SYMBOL(__delay);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче