ia64/xen-unstable

changeset 10365:c230dbe793d6

[LINUX] Fix interaction between idle loop and RCU subsystem.

There is a problem with the current implementation of stop_hz_timer in
arch/i386/kernel/time-xen.c where the hz timer can be stopped on a CPU
which has RCU callbacks pending.

This patch backports a new RCU API created to fix this problem for the
s390 implementation of stop_hz_timer and also updates the time-xen.c
implementation of stop_hz_timer to call the new API.

Signed-off-by: Harry Butterworth <butterwo@uk.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Mon Jun 12 14:17:05 2006 +0100 (2006-06-12)
parents 34ff26fb2240
children 6bffed2aa78b
files linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c patches/linux-2.6.16.13/rcu_needs_cpu.patch
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Mon Jun 12 12:01:32 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Mon Jun 12 14:17:05 2006 +0100
     1.3 @@ -978,12 +978,19 @@ static void stop_hz_timer(void)
     1.4  	unsigned int cpu = smp_processor_id();
     1.5  	unsigned long j;
     1.6  
     1.7 -	/* We must do this /before/ checking rcu_pending(). */
     1.8  	cpu_set(cpu, nohz_cpu_mask);
     1.9 +
    1.10 +	/* See matching smp_mb in rcu_start_batch in rcupdate.c.  These mbs  */
    1.11 +	/* ensure that if __rcu_pending (nested in rcu_needs_cpu) fetches a  */
    1.12 +	/* value of rcp->cur that matches rdp->quiescbatch and allows us to  */
    1.13 +	/* stop the hz timer then the cpumasks created for subsequent values */
    1.14 +	/* of cur in rcu_start_batch are guaranteed to pick up the updated   */
    1.15 +	/* nohz_cpu_mask and so will not depend on this cpu.                 */
    1.16 +
    1.17  	smp_mb();
    1.18  
    1.19  	/* Leave ourselves in 'tick mode' if rcu or softirq pending. */
    1.20 -	if (rcu_pending(cpu) || local_softirq_pending()) {
    1.21 +	if (rcu_needs_cpu(cpu) || local_softirq_pending()) {
    1.22  		cpu_clear(cpu, nohz_cpu_mask);
    1.23  		j = jiffies + 1;
    1.24  	} else {
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/patches/linux-2.6.16.13/rcu_needs_cpu.patch	Mon Jun 12 14:17:05 2006 +0100
     2.3 @@ -0,0 +1,33 @@
     2.4 +--- ../pristine-linux-2.6.16.13/kernel/rcupdate.c	2006-05-02 22:38:44.000000000 +0100
     2.5 ++++ ./kernel/rcupdate.c	2006-06-09 20:27:45.000000000 +0100
     2.6 +@@ -485,6 +485,20 @@ int rcu_pending(int cpu)
     2.7 + 		__rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
     2.8 + }
     2.9 + 
    2.10 ++/*
    2.11 ++ * Check to see if any future RCU-related work will need to be done
    2.12 ++ * by the current CPU, even if none need be done immediately, returning
    2.13 ++ * 1 if so.  This function is part of the RCU implementation; it is -not-
    2.14 ++ * an exported member of the RCU API.
    2.15 ++ */
    2.16 ++int rcu_needs_cpu(int cpu)
    2.17 ++{
    2.18 ++	struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
    2.19 ++	struct rcu_data *rdp_bh = &per_cpu(rcu_bh_data, cpu);
    2.20 ++
    2.21 ++	return (!!rdp->curlist || !!rdp_bh->curlist || rcu_pending(cpu));
    2.22 ++}
    2.23 ++
    2.24 + void rcu_check_callbacks(int cpu, int user)
    2.25 + {
    2.26 + 	if (user || 
    2.27 +--- ../pristine-linux-2.6.16.13/include/linux/rcupdate.h	2006-05-02 22:38:44.000000000 +0100
    2.28 ++++ ./include/linux/rcupdate.h	2006-06-09 20:28:57.000000000 +0100
    2.29 +@@ -134,6 +134,7 @@ static inline void rcu_bh_qsctr_inc(int 
    2.30 + }
    2.31 + 
    2.32 + extern int rcu_pending(int cpu);
    2.33 ++extern int rcu_needs_cpu(int cpu);
    2.34 + 
    2.35 + /**
    2.36 +  * rcu_read_lock - mark the beginning of an RCU read-side critical section.