aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcu.h
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2012-01-06 17:11:30 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-02-21 12:03:25 -0500
commit486e259340fc4c60474f2c14703e3b3634bb58ca (patch)
tree70a58702194588fa0773463523f72c682785d040 /kernel/rcu.h
parent0bb7b59d6e2b8440cd7097097dd4bbfc4d76ed07 (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.h4
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
77extern void kfree(const void *); 77extern void kfree(const void *);
78 78
79static inline void __rcu_reclaim(char *rn, struct rcu_head *head) 79static 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