mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.88 (3e564e1cTiVK2rPAdHl9ccMD8nraEw)
ac_timer.c, apic.c: Fix timer code to schedule alarm handlers with some slop.
This commit is contained in:
1 parent
a75def4139
commit
ef170179d0
2 files changed
+218
-257
No files matched your search
+65
-72
@@ -218,9 +218,7 @@ int __init verify_local_APIC(void)
|
||||
|
||||
void __init sync_Arb_IDs(void)
|
||||
{
|
||||
/*
|
||||
* Wait for idle.
|
||||
*/
|
||||
/* Wait for idle. */
|
||||
apic_wait_icr_idle();
|
||||
|
||||
Dprintk("Synchronizing Arb IDs.\n");
|
||||
@@ -508,11 +506,11 @@ void __init wait_8254_wraparound(void)
|
||||
prev_count = curr_count;
|
||||
curr_count = get_8254_timer_count();
|
||||
delta = curr_count-prev_count;
|
||||
/*
|
||||
* This limit for delta seems arbitrary, but it isn't, it's
|
||||
* slightly above the level of error a buggy Mercury/Neptune
|
||||
* chipset timer can cause.
|
||||
*/
|
||||
/*
|
||||
* This limit for delta seems arbitrary, but it isn't, it's slightly
|
||||
* above the level of error a buggy Mercury/Neptune chipset timer can
|
||||
* cause.
|
||||
*/
|
||||
} while (delta < 300);
|
||||
}
|
||||
|
||||
@@ -581,7 +579,7 @@ int __init calibrate_APIC_clock(void)
|
||||
* counter running for calibration. */
|
||||
__setup_APIC_LVTT(1000000000);
|
||||
|
||||
/* The timer chip counts down to zero. Let's wait
|
||||
/* The timer chip counts down to zero. Let's wait
|
||||
* for a wraparound to start exact measurement:
|
||||
* (the current tick might have been already half done) */
|
||||
wait_8254_wraparound();
|
||||
@@ -611,18 +609,18 @@ int __init calibrate_APIC_clock(void)
|
||||
result/(1000000/HZ),
|
||||
result%(1000000/HZ));
|
||||
|
||||
cpu_freq = (u64)(((t2-t1)/LOOPS)*HZ);
|
||||
cpu_freq = (u64)(((t2-t1)/LOOPS)*HZ);
|
||||
|
||||
/* set up multipliers for accurate timer code */
|
||||
bus_freq = result*HZ;
|
||||
bus_cycle = (u32) (1000000000000LL/bus_freq); /* in pico seconds */
|
||||
bus_scale = (1000*262144)/bus_cycle;
|
||||
/* set up multipliers for accurate timer code */
|
||||
bus_freq = result*HZ;
|
||||
bus_cycle = (u32) (1000000000000LL/bus_freq); /* in pico seconds */
|
||||
bus_scale = (1000*262144)/bus_cycle;
|
||||
|
||||
/* print results */
|
||||
printk("..... bus_freq = %u Hz\n", bus_freq);
|
||||
printk("..... bus_cycle = %u ps\n", bus_cycle);
|
||||
printk("..... bus_scale = %u \n", bus_scale);
|
||||
/* reset APIC to zero timeout value */
|
||||
/* print results */
|
||||
printk("..... bus_freq = %u Hz\n", bus_freq);
|
||||
printk("..... bus_cycle = %u ps\n", bus_cycle);
|
||||
printk("..... bus_scale = %u \n", bus_scale);
|
||||
/* reset APIC to zero timeout value */
|
||||
__setup_APIC_LVTT(0);
|
||||
return result;
|
||||
}
|
||||
@@ -636,7 +634,7 @@ void __init setup_APIC_clocks (void)
|
||||
printk("Using local APIC timer interrupts.\n");
|
||||
using_apic_timer = 1;
|
||||
__cli();
|
||||
/* calibrate CPU0 for CPU speed and BUS speed */
|
||||
/* calibrate CPU0 for CPU speed and BUS speed */
|
||||
bus_freq = calibrate_APIC_clock();
|
||||
/* Now set up the timer for real. */
|
||||
setup_APIC_timer((void *)bus_freq);
|
||||
@@ -654,41 +652,38 @@ 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;
|
||||
|
||||
now = NOW();
|
||||
expire = timeout - now; /* value from now */
|
||||
now = 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 */
|
||||
}
|
||||
|
||||
if (expire <= 0) {
|
||||
TRC(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 */
|
||||
}
|
||||
/* conversion to bus units */
|
||||
apic_tmict = (((u64)bus_scale) * expire)>>18;
|
||||
|
||||
/* conversion to bus units */
|
||||
apic_tmict = (((u64)bus_scale) * expire)>>18;
|
||||
if (apic_tmict >= 0xffffffff) {
|
||||
printk("APICT[%02d] Timeout value too large\n", cpu);
|
||||
apic_tmict = 0xffffffff;
|
||||
}
|
||||
if (apic_tmict == 0) {
|
||||
printk("APICT[%02d] timeout value too small\n", cpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (apic_tmict >= 0xffffffff) {
|
||||
/* This is bad! */
|
||||
printk("APICT[%02d] Timeout value too large\n", cpu);
|
||||
apic_tmict = 0xffffffff;
|
||||
}
|
||||
if (apic_tmict == 0) {
|
||||
TRC(printk("APICT[%02d] timeout value too small\n", cpu));
|
||||
return 0;
|
||||
}
|
||||
/* programm timer */
|
||||
apic_write(APIC_TMICT, (unsigned long)apic_tmict);
|
||||
|
||||
/* programm timer */
|
||||
apic_write(APIC_TMICT, (unsigned long)apic_tmict);
|
||||
|
||||
TRC(printk("APICT[%02d] reprog(): expire=%lld %u\n",
|
||||
cpu, expire, apic_tmict));
|
||||
return 1;
|
||||
TRC(printk("APICT[%02d] reprog(): expire=%lld %u\n",
|
||||
cpu, expire, apic_tmict));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -702,29 +697,28 @@ int reprogram_ac_timer(s_time_t timeout)
|
||||
static s_time_t last_cpu0_tirq = 0;
|
||||
inline void smp_local_timer_interrupt(struct pt_regs * regs)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
s_time_t diff, now;
|
||||
|
||||
int cpu = smp_processor_id();
|
||||
s_time_t diff, now;
|
||||
|
||||
/* if CPU 0 do old timer stuff */
|
||||
if (cpu == 0) {
|
||||
if (cpu == 0)
|
||||
{
|
||||
now = NOW();
|
||||
diff = now - last_cpu0_tirq;
|
||||
|
||||
now = NOW();
|
||||
diff = now - last_cpu0_tirq;
|
||||
if (diff <= 0) {
|
||||
printk ("System Time went backwards: %lld\n", diff);
|
||||
return;
|
||||
}
|
||||
|
||||
if (diff <= 0) {
|
||||
printk ("System Time went backwards: %lld\n", diff);
|
||||
return;
|
||||
}
|
||||
|
||||
while (diff >= MILLISECS(10)) {
|
||||
do_timer(regs);
|
||||
diff -= MILLISECS(10);
|
||||
last_cpu0_tirq += MILLISECS(10);
|
||||
}
|
||||
}
|
||||
/* call accurate timer function */
|
||||
do_ac_timer();
|
||||
while (diff >= MILLISECS(10)) {
|
||||
do_timer(regs);
|
||||
diff -= MILLISECS(10);
|
||||
last_cpu0_tirq += MILLISECS(10);
|
||||
}
|
||||
}
|
||||
/* call accurate timer function */
|
||||
do_ac_timer();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -747,9 +741,8 @@ void smp_apic_timer_interrupt(struct pt_regs * regs)
|
||||
apic_timer_irqs[cpu]++;
|
||||
|
||||
/*
|
||||
* NOTE! We'd better ACK the irq immediately,
|
||||
* because timer handling can be slow.
|
||||
* XXX is this save?
|
||||
* NOTE! We'd better ACK the irq immediately, because timer handling can
|
||||
* be slow. XXX is this save?
|
||||
*/
|
||||
ack_APIC_irq();
|
||||
|
||||
@@ -825,7 +818,7 @@ int __init APIC_init_uniprocessor (void)
|
||||
* Complain if the BIOS pretends there is one.
|
||||
*/
|
||||
if (!cpu_has_apic&&APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]))
|
||||
{
|
||||
{
|
||||
printk("BIOS bug, local APIC #%d not detected!...\n",
|
||||
boot_cpu_physical_apicid);
|
||||
return -1;
|
||||
|
||||
+153
-185
@@ -44,6 +44,12 @@
|
||||
#define TRC(_x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We pull handlers off the timer list this far in future,
|
||||
* rather than reprogramming the time hardware.
|
||||
*/
|
||||
#define TIMER_SLOP (50*1000) /* ns */
|
||||
|
||||
/* A timer list per CPU */
|
||||
typedef struct ac_timers_st
|
||||
{
|
||||
@@ -58,8 +64,8 @@ static ac_timers_t ac_timers[NR_CPUS];
|
||||
#define MAX_STATS
|
||||
typedef struct act_stats_st
|
||||
{
|
||||
u32 count;
|
||||
u32 times[2*(BUCKETS)];
|
||||
u32 count;
|
||||
u32 times[2*(BUCKETS)];
|
||||
} __cacheline_aligned act_stats_t;
|
||||
static act_stats_t act_stats[NR_CPUS];
|
||||
|
||||
@@ -79,71 +85,68 @@ static int detach_ac_timer(struct ac_timer *timer);
|
||||
*/
|
||||
int add_ac_timer(struct ac_timer *timer)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
unsigned long flags;
|
||||
s_time_t now;
|
||||
int cpu = smp_processor_id();
|
||||
unsigned long flags;
|
||||
s_time_t now;
|
||||
|
||||
/* sanity checks */
|
||||
|
||||
/* make sure timeout value is in the future */
|
||||
now = NOW();
|
||||
TRC(printk("ACT [%02d] add(): now=%lld timo=%lld\n",
|
||||
cpu, now, timer->expires));
|
||||
if (timer->expires <= now) {
|
||||
printk("ACT[%02d] add_ac_timer: now=0x%08X%08X > expire=0x%08X%08X\n",
|
||||
cpu, (u32)(now>>32), (u32)now,
|
||||
(u32)(timer->expires>>32), (u32)timer->expires);
|
||||
return 1;
|
||||
}
|
||||
spin_lock_irqsave(&ac_timers[cpu].lock, flags);
|
||||
/*
|
||||
/* make sure timeout value is in the future */
|
||||
now = NOW();
|
||||
TRC(printk("ACT [%02d] add(): now=%lld timo=%lld\n",
|
||||
cpu, now, timer->expires));
|
||||
if (timer->expires <= now) {
|
||||
printk("ACT[%02d] add_ac_timer: now=0x%08X%08X > expire=0x%08X%08X\n",
|
||||
cpu, (u32)(now>>32), (u32)now,
|
||||
(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
|
||||
*/
|
||||
if (list_empty(&ac_timers[cpu].timers)) {
|
||||
/* Reprogramm and add to head of list */
|
||||
if (!reprogram_ac_timer(timer->expires)) {
|
||||
/* failed */
|
||||
printk("ACT [%02d] add(): add at head failed\n", cpu);
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
return 1;
|
||||
}
|
||||
list_add(&timer->timer_list, &ac_timers[cpu].timers);
|
||||
TRC(printk("ACT [%02d] add(0x%08X%08X): added at head\n", cpu,
|
||||
(u32)(timer->expires>>32), (u32)timer->expires));
|
||||
} else {
|
||||
struct list_head *pos;
|
||||
struct ac_timer *t;
|
||||
for (pos = ac_timers[cpu].timers.next;
|
||||
pos != &ac_timers[cpu].timers;
|
||||
pos = pos->next) {
|
||||
t = list_entry(pos, struct ac_timer, timer_list);
|
||||
if (t->expires > timer->expires)
|
||||
break;
|
||||
}
|
||||
if (list_empty(&ac_timers[cpu].timers)) {
|
||||
/* Reprogramm and add to head of list */
|
||||
if (!reprogram_ac_timer(timer->expires)) {
|
||||
/* failed */
|
||||
printk("ACT [%02d] add(): add at head failed\n", cpu);
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
return 1;
|
||||
}
|
||||
list_add(&timer->timer_list, &ac_timers[cpu].timers);
|
||||
TRC(printk("ACT [%02d] add(0x%08X%08X): added at head\n", cpu,
|
||||
(u32)(timer->expires>>32), (u32)timer->expires));
|
||||
} else {
|
||||
struct list_head *pos;
|
||||
struct ac_timer *t;
|
||||
for (pos = ac_timers[cpu].timers.next;
|
||||
pos != &ac_timers[cpu].timers;
|
||||
pos = pos->next) {
|
||||
t = list_entry(pos, struct ac_timer, timer_list);
|
||||
if (t->expires > timer->expires)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pos->prev == &ac_timers[cpu].timers) {
|
||||
/* added to head, reprogramm timer */
|
||||
if (!reprogram_ac_timer(timer->expires)) {
|
||||
/* failed */
|
||||
TRC(printk("ACT [%02d] add(): add at head failed\n", cpu));
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
return 1;
|
||||
}
|
||||
list_add (&(timer->timer_list), pos->prev);
|
||||
TRC(printk("ACT [%02d] add(0x%08X%08X): added at head\n", cpu,
|
||||
(u32)(timer->expires>>32), (u32)timer->expires));
|
||||
} else {
|
||||
list_add (&(timer->timer_list), pos->prev);
|
||||
TRC(printk("ACT [%02d] add(0x%08X%08X): add < exp=0x%08X%08X\n",
|
||||
cpu,
|
||||
(u32)(timer->expires>>32), (u32)timer->expires,
|
||||
(u32)(t->expires>>32), (u32)t->expires));
|
||||
}
|
||||
|
||||
}
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
return 0;
|
||||
if (pos->prev == &ac_timers[cpu].timers) {
|
||||
/* added to head, reprogramm timer */
|
||||
if (!reprogram_ac_timer(timer->expires)) {
|
||||
/* failed */
|
||||
TRC(printk("ACT [%02d] add(): add at head failed\n", cpu));
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
return 1;
|
||||
}
|
||||
list_add (&(timer->timer_list), pos->prev);
|
||||
TRC(printk("ACT [%02d] add(0x%08X%08X): added at head\n", cpu,
|
||||
(u32)(timer->expires>>32), (u32)timer->expires));
|
||||
} else {
|
||||
list_add (&(timer->timer_list), pos->prev);
|
||||
TRC(printk("ACT [%02d] add(0x%08X%08X): add < exp=0x%08X%08X\n",
|
||||
cpu,
|
||||
(u32)(timer->expires>>32), (u32)timer->expires,
|
||||
(u32)(t->expires>>32), (u32)t->expires));
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -154,11 +157,11 @@ int add_ac_timer(struct ac_timer *timer)
|
||||
*/
|
||||
static int detach_ac_timer(struct ac_timer *timer)
|
||||
{
|
||||
TRC(int cpu = smp_processor_id());
|
||||
TRC(printk("ACT [%02d] detach(): \n", cpu));
|
||||
list_del(&timer->timer_list);
|
||||
timer->timer_list.next = NULL;
|
||||
return 0;
|
||||
TRC(int cpu = smp_processor_id());
|
||||
TRC(printk("ACT [%02d] detach(): \n", cpu));
|
||||
list_del(&timer->timer_list);
|
||||
timer->timer_list.next = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -169,18 +172,17 @@ static int detach_ac_timer(struct ac_timer *timer)
|
||||
*/
|
||||
int rem_ac_timer(struct ac_timer *timer)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
int res;
|
||||
unsigned long flags;
|
||||
int cpu = smp_processor_id();
|
||||
int res;
|
||||
unsigned long flags;
|
||||
|
||||
TRC(printk("ACT [%02d] remove(): timo=%lld \n", cpu, timer->expires));
|
||||
/* sanity checks */
|
||||
TRC(printk("ACT [%02d] remove(): timo=%lld \n", cpu, timer->expires));
|
||||
|
||||
spin_lock_irqsave(&ac_timers[cpu].lock, flags);
|
||||
res = detach_ac_timer(timer);
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
spin_lock_irqsave(&ac_timers[cpu].lock, flags);
|
||||
res = detach_ac_timer(timer);
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -191,12 +193,12 @@ int rem_ac_timer(struct ac_timer *timer)
|
||||
*/
|
||||
int mod_ac_timer(struct ac_timer *timer, s_time_t new_time)
|
||||
{
|
||||
if (rem_ac_timer(timer) != 0)
|
||||
return -1;
|
||||
timer->expires = new_time;
|
||||
if (add_ac_timer(timer) != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
if (rem_ac_timer(timer) != 0)
|
||||
return -1;
|
||||
timer->expires = new_time;
|
||||
if (add_ac_timer(timer) != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -205,108 +207,76 @@ int mod_ac_timer(struct ac_timer *timer, s_time_t new_time)
|
||||
*/
|
||||
void do_ac_timer(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
unsigned long flags;
|
||||
s_time_t now;
|
||||
struct ac_timer *t;
|
||||
struct list_head *tmp;
|
||||
int cpu = smp_processor_id();
|
||||
unsigned long flags;
|
||||
struct ac_timer *t;
|
||||
|
||||
spin_lock_irqsave(&ac_timers[cpu].lock, flags);
|
||||
spin_lock_irqsave(&ac_timers[cpu].lock, flags);
|
||||
|
||||
do_timer_again:
|
||||
|
||||
now = NOW();
|
||||
TRC(printk("ACT [%02d] do(): now=%lld\n", cpu, now));
|
||||
TRC(printk("ACT [%02d] do(): now=%lld\n", cpu, NOW()));
|
||||
|
||||
/* Sanity checks */
|
||||
/* empty time list */
|
||||
if (list_empty(&ac_timers[cpu].timers)) {
|
||||
printk("ACT[%02d] do_ac_timer(): timer irq without timer\n", cpu);
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* execute the head of timer queue */
|
||||
t = list_entry(ac_timers[cpu].timers.next, struct ac_timer, timer_list);
|
||||
detach_ac_timer(t);
|
||||
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
|
||||
/* Sanity: is the timer list empty? */
|
||||
if ( list_empty(&ac_timers[cpu].timers) )
|
||||
printk("ACT[%02d] do_ac_timer(): timer irq without timer\n", cpu);
|
||||
|
||||
#ifdef AC_TIMER_STATS
|
||||
{
|
||||
s32 diff;
|
||||
u32 i;
|
||||
diff = ((s32)(now - t->expires)) / 1000; /* delta in us */
|
||||
if (diff < -BUCKETS)
|
||||
diff = -BUCKETS;
|
||||
else if (diff > BUCKETS)
|
||||
diff = BUCKETS;
|
||||
act_stats[cpu].times[diff+BUCKETS]++;
|
||||
act_stats[cpu].count++;
|
||||
{
|
||||
s32 diff;
|
||||
u32 i;
|
||||
diff = ((s32)(NOW() - t->expires)) / 1000; /* delta in us */
|
||||
if (diff < -BUCKETS)
|
||||
diff = -BUCKETS;
|
||||
else if (diff > BUCKETS)
|
||||
diff = BUCKETS;
|
||||
act_stats[cpu].times[diff+BUCKETS]++;
|
||||
act_stats[cpu].count++;
|
||||
|
||||
if (act_stats[cpu].count >= 5000) {
|
||||
printk("ACT Stats\n");
|
||||
if (act_stats[cpu].count >= 5000) {
|
||||
printk("ACT Stats\n");
|
||||
for (i=0; i < 2*BUCKETS; i++) {
|
||||
if (act_stats[cpu].times[i] != 0)
|
||||
printk("ACT [%02d]: %3dus: %5d\n",
|
||||
cpu,i-BUCKETS, act_stats[cpu].times[i]);
|
||||
act_stats[cpu].times[i]=0;
|
||||
}
|
||||
act_stats[cpu].count = 0;
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
printk("ACT [%02d]: %3dus: %5d\n",
|
||||
cpu,i-BUCKETS, act_stats[cpu].times[i]);
|
||||
act_stats[cpu].times[i]=0;
|
||||
}
|
||||
act_stats[cpu].count = 0;
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (t->expires > now) {
|
||||
//printk("ACT [%02d] do(): irq too early (%lld ns)\n",
|
||||
// cpu, now - t->expires );
|
||||
}
|
||||
if (t->function != NULL)
|
||||
t->function(t->data);
|
||||
|
||||
|
||||
/* check if there are other timer functions on the list */
|
||||
now = NOW();
|
||||
|
||||
spin_lock_irqsave(&ac_timers[cpu].lock, flags);
|
||||
|
||||
if (!list_empty(&ac_timers[cpu].timers)) {
|
||||
list_for_each(tmp, &ac_timers[cpu].timers) {
|
||||
t = list_entry(tmp, struct ac_timer, timer_list);
|
||||
TRC(printk("ACT [%02d] do(): now=%lld timo=%lld\n",
|
||||
cpu, now, t->expires));
|
||||
if (t->expires <= now) {
|
||||
detach_ac_timer(t);
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
if (t->function != NULL)
|
||||
t->function(t->data);
|
||||
spin_lock_irqsave(&ac_timers[cpu].lock, flags);
|
||||
now = NOW();
|
||||
} else {
|
||||
TRC(printk("ACT [%02d] do(): break1\n", cpu));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Handle all timeouts in the near future. */
|
||||
while ( !list_empty(&ac_timers[cpu].timers) )
|
||||
{
|
||||
t = list_entry(ac_timers[cpu].timers.next,
|
||||
struct ac_timer, timer_list);
|
||||
if ( t->expires > (NOW() + TIMER_SLOP) ) break;
|
||||
detach_ac_timer(t);
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
if ( t->function != NULL ) t->function(t->data);
|
||||
spin_lock_irqsave(&ac_timers[cpu].lock, flags);
|
||||
}
|
||||
|
||||
/* If list not empty reprogramm timer to new head of list */
|
||||
if (!list_empty(&ac_timers[cpu].timers)) {
|
||||
t = list_entry(ac_timers[cpu].timers.next,struct ac_timer,timer_list);
|
||||
if (t->expires > 0) {
|
||||
TRC(printk("ACT [%02d] do(): reprog timo=%lld\n",cpu,t->expires));
|
||||
if (!reprogram_ac_timer(t->expires)) {
|
||||
TRC(printk("ACT [%02d] do(): again\n", cpu));
|
||||
goto do_timer_again;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
TRC(printk("ACT [%02d] do(): end\n", cpu));
|
||||
/* If list not empty then reprogram timer to new head of list */
|
||||
if ( !list_empty(&ac_timers[cpu].timers) )
|
||||
{
|
||||
t = list_entry(ac_timers[cpu].timers.next,
|
||||
struct ac_timer, timer_list);
|
||||
if ( t->expires > 0 )
|
||||
{
|
||||
TRC(printk("ACT [%02d] do(): reprog timo=%lld\n",cpu,t->expires));
|
||||
if ( !reprogram_ac_timer(t->expires) )
|
||||
{
|
||||
TRC(printk("ACT [%02d] do(): again\n", cpu));
|
||||
goto do_timer_again;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
|
||||
TRC(printk("ACT [%02d] do(): end\n", cpu));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -317,16 +287,16 @@ static void dump_tqueue(struct list_head *queue, char *name)
|
||||
{
|
||||
struct list_head *list;
|
||||
int loop = 0;
|
||||
struct ac_timer *t;
|
||||
struct ac_timer *t;
|
||||
|
||||
printk ("QUEUE %s %lx n: %lx, p: %lx\n", name, (unsigned long)queue,
|
||||
(unsigned long) queue->next, (unsigned long) queue->prev);
|
||||
list_for_each (list, queue) {
|
||||
t = list_entry(list, struct ac_timer, timer_list);
|
||||
t = list_entry(list, struct ac_timer, timer_list);
|
||||
printk (" %s %d : %lx ex=0x%08X%08X %lu n: %lx, p: %lx\n",
|
||||
name, loop++,
|
||||
name, loop++,
|
||||
(unsigned long)list,
|
||||
(u32)(t->expires>>32), (u32)t->expires, t->data,
|
||||
(u32)(t->expires>>32), (u32)t->expires, t->data,
|
||||
(unsigned long)list->next, (unsigned long)list->prev);
|
||||
}
|
||||
return;
|
||||
@@ -336,32 +306,30 @@ static void dump_tqueue(struct list_head *queue, char *name)
|
||||
static void dump_timerq(u_char key, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
u_long flags;
|
||||
s_time_t now = NOW();
|
||||
s_time_t now = NOW();
|
||||
|
||||
printk("Dumping ac_timer queues for cpu 0: NOW=0x%08X%08X\n",
|
||||
(u32)(now>>32), (u32)now);
|
||||
(u32)(now>>32), (u32)now);
|
||||
|
||||
spin_lock_irqsave(&ac_timers[0].lock, flags);
|
||||
dump_tqueue(&ac_timers[0].timers, "ac_time");
|
||||
spin_unlock_irqrestore(&ac_timers[0].lock, flags);
|
||||
printk("\n");
|
||||
printk("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* init
|
||||
*/
|
||||
|
||||
void __init ac_timer_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk ("ACT: Initialising Accurate timers\n");
|
||||
printk ("ACT: Initialising Accurate timers\n");
|
||||
|
||||
for (i = 0; i < NR_CPUS; i++)
|
||||
{
|
||||
INIT_LIST_HEAD(&ac_timers[i].timers);
|
||||
spin_lock_init(&ac_timers[i].lock);
|
||||
INIT_LIST_HEAD(&ac_timers[i].timers);
|
||||
spin_lock_init(&ac_timers[i].lock);
|
||||
}
|
||||
|
||||
add_key_handler('a', dump_timerq, "dump ac_timer queues");
|
||||
add_key_handler('a', dump_timerq, "dump ac_timer queues");
|
||||
}
|
||||