diff options
author | Zachary Amsden <zach@vmware.com> | 2007-03-05 00:30:34 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-05 07:57:52 -0800 |
commit | 7507ba34e827ca3c6bbcd34d20a8df8ba365fca6 (patch) | |
tree | afa186f38ab55667074a06ade7ad6a1d1ec84d9e /arch/i386/kernel/vmitime.c | |
parent | 0dc952dc3e6d96d554a19fa7bee3f3b1d55e3cff (diff) |
[PATCH] vmi: timer fixes round two
Critical bugfixes for the VMI-Timer code.
1) Do not setup a one shot alarm if we are keeping the periodic alarm
armed. Additionally, since the periodic alarm can be run at a lower rate
than HZ, let's fixup the guard to the no-idle-hz mode appropriately. This
fixes the bug where the no-idle-hz mode might have a higher interrupt rate
than the non-idle case.
2) The interrupt handler can no longer adjust xtime due to nested lock
acquisition. Drop this. We don't need to check for wallclock time at
every tick, it can be done in userspace instead.
3) Add a bypass to disable noidle operation. This is useful as a last
minute workaround, or testing measure.
4) The code to skip the IO_APIC timer testing (no_timer_check) should be
conditional on IO_APIC, not SMP, since UP kernels can have this configured
in as well.
Signed-off-by: Dan Hecht <dhecht@vmware.com>
Signed-off-by: Zachary Amsden <zach@vmware.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/i386/kernel/vmitime.c')
-rw-r--r-- | arch/i386/kernel/vmitime.c | 30 |
1 files changed, 11 insertions, 19 deletions
diff --git a/arch/i386/kernel/vmitime.c b/arch/i386/kernel/vmitime.c index 76d2adcae5a..694aa85d22c 100644 --- a/arch/i386/kernel/vmitime.c +++ b/arch/i386/kernel/vmitime.c @@ -276,16 +276,13 @@ static void vmi_account_real_cycles(unsigned long long cur_real_cycles) cycles_not_accounted = cur_real_cycles - real_cycles_accounted_system; while (cycles_not_accounted >= cycles_per_jiffy) { - /* systems wide jiffies and wallclock. */ + /* systems wide jiffies. */ do_timer(1); cycles_not_accounted -= cycles_per_jiffy; real_cycles_accounted_system += cycles_per_jiffy; } - if (vmi_timer_ops.wallclock_updated()) - update_xtime_from_wallclock(); - write_sequnlock(&xtime_lock); } @@ -380,7 +377,6 @@ int vmi_stop_hz_timer(void) unsigned long seq, next; unsigned long long real_cycles_expiry; int cpu = smp_processor_id(); - int idle; BUG_ON(!irqs_disabled()); if (sysctl_hz_timer != 0) @@ -388,13 +384,13 @@ int vmi_stop_hz_timer(void) cpu_set(cpu, nohz_cpu_mask); smp_mb(); + if (rcu_needs_cpu(cpu) || local_softirq_pending() || - (next = next_timer_interrupt(), time_before_eq(next, jiffies))) { + (next = next_timer_interrupt(), + time_before_eq(next, jiffies + HZ/CONFIG_VMI_ALARM_HZ))) { cpu_clear(cpu, nohz_cpu_mask); - next = jiffies; - idle = 0; - } else - idle = 1; + return 0; + } /* Convert jiffies to the real cycle counter. */ do { @@ -404,17 +400,13 @@ int vmi_stop_hz_timer(void) } while (read_seqretry(&xtime_lock, seq)); /* This cpu is going idle. Disable the periodic alarm. */ - if (idle) { - vmi_timer_ops.cancel_alarm(VMI_CYCLES_AVAILABLE); - per_cpu(idle_start_jiffies, cpu) = jiffies; - } - + vmi_timer_ops.cancel_alarm(VMI_CYCLES_AVAILABLE); + per_cpu(idle_start_jiffies, cpu) = jiffies; /* Set the real time alarm to expire at the next event. */ vmi_timer_ops.set_alarm( - VMI_ALARM_WIRING | VMI_ALARM_IS_ONESHOT | VMI_CYCLES_REAL, - real_cycles_expiry, 0); - - return idle; + VMI_ALARM_WIRING | VMI_ALARM_IS_ONESHOT | VMI_CYCLES_REAL, + real_cycles_expiry, 0); + return 1; } static void vmi_reenable_hz_timer(int cpu) |