diff options
author | Paul E. McKenney <paul.mckenney@linaro.org> | 2012-01-06 17:11:30 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-02-21 12:03:25 -0500 |
commit | 486e259340fc4c60474f2c14703e3b3634bb58ca (patch) | |
tree | 70a58702194588fa0773463523f72c682785d040 /kernel/rcu.h | |
parent | 0bb7b59d6e2b8440cd7097097dd4bbfc4d76ed07 (diff) |
rcu: Avoid waking up CPUs having only kfree_rcu() callbacks
When CONFIG_RCU_FAST_NO_HZ is enabled, RCU will allow a given CPU to
enter dyntick-idle mode even if it still has RCU callbacks queued.
RCU avoids system hangs in this case by scheduling a timer for several
jiffies in the future. However, if all of the callbacks on that CPU
are from kfree_rcu(), there is no reason to wake the CPU up, as it is
not a problem to defer freeing of memory.
This commit therefore tracks the number of callbacks on a given CPU
that are from kfree_rcu(), and avoids scheduling the timer if all of
a given CPU's callbacks are from kfree_rcu().
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/rcu.h')
-rw-r--r-- | kernel/rcu.h | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/kernel/rcu.h b/kernel/rcu.h index aa88baab5f78..a074b0b43fc2 100644 --- a/kernel/rcu.h +++ b/kernel/rcu.h | |||
@@ -76,16 +76,18 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) | |||
76 | 76 | ||
77 | extern void kfree(const void *); | 77 | extern void kfree(const void *); |
78 | 78 | ||
79 | static inline void __rcu_reclaim(char *rn, struct rcu_head *head) | 79 | static inline bool __rcu_reclaim(char *rn, struct rcu_head *head) |
80 | { | 80 | { |
81 | unsigned long offset = (unsigned long)head->func; | 81 | unsigned long offset = (unsigned long)head->func; |
82 | 82 | ||
83 | if (__is_kfree_rcu_offset(offset)) { | 83 | if (__is_kfree_rcu_offset(offset)) { |
84 | RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset)); | 84 | RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset)); |
85 | kfree((void *)head - offset); | 85 | kfree((void *)head - offset); |
86 | return 1; | ||
86 | } else { | 87 | } else { |
87 | RCU_TRACE(trace_rcu_invoke_callback(rn, head)); | 88 | RCU_TRACE(trace_rcu_invoke_callback(rn, head)); |
88 | head->func(head); | 89 | head->func(head); |
90 | return 0; | ||
89 | } | 91 | } |
90 | } | 92 | } |
91 | 93 | ||