diff mbox

[v3,4/6] xen: RCU: don't let a CPU with a callback go idle.

Message ID 150307947033.29525.16503215464785953885.stgit@Solace.fritz.box (mailing list archive)
State New, archived
Headers show

Commit Message

Dario Faggioli Aug. 18, 2017, 6:04 p.m. UTC
If a CPU has a callback queued, it must be ready to invoke
it, as soon as all the other CPUs involved in the grace period
has gone through a quiescent state.

But if we let such CPU go idle, we can't really tell when (if!)
it will realize that it is actually time to invoke the callback.
To solve this problem, a CPU that has a callback queued (and has
already gone through a quiescent state itself) will stay online,
until the grace period ends, and the callback can be invoked.

This is similar to what Linux does, and is the second and last
step for fixing the overly long (or infinite!) grace periods.
The problem, though, is that, within Linux, we have the tick,
so, all that is necessary is to not stop the tick for the CPU
(even if it has gone idle). In Xen, there's no tick, so we must
avoid for the CPU to go idle entirely, and let it spin on
rcu_pending(), consuming power and causing overhead.

In this commit, we implement the above, using rcu_needs_cpu(),
in a way similar to how it is used in Linux. This it correct,
useful and not wasteful for CPUs that participate in grace
period, but have not a callback queued. For the ones that
has callbacks, an optimization that avoids having to spin is
introduced in a subsequent change.

Signed-off-by: Dario Faggioli <dario.faggioli@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
Cc: Tim Deegan <tim@xen.org>
Cc: Wei Liu <wei.liu2@citrix.com>
---
 xen/include/xen/sched.h |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

Comments

George Dunlap Aug. 29, 2017, 3:01 p.m. UTC | #1
On 08/18/2017 07:04 PM, Dario Faggioli wrote:
> If a CPU has a callback queued, it must be ready to invoke
> it, as soon as all the other CPUs involved in the grace period
> has gone through a quiescent state.
> 
> But if we let such CPU go idle, we can't really tell when (if!)
> it will realize that it is actually time to invoke the callback.
> To solve this problem, a CPU that has a callback queued (and has
> already gone through a quiescent state itself) will stay online,
> until the grace period ends, and the callback can be invoked.
> 
> This is similar to what Linux does, and is the second and last
> step for fixing the overly long (or infinite!) grace periods.
> The problem, though, is that, within Linux, we have the tick,
> so, all that is necessary is to not stop the tick for the CPU
> (even if it has gone idle). In Xen, there's no tick, so we must
> avoid for the CPU to go idle entirely, and let it spin on
> rcu_pending(), consuming power and causing overhead.
> 
> In this commit, we implement the above, using rcu_needs_cpu(),
> in a way similar to how it is used in Linux. This it correct,
> useful and not wasteful for CPUs that participate in grace
> period, but have not a callback queued. For the ones that
> has callbacks, an optimization that avoids having to spin is
> introduced in a subsequent change.
> 
> Signed-off-by: Dario Faggioli <dario.faggioli@citrix.com>
> Reviewed-by: Jan Beulich <jbeulich@suse.com>

Acked-by: George Dunlap <george.dunlap@citrix.com>
diff mbox

Patch

diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 5828a01..c116604 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -847,7 +847,8 @@  uint64_t get_cpu_idle_time(unsigned int cpu);
 
 /*
  * Used by idle loop to decide whether there is work to do:
- *  (1) Run softirqs; or (2) Play dead; or (3) Run tasklets.
+ *  (1) Deal with RCU; (2) or run softirqs; or (3) Play dead;
+ *  or (4) Run tasklets.
  *
  * About (3), if a tasklet is enqueued, it will be scheduled
  * really really soon, and hence it's pointless to try to
@@ -855,7 +856,8 @@  uint64_t get_cpu_idle_time(unsigned int cpu);
  * the tasklet_work_to_do() helper).
  */
 #define cpu_is_haltable(cpu)                    \
-    (!softirq_pending(cpu) &&                   \
+    (!rcu_needs_cpu(cpu) &&                     \
+     !softirq_pending(cpu) &&                   \
      cpu_online(cpu) &&                         \
      !per_cpu(tasklet_work_to_do, cpu))