diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-05-30 10:18:30 +0000 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-05-30 10:18:30 +0000 |
commit | 1b3ead1336bc92ee90a23a38f3432227b20b5b22 (patch) | |
tree | 0df010006a6864e6222f6af960117210946e7888 | |
parent | c83e3c7ddb9ba20a381898ef9f8cdeb3c258b551 (diff) | |
download | xen-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>
-rw-r--r-- | .rootkeys | 1 | ||||
-rw-r--r-- | linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c | 17 | ||||
-rw-r--r-- | linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c | 43 | ||||
-rw-r--r-- | patches/linux-2.6.11/rcu-nohz.patch | 16 |
4 files changed, 41 insertions, 36 deletions
@@ -369,6 +369,7 @@ 42372652KCUP-IOH9RN19YQmGhs4aA patches/linux-2.6.11/iomap.patch 428359d4b3fDYtazwXi4UUmSWaOUew patches/linux-2.6.11/linux-2.6.11.10.patch 418abc69J3F638vPO9MYoDGeYilxoQ patches/linux-2.6.11/nettel.patch +429ae875I9ZrqrRDjGD34IC2kzDREw patches/linux-2.6.11/rcu-nohz.patch 3f776bd1Hy9rn69ntXBhPReUFw9IEA tools/Makefile 40e1b09db5mN69Ijj0X_Eol-S7dXiw tools/Rules.mk 4124b307nRyK3dhn1hAsvrY76NuV3g tools/check/Makefile 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) diff --git a/patches/linux-2.6.11/rcu-nohz.patch b/patches/linux-2.6.11/rcu-nohz.patch new file mode 100644 index 0000000000..d7bafb3a62 --- /dev/null +++ b/patches/linux-2.6.11/rcu-nohz.patch @@ -0,0 +1,16 @@ +diff -ur linux-2.6.11/kernel/rcupdate.c linux-2.6.11-rcu/kernel/rcupdate.c +--- linux-2.6.11/kernel/rcupdate.c 2005-05-30 10:51:41 +01:00 ++++ linux-2.6.11-rcu/kernel/rcupdate.c 2005-05-30 10:53:53 +01:00 +@@ -202,8 +202,11 @@ + */ + static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp) + { ++ cpumask_t mask; ++ + cpu_clear(cpu, rsp->cpumask); +- if (cpus_empty(rsp->cpumask)) { ++ cpus_andnot(mask, rsp->cpumask, nohz_cpu_mask); ++ if (cpus_empty(mask)) { + /* batch completed ! */ + rcp->completed = rcp->cur; + rcu_start_batch(rcp, rsp, 0); |