aboutsummaryrefslogtreecommitdiffstats
path: root/linux-2.6.11-xen-sparse
diff options
context:
space:
mode:
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-05-30 10:18:30 +0000
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>2005-05-30 10:18:30 +0000
commit1b3ead1336bc92ee90a23a38f3432227b20b5b22 (patch)
tree0df010006a6864e6222f6af960117210946e7888 /linux-2.6.11-xen-sparse
parentc83e3c7ddb9ba20a381898ef9f8cdeb3c258b551 (diff)
downloadxen-1b3ead1336bc92ee90a23a38f3432227b20b5b22.tar.gz
xen-1b3ead1336bc92ee90a23a38f3432227b20b5b22.tar.bz2
xen-1b3ead1336bc92ee90a23a38f3432227b20b5b22.zip
bitkeeper revision 1.1159.258.154 (429ae8764I9WsS60DkRARFDRTCFT1Q)
Fix Xen idle loop to enter/exit tickless mode in same way as s390, which interfaces properly with the RCU subsystem. This includes a patch that fixes a race in the generic RCU code: it was created by IBM for s390, and is being pushed upstream by them. Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'linux-2.6.11-xen-sparse')
-rw-r--r--linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c17
-rw-r--r--linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c43
2 files changed, 24 insertions, 36 deletions
diff --git a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c
index 9a0e5d1322..0ef40b7035 100644
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c
@@ -91,25 +91,18 @@ void enable_hlt(void)
EXPORT_SYMBOL(enable_hlt);
/* XXX XEN doesn't use default_idle(), poll_idle(). Use xen_idle() instead. */
-extern int set_timeout_timer(void);
+extern void stop_hz_timer(void);
+extern void start_hz_timer(void);
void xen_idle(void)
{
- int cpu;
-
local_irq_disable();
- cpu = smp_processor_id();
- if (rcu_pending(cpu))
- rcu_check_callbacks(cpu, 0);
-
if (need_resched()) {
local_irq_enable();
- } else if (set_timeout_timer() == 0) {
- /* NB. Blocking reenable events in a race-free manner. */
- HYPERVISOR_block();
} else {
- local_irq_enable();
- HYPERVISOR_yield();
+ stop_hz_timer();
+ HYPERVISOR_block(); /* implicit local_irq_enable() */
+ start_hz_timer();
}
}
diff --git a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c
index e013191f7b..acf5dd3130 100644
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c
@@ -665,36 +665,31 @@ static inline u64 __jiffies_to_st(unsigned long j)
}
/*
- * This function works out when the the next timer function has to be
- * executed (by looking at the timer list) and sets the Xen one-shot
- * domain timer to the appropriate value. This is typically called in
- * cpu_idle() before the domain blocks.
- *
- * The function returns a non-0 value on error conditions.
- *
- * It must be called with interrupts disabled.
+ * stop_hz_timer / start_hz_timer - enter/exit 'tickless mode' on an idle cpu
+ * These functions are based on implementations from arch/s390/kernel/time.c
*/
-int set_timeout_timer(void)
+void stop_hz_timer(void)
{
- u64 alarm = 0;
- int ret = 0;
+ unsigned int cpu = smp_processor_id();
unsigned long j;
- /*
- * This is safe against long blocking (since calculations are
- * not based on TSC deltas). It is also safe against warped
- * system time since suspend-resume is cooperative and we
- * would first get locked out. It is safe against normal
- * updates of jiffies since interrupts are off.
- */
- j = next_timer_interrupt();
- alarm = __jiffies_to_st(j);
+ /* s390 does this /before/ checking rcu_pending(). We copy them. */
+ cpu_set(cpu, nohz_cpu_mask);
- /* Failure is pretty bad, but we'd best soldier on. */
- if ( HYPERVISOR_set_timer_op(alarm) != 0 )
- ret = -1;
+ /* Leave ourselves in 'tick mode' if rcu or softirq pending. */
+ if (rcu_pending(cpu) || local_softirq_pending()) {
+ cpu_clear(cpu, nohz_cpu_mask);
+ j = jiffies + 1;
+ } else {
+ j = next_timer_interrupt();
+ }
- return ret;
+ BUG_ON(HYPERVISOR_set_timer_op(__jiffies_to_st(j)) != 0);
+}
+
+void start_hz_timer(void)
+{
+ cpu_clear(smp_processor_id(), nohz_cpu_mask);
}
void time_suspend(void)