diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-08-16 15:40:43 +0000 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-08-16 15:40:43 +0000 |
commit | eb72f656ae6128891e67422d68ef132bc70393ac (patch) | |
tree | 7833f598bcc020478a89b5d2bc8a76e2d4b2921a | |
parent | f31042c4c4a2f0a429a0471a16e3b25139b657df (diff) | |
download | xen-eb72f656ae6128891e67422d68ef132bc70393ac.tar.gz xen-eb72f656ae6128891e67422d68ef132bc70393ac.tar.bz2 xen-eb72f656ae6128891e67422d68ef132bc70393ac.zip |
Fix xtime_lock handling in timer interrupt. There's no need
to hold it while doing local VCPU work, and there might be
danger of deadlock if we do.
Signed-off-by: Keir Fraser <keir@xensource.com>
-rw-r--r-- | linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c | 45 |
1 files changed, 15 insertions, 30 deletions
diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c index ea421f080b..4ceded947a 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c @@ -540,17 +540,14 @@ unsigned long profile_pc(struct pt_regs *regs) EXPORT_SYMBOL(profile_pc); #endif -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - */ -static inline void do_timer_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { s64 delta, delta_cpu; int cpu = smp_processor_id(); struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu); + write_seqlock(&xtime_lock); + do { get_time_values_from_xen(); @@ -582,7 +579,18 @@ static inline void do_timer_interrupt(int irq, void *dev_id, do_timer(regs); } - /* Local CPU jiffy work. */ + if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) { + update_wallclock(); + clock_was_set(); + } + + write_sequnlock(&xtime_lock); + + /* + * Local CPU jiffy work. No need to hold xtime_lock, and I'm not sure + * if there is risk of deadlock if we do (since update_process_times + * may do scheduler rebalancing work and thus acquire runqueue locks). + */ while (delta_cpu >= NS_PER_TICK) { delta_cpu -= NS_PER_TICK; per_cpu(processed_system_time, cpu) += NS_PER_TICK; @@ -590,29 +598,6 @@ static inline void do_timer_interrupt(int irq, void *dev_id, profile_tick(CPU_PROFILING, regs); } - if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) { - update_wallclock(); - clock_was_set(); - } -} - -/* - * This is the same as the above, except we _also_ save the current - * Time Stamp Counter value at the time of the timer interrupt, so that - * we later on can estimate the time of day more exactly. - */ -irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - /* - * Here we are in the timer irq handler. We just have irqs locally - * disabled but we don't know if the timer_bh is running on the other - * CPU. We need to avoid to SMP race with it. NOTE: we don' t need - * the irq version of write_lock because as just said we have irq - * locally disabled. -arca - */ - write_seqlock(&xtime_lock); - do_timer_interrupt(irq, NULL, regs); - write_sequnlock(&xtime_lock); return IRQ_HANDLED; } |