diff options
author | Paul E. McKenney <paul.mckenney@linaro.org> | 2012-03-01 16:18:08 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-05-09 17:27:54 -0400 |
commit | b1420f1c8bfc30ecf6380a31d0f686884834b599 (patch) | |
tree | 56eb378bcd64175a7302a1031b388ecf569a30bb /kernel/rcutree.h | |
parent | 98248a0e24327bc64eb7518145c44bff7bebebc3 (diff) |
rcu: Make rcu_barrier() less disruptive
The rcu_barrier() primitive interrupts each and every CPU, registering
a callback on every CPU. Once all of these callbacks have been invoked,
rcu_barrier() knows that every callback that was registered before
the call to rcu_barrier() has also been invoked.
However, there is no point in registering a callback on a CPU that
currently has no callbacks, most especially if that CPU is in a
deep idle state. This commit therefore makes rcu_barrier() avoid
interrupting CPUs that have no callbacks. Doing this requires reworking
the handling of orphaned callbacks, otherwise callbacks could slip through
rcu_barrier()'s net by being orphaned from a CPU that rcu_barrier() had
not yet interrupted to a CPU that rcu_barrier() had already interrupted.
This reworking was needed anyway to take a first step towards weaning
RCU from the CPU_DYING notifier's use of stop_cpu().
Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcutree.h')
-rw-r--r-- | kernel/rcutree.h | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 36ca28ecedc6..1e49c5685960 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h | |||
@@ -371,6 +371,17 @@ struct rcu_state { | |||
371 | 371 | ||
372 | raw_spinlock_t onofflock; /* exclude on/offline and */ | 372 | raw_spinlock_t onofflock; /* exclude on/offline and */ |
373 | /* starting new GP. */ | 373 | /* starting new GP. */ |
374 | struct rcu_head *orphan_nxtlist; /* Orphaned callbacks that */ | ||
375 | /* need a grace period. */ | ||
376 | struct rcu_head **orphan_nxttail; /* Tail of above. */ | ||
377 | struct rcu_head *orphan_donelist; /* Orphaned callbacks that */ | ||
378 | /* are ready to invoke. */ | ||
379 | struct rcu_head **orphan_donetail; /* Tail of above. */ | ||
380 | long qlen_lazy; /* Number of lazy callbacks. */ | ||
381 | long qlen; /* Total number of callbacks. */ | ||
382 | struct task_struct *rcu_barrier_in_progress; | ||
383 | /* Task doing rcu_barrier(), */ | ||
384 | /* or NULL if no barrier. */ | ||
374 | raw_spinlock_t fqslock; /* Only one task forcing */ | 385 | raw_spinlock_t fqslock; /* Only one task forcing */ |
375 | /* quiescent states. */ | 386 | /* quiescent states. */ |
376 | unsigned long jiffies_force_qs; /* Time at which to invoke */ | 387 | unsigned long jiffies_force_qs; /* Time at which to invoke */ |