mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
bitkeeper revision 1.137 (3e745d6egPhbuKyLs12XPZOtKEunKA)
schedule.c, ac_timer.c, time.c, apic.c: Some timer fixes.
This commit is contained in:
1 parent
93615cf273
commit
3350e93244
4 files changed
+51
-46
No files matched your search
+26
-23
@@ -19,15 +19,15 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Local APIC handling, local APIC timers
|
||||
* Local APIC handling, local APIC timers
|
||||
*
|
||||
* (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
|
||||
* (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
|
||||
*
|
||||
* Fixes
|
||||
* Maciej W. Rozycki : Bits for genuine 82489DX APICs;
|
||||
* thanks to Eric Gilmore
|
||||
* and Rolf G. Tews
|
||||
* for testing these extensively.
|
||||
* Fixes
|
||||
* Maciej W. Rozycki : Bits for genuine 82489DX APICs;
|
||||
* thanks to Eric Gilmore
|
||||
* and Rolf G. Tews
|
||||
* for testing these extensively.
|
||||
*/
|
||||
|
||||
|
||||
@@ -329,13 +329,13 @@ void __init setup_local_APIC (void)
|
||||
value = APIC_DM_NMI;
|
||||
else
|
||||
value = APIC_DM_NMI | APIC_LVT_MASKED;
|
||||
if (!APIC_INTEGRATED(ver)) /* 82489DX */
|
||||
if (!APIC_INTEGRATED(ver)) /* 82489DX */
|
||||
value |= APIC_LVT_LEVEL_TRIGGER;
|
||||
apic_write_around(APIC_LVT1, value);
|
||||
|
||||
if (APIC_INTEGRATED(ver)) { /* !82489DX */
|
||||
if (APIC_INTEGRATED(ver)) { /* !82489DX */
|
||||
maxlvt = get_maxlvt();
|
||||
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
|
||||
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
|
||||
apic_write(APIC_ESR, 0);
|
||||
value = apic_read(APIC_ESR);
|
||||
printk("ESR value before enabling vector: %08lx\n", value);
|
||||
@@ -653,25 +653,28 @@ void __init setup_APIC_clocks (void)
|
||||
*/
|
||||
int reprogram_ac_timer(s_time_t timeout)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
s_time_t now;
|
||||
s_time_t expire;
|
||||
u64 apic_tmict;
|
||||
int cpu = smp_processor_id();
|
||||
s_time_t now;
|
||||
s_time_t expire;
|
||||
u64 apic_tmict;
|
||||
|
||||
if (timeout == 0) {
|
||||
/* XXX RN: not sure if this disables it or cause interruptto
|
||||
* go off imediately */
|
||||
apic_tmict = 0;
|
||||
/*
|
||||
* We use this value because we don't trust zero (we think it may just
|
||||
* cause an immediate interrupt). At least this is guaranteed to hold it
|
||||
* off for ages (esp. since the clock ticks on bus clock, not cpu clock!).
|
||||
*/
|
||||
if (timeout == 0) {
|
||||
apic_tmict = 0xffffffff;
|
||||
goto reprogram;
|
||||
}
|
||||
|
||||
now = NOW();
|
||||
expire = timeout - now; /* value from now */
|
||||
expire = timeout - now; /* value from now */
|
||||
|
||||
if (expire <= 0) {
|
||||
printk("APICT[%02d] Timeout in the past 0x%08X%08X > 0x%08X%08X\n",
|
||||
cpu, (u32)(now>>32), (u32)now, (u32)(timeout>>32),(u32)timeout);
|
||||
return 0; /* timeout value in the past */
|
||||
return 0; /* timeout value in the past */
|
||||
}
|
||||
|
||||
/* conversion to bus units */
|
||||
@@ -687,7 +690,7 @@ int reprogram_ac_timer(s_time_t timeout)
|
||||
}
|
||||
|
||||
reprogram:
|
||||
/* programm timer */
|
||||
/* Program the timer. */
|
||||
apic_write(APIC_TMICT, (unsigned long)apic_tmict);
|
||||
|
||||
TRC(printk("APICT[%02d] reprog(): expire=%lld %u\n",
|
||||
@@ -755,9 +758,9 @@ void smp_apic_timer_interrupt(struct pt_regs * regs)
|
||||
*/
|
||||
ack_APIC_irq();
|
||||
|
||||
/* call the local handler */
|
||||
/* call the local handler */
|
||||
irq_enter(cpu, 0);
|
||||
perfc_incrc(apic_timer);
|
||||
perfc_incrc(apic_timer);
|
||||
smp_local_timer_interrupt(regs);
|
||||
irq_exit(cpu, 0);
|
||||
|
||||
|
||||
+13
-12
@@ -240,15 +240,12 @@ static u32 st_scale_i;
|
||||
u32 stime_pcc; /* cycle counter value at last timer irq */
|
||||
s_time_t stime_now; /* time in ns at last timer IRQ */
|
||||
|
||||
s_time_t get_s_time(void)
|
||||
static inline s_time_t __get_s_time(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 delta_tsc, low, pcc;
|
||||
u64 delta;
|
||||
s_time_t now;
|
||||
|
||||
spin_lock_irqsave(&stime_lock, flags);
|
||||
|
||||
pcc = stime_pcc;
|
||||
now = stime_now;
|
||||
|
||||
@@ -259,9 +256,17 @@ s_time_t get_s_time(void)
|
||||
delta >>= 32;
|
||||
delta += ((u64)delta_tsc * st_scale_i);
|
||||
|
||||
spin_unlock_irqrestore(&stime_lock, flags);
|
||||
return now + delta;
|
||||
}
|
||||
|
||||
return now + delta;
|
||||
s_time_t get_s_time(void)
|
||||
{
|
||||
s_time_t now;
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&stime_lock, flags);
|
||||
now = __get_s_time();
|
||||
spin_unlock_irqrestore(&stime_lock, flags);
|
||||
return now;
|
||||
}
|
||||
|
||||
|
||||
@@ -326,17 +331,13 @@ static struct ac_timer update_timer;
|
||||
static void update_time(unsigned long foo)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 new_pcc;
|
||||
s_time_t new_st;
|
||||
unsigned long usec;
|
||||
|
||||
new_st = NOW();
|
||||
rdtscl(new_pcc);
|
||||
|
||||
/* Update system time. */
|
||||
spin_lock_irqsave(&stime_lock, flags);
|
||||
stime_now = new_st;
|
||||
stime_pcc=new_pcc;
|
||||
stime_now = new_st = __get_s_time();
|
||||
rdtscl(stime_pcc);
|
||||
/* Don't reeenable IRQs until we release wctime_lock. */
|
||||
spin_unlock(&stime_lock);
|
||||
|
||||
|
||||
@@ -82,7 +82,9 @@ int add_ac_timer(struct ac_timer *timer)
|
||||
(u32)(timer->expires>>32), (u32)timer->expires));
|
||||
return 1;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ac_timers[cpu].lock, flags);
|
||||
|
||||
/*
|
||||
* Add timer to the list. If it gets added to the front we have to
|
||||
* reprogramm the timer
|
||||
@@ -154,8 +156,12 @@ int rem_ac_timer(struct ac_timer *timer)
|
||||
/* just removed the head */
|
||||
if (list_empty(&ac_timers[cpu].timers)) {
|
||||
reprogram_ac_timer((s_time_t) 0);
|
||||
} else {
|
||||
timer = list_entry(ac_timers[cpu].timers.next,
|
||||
struct ac_timer, timer_list);
|
||||
if ( timer->expires > (NOW() + TIMER_SLOP) )
|
||||
reprogram_ac_timer(timer->expires);
|
||||
}
|
||||
/* XXX should actaully reprogramm APIC to new head */
|
||||
}
|
||||
} else
|
||||
res = -1;
|
||||
@@ -201,13 +207,7 @@ void do_ac_timer(void)
|
||||
|
||||
/* Sanity: is the timer list empty? */
|
||||
if ( list_empty(&ac_timers[cpu].timers) ) {
|
||||
/*
|
||||
* XXX RN: This shouldn't happen, but does! Two possibilities:
|
||||
* - Race condition between removing and reseting APIC
|
||||
* - setting an APIC timeout value of 0 causes an immediate
|
||||
* timer interrupt to fire.
|
||||
* None of these should be critical!
|
||||
*/
|
||||
/* This does sometimes happen: race condition in resetting timeout? */
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -368,9 +368,9 @@ asmlinkage void schedule(void)
|
||||
|
||||
sched_done:
|
||||
ASSERT(r_time != 0);
|
||||
ASSERT(r_time > ctx_allow);
|
||||
ASSERT(r_time >= ctx_allow);
|
||||
|
||||
#if 0
|
||||
#ifndef NDEBUG
|
||||
if ( (r_time==0) || (r_time < ctx_allow)) {
|
||||
printk("[%02d]: %lx\n", this_cpu, r_time);
|
||||
dump_rqueue(&schedule_data[this_cpu].runqueue, "foo");
|
||||
@@ -389,7 +389,8 @@ asmlinkage void schedule(void)
|
||||
timer_redo:
|
||||
schedule_data[this_cpu].s_timer.expires = now + r_time;
|
||||
if (add_ac_timer(&schedule_data[this_cpu].s_timer) == 1) {
|
||||
printk("SCHED[%02d]: Shit this shouldn't happen\n", this_cpu);
|
||||
printk("SCHED[%02d]: Shit this shouldn't happen %08x\n",
|
||||
this_cpu, r_time);
|
||||
now = NOW();
|
||||
goto timer_redo;
|
||||
}
|
||||
|
||||