Message ID | 150307947033.29525.16503215464785953885.stgit@Solace.fritz.box (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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 --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))