aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree.h
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /kernel/rcutree.h
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'kernel/rcutree.h')
-rw-r--r--kernel/rcutree.h133
1 files changed, 98 insertions, 35 deletions
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 1899023b0962..4a525a30e08e 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -34,10 +34,11 @@
34 * In practice, this has not been tested, so there is probably some 34 * In practice, this has not been tested, so there is probably some
35 * bug somewhere. 35 * bug somewhere.
36 */ 36 */
37#define MAX_RCU_LVLS 3 37#define MAX_RCU_LVLS 4
38#define RCU_FANOUT (CONFIG_RCU_FANOUT) 38#define RCU_FANOUT (CONFIG_RCU_FANOUT)
39#define RCU_FANOUT_SQ (RCU_FANOUT * RCU_FANOUT) 39#define RCU_FANOUT_SQ (RCU_FANOUT * RCU_FANOUT)
40#define RCU_FANOUT_CUBE (RCU_FANOUT_SQ * RCU_FANOUT) 40#define RCU_FANOUT_CUBE (RCU_FANOUT_SQ * RCU_FANOUT)
41#define RCU_FANOUT_FOURTH (RCU_FANOUT_CUBE * RCU_FANOUT)
41 42
42#if NR_CPUS <= RCU_FANOUT 43#if NR_CPUS <= RCU_FANOUT
43# define NUM_RCU_LVLS 1 44# define NUM_RCU_LVLS 1
@@ -45,23 +46,33 @@
45# define NUM_RCU_LVL_1 (NR_CPUS) 46# define NUM_RCU_LVL_1 (NR_CPUS)
46# define NUM_RCU_LVL_2 0 47# define NUM_RCU_LVL_2 0
47# define NUM_RCU_LVL_3 0 48# define NUM_RCU_LVL_3 0
49# define NUM_RCU_LVL_4 0
48#elif NR_CPUS <= RCU_FANOUT_SQ 50#elif NR_CPUS <= RCU_FANOUT_SQ
49# define NUM_RCU_LVLS 2 51# define NUM_RCU_LVLS 2
50# define NUM_RCU_LVL_0 1 52# define NUM_RCU_LVL_0 1
51# define NUM_RCU_LVL_1 DIV_ROUND_UP(NR_CPUS, RCU_FANOUT) 53# define NUM_RCU_LVL_1 DIV_ROUND_UP(NR_CPUS, RCU_FANOUT)
52# define NUM_RCU_LVL_2 (NR_CPUS) 54# define NUM_RCU_LVL_2 (NR_CPUS)
53# define NUM_RCU_LVL_3 0 55# define NUM_RCU_LVL_3 0
56# define NUM_RCU_LVL_4 0
54#elif NR_CPUS <= RCU_FANOUT_CUBE 57#elif NR_CPUS <= RCU_FANOUT_CUBE
55# define NUM_RCU_LVLS 3 58# define NUM_RCU_LVLS 3
56# define NUM_RCU_LVL_0 1 59# define NUM_RCU_LVL_0 1
57# define NUM_RCU_LVL_1 DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_SQ) 60# define NUM_RCU_LVL_1 DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_SQ)
58# define NUM_RCU_LVL_2 DIV_ROUND_UP(NR_CPUS, RCU_FANOUT) 61# define NUM_RCU_LVL_2 DIV_ROUND_UP(NR_CPUS, RCU_FANOUT)
59# define NUM_RCU_LVL_3 NR_CPUS 62# define NUM_RCU_LVL_3 NR_CPUS
63# define NUM_RCU_LVL_4 0
64#elif NR_CPUS <= RCU_FANOUT_FOURTH
65# define NUM_RCU_LVLS 4
66# define NUM_RCU_LVL_0 1
67# define NUM_RCU_LVL_1 DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_CUBE)
68# define NUM_RCU_LVL_2 DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_SQ)
69# define NUM_RCU_LVL_3 DIV_ROUND_UP(NR_CPUS, RCU_FANOUT)
70# define NUM_RCU_LVL_4 NR_CPUS
60#else 71#else
61# error "CONFIG_RCU_FANOUT insufficient for NR_CPUS" 72# error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
62#endif /* #if (NR_CPUS) <= RCU_FANOUT */ 73#endif /* #if (NR_CPUS) <= RCU_FANOUT */
63 74
64#define RCU_SUM (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3) 75#define RCU_SUM (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3 + NUM_RCU_LVL_4)
65#define NUM_RCU_NODES (RCU_SUM - NR_CPUS) 76#define NUM_RCU_NODES (RCU_SUM - NR_CPUS)
66 77
67/* 78/*
@@ -79,9 +90,12 @@ struct rcu_dynticks {
79 * Definition for node within the RCU grace-period-detection hierarchy. 90 * Definition for node within the RCU grace-period-detection hierarchy.
80 */ 91 */
81struct rcu_node { 92struct rcu_node {
82 spinlock_t lock; /* Root rcu_node's lock protects some */ 93 raw_spinlock_t lock; /* Root rcu_node's lock protects some */
83 /* rcu_state fields as well as following. */ 94 /* rcu_state fields as well as following. */
84 long gpnum; /* Current grace period for this node. */ 95 unsigned long gpnum; /* Current grace period for this node. */
96 /* This will either be equal to or one */
97 /* behind the root rcu_node's gpnum. */
98 unsigned long completed; /* Last GP completed for this node. */
85 /* This will either be equal to or one */ 99 /* This will either be equal to or one */
86 /* behind the root rcu_node's gpnum. */ 100 /* behind the root rcu_node's gpnum. */
87 unsigned long qsmask; /* CPUs or groups that need to switch in */ 101 unsigned long qsmask; /* CPUs or groups that need to switch in */
@@ -90,8 +104,12 @@ struct rcu_node {
90 /* an rcu_data structure, otherwise, each */ 104 /* an rcu_data structure, otherwise, each */
91 /* bit corresponds to a child rcu_node */ 105 /* bit corresponds to a child rcu_node */
92 /* structure. */ 106 /* structure. */
107 unsigned long expmask; /* Groups that have ->blocked_tasks[] */
108 /* elements that need to drain to allow the */
109 /* current expedited grace period to */
110 /* complete (only for TREE_PREEMPT_RCU). */
93 unsigned long qsmaskinit; 111 unsigned long qsmaskinit;
94 /* Per-GP initialization for qsmask. */ 112 /* Per-GP initial value for qsmask & expmask. */
95 unsigned long grpmask; /* Mask to apply to parent qsmask. */ 113 unsigned long grpmask; /* Mask to apply to parent qsmask. */
96 /* Only one bit will be set in this mask. */ 114 /* Only one bit will be set in this mask. */
97 int grplo; /* lowest-numbered CPU or group here. */ 115 int grplo; /* lowest-numbered CPU or group here. */
@@ -99,7 +117,7 @@ struct rcu_node {
99 u8 grpnum; /* CPU/group number for next level up. */ 117 u8 grpnum; /* CPU/group number for next level up. */
100 u8 level; /* root is at level 0. */ 118 u8 level; /* root is at level 0. */
101 struct rcu_node *parent; 119 struct rcu_node *parent;
102 struct list_head blocked_tasks[2]; 120 struct list_head blocked_tasks[4];
103 /* Tasks blocked in RCU read-side critsect. */ 121 /* Tasks blocked in RCU read-side critsect. */
104 /* Grace period number (->gpnum) x blocked */ 122 /* Grace period number (->gpnum) x blocked */
105 /* by tasks on the (x & 0x1) element of the */ 123 /* by tasks on the (x & 0x1) element of the */
@@ -114,6 +132,21 @@ struct rcu_node {
114 for ((rnp) = &(rsp)->node[0]; \ 132 for ((rnp) = &(rsp)->node[0]; \
115 (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++) 133 (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++)
116 134
135/*
136 * Do a breadth-first scan of the non-leaf rcu_node structures for the
137 * specified rcu_state structure. Note that if there is a singleton
138 * rcu_node tree with but one rcu_node structure, this loop is a no-op.
139 */
140#define rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) \
141 for ((rnp) = &(rsp)->node[0]; \
142 (rnp) < (rsp)->level[NUM_RCU_LVLS - 1]; (rnp)++)
143
144/*
145 * Scan the leaves of the rcu_node hierarchy for the specified rcu_state
146 * structure. Note that if there is a singleton rcu_node tree with but
147 * one rcu_node structure, this loop -will- visit the rcu_node structure.
148 * It is still a leaf node, even if it is also the root node.
149 */
117#define rcu_for_each_leaf_node(rsp, rnp) \ 150#define rcu_for_each_leaf_node(rsp, rnp) \
118 for ((rnp) = (rsp)->level[NUM_RCU_LVLS - 1]; \ 151 for ((rnp) = (rsp)->level[NUM_RCU_LVLS - 1]; \
119 (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++) 152 (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++)
@@ -128,11 +161,11 @@ struct rcu_node {
128/* Per-CPU data for read-copy update. */ 161/* Per-CPU data for read-copy update. */
129struct rcu_data { 162struct rcu_data {
130 /* 1) quiescent-state and grace-period handling : */ 163 /* 1) quiescent-state and grace-period handling : */
131 long completed; /* Track rsp->completed gp number */ 164 unsigned long completed; /* Track rsp->completed gp number */
132 /* in order to detect GP end. */ 165 /* in order to detect GP end. */
133 long gpnum; /* Highest gp number that this CPU */ 166 unsigned long gpnum; /* Highest gp number that this CPU */
134 /* is aware of having started. */ 167 /* is aware of having started. */
135 long passed_quiesc_completed; 168 unsigned long passed_quiesc_completed;
136 /* Value of completed at time of qs. */ 169 /* Value of completed at time of qs. */
137 bool passed_quiesc; /* User-mode/idle loop etc. */ 170 bool passed_quiesc; /* User-mode/idle loop etc. */
138 bool qs_pending; /* Core waits for quiesc state. */ 171 bool qs_pending; /* Core waits for quiesc state. */
@@ -188,14 +221,14 @@ struct rcu_data {
188 unsigned long resched_ipi; /* Sent a resched IPI. */ 221 unsigned long resched_ipi; /* Sent a resched IPI. */
189 222
190 /* 5) __rcu_pending() statistics. */ 223 /* 5) __rcu_pending() statistics. */
191 long n_rcu_pending; /* rcu_pending() calls since boot. */ 224 unsigned long n_rcu_pending; /* rcu_pending() calls since boot. */
192 long n_rp_qs_pending; 225 unsigned long n_rp_qs_pending;
193 long n_rp_cb_ready; 226 unsigned long n_rp_cb_ready;
194 long n_rp_cpu_needs_gp; 227 unsigned long n_rp_cpu_needs_gp;
195 long n_rp_gp_completed; 228 unsigned long n_rp_gp_completed;
196 long n_rp_gp_started; 229 unsigned long n_rp_gp_started;
197 long n_rp_need_fqs; 230 unsigned long n_rp_need_fqs;
198 long n_rp_need_nothing; 231 unsigned long n_rp_need_nothing;
199 232
200 int cpu; 233 int cpu;
201}; 234};
@@ -213,15 +246,27 @@ struct rcu_data {
213 246
214#define RCU_JIFFIES_TILL_FORCE_QS 3 /* for rsp->jiffies_force_qs */ 247#define RCU_JIFFIES_TILL_FORCE_QS 3 /* for rsp->jiffies_force_qs */
215#ifdef CONFIG_RCU_CPU_STALL_DETECTOR 248#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
216#define RCU_SECONDS_TILL_STALL_CHECK (10 * HZ) /* for rsp->jiffies_stall */ 249
217#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ) /* for rsp->jiffies_stall */ 250#ifdef CONFIG_PROVE_RCU
218#define RCU_STALL_RAT_DELAY 2 /* Allow other CPUs time */ 251#define RCU_STALL_DELAY_DELTA (5 * HZ)
219 /* to take at least one */ 252#else
220 /* scheduling clock irq */ 253#define RCU_STALL_DELAY_DELTA 0
221 /* before ratting on them. */ 254#endif
255
256#define RCU_SECONDS_TILL_STALL_CHECK (10 * HZ + RCU_STALL_DELAY_DELTA)
257 /* for rsp->jiffies_stall */
258#define RCU_SECONDS_TILL_STALL_RECHECK (30 * HZ + RCU_STALL_DELAY_DELTA)
259 /* for rsp->jiffies_stall */
260#define RCU_STALL_RAT_DELAY 2 /* Allow other CPUs time */
261 /* to take at least one */
262 /* scheduling clock irq */
263 /* before ratting on them. */
222 264
223#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ 265#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
224 266
267#define ULONG_CMP_GE(a, b) (ULONG_MAX / 2 >= (a) - (b))
268#define ULONG_CMP_LT(a, b) (ULONG_MAX / 2 < (a) - (b))
269
225/* 270/*
226 * RCU global state, including node hierarchy. This hierarchy is 271 * RCU global state, including node hierarchy. This hierarchy is
227 * represented in "heap" form in a dense array. The root (first level) 272 * represented in "heap" form in a dense array. The root (first level)
@@ -243,12 +288,19 @@ struct rcu_state {
243 288
244 u8 signaled ____cacheline_internodealigned_in_smp; 289 u8 signaled ____cacheline_internodealigned_in_smp;
245 /* Force QS state. */ 290 /* Force QS state. */
246 long gpnum; /* Current gp number. */ 291 u8 fqs_active; /* force_quiescent_state() */
247 long completed; /* # of last completed gp. */ 292 /* is running. */
293 u8 fqs_need_gp; /* A CPU was prevented from */
294 /* starting a new grace */
295 /* period because */
296 /* force_quiescent_state() */
297 /* was running. */
298 unsigned long gpnum; /* Current gp number. */
299 unsigned long completed; /* # of last completed gp. */
248 300
249 /* End of fields guarded by root rcu_node's lock. */ 301 /* End of fields guarded by root rcu_node's lock. */
250 302
251 spinlock_t onofflock; /* exclude on/offline and */ 303 raw_spinlock_t onofflock; /* exclude on/offline and */
252 /* starting new GP. Also */ 304 /* starting new GP. Also */
253 /* protects the following */ 305 /* protects the following */
254 /* orphan_cbs fields. */ 306 /* orphan_cbs fields. */
@@ -258,7 +310,7 @@ struct rcu_state {
258 /* going offline. */ 310 /* going offline. */
259 struct rcu_head **orphan_cbs_tail; /* And tail pointer. */ 311 struct rcu_head **orphan_cbs_tail; /* And tail pointer. */
260 long orphan_qlen; /* Number of orphaned cbs. */ 312 long orphan_qlen; /* Number of orphaned cbs. */
261 spinlock_t fqslock; /* Only one task forcing */ 313 raw_spinlock_t fqslock; /* Only one task forcing */
262 /* quiescent states. */ 314 /* quiescent states. */
263 unsigned long jiffies_force_qs; /* Time at which to invoke */ 315 unsigned long jiffies_force_qs; /* Time at which to invoke */
264 /* force_quiescent_state(). */ 316 /* force_quiescent_state(). */
@@ -274,12 +326,14 @@ struct rcu_state {
274 unsigned long jiffies_stall; /* Time at which to check */ 326 unsigned long jiffies_stall; /* Time at which to check */
275 /* for CPU stalls. */ 327 /* for CPU stalls. */
276#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ 328#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
277#ifdef CONFIG_NO_HZ
278 long dynticks_completed; /* Value of completed @ snap. */
279#endif /* #ifdef CONFIG_NO_HZ */
280}; 329};
281 330
282#ifdef RCU_TREE_NONCORE 331/* Return values for rcu_preempt_offline_tasks(). */
332
333#define RCU_OFL_TASKS_NORM_GP 0x1 /* Tasks blocking normal */
334 /* GP were moved to root. */
335#define RCU_OFL_TASKS_EXP_GP 0x2 /* Tasks blocking expedited */
336 /* GP were moved to root. */
283 337
284/* 338/*
285 * RCU implementation internal declarations: 339 * RCU implementation internal declarations:
@@ -295,14 +349,19 @@ extern struct rcu_state rcu_preempt_state;
295DECLARE_PER_CPU(struct rcu_data, rcu_preempt_data); 349DECLARE_PER_CPU(struct rcu_data, rcu_preempt_data);
296#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ 350#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
297 351
298#else /* #ifdef RCU_TREE_NONCORE */ 352#ifndef RCU_TREE_NONCORE
299 353
300/* Forward declarations for rcutree_plugin.h */ 354/* Forward declarations for rcutree_plugin.h */
301static inline void rcu_bootup_announce(void); 355static void rcu_bootup_announce(void);
302long rcu_batches_completed(void); 356long rcu_batches_completed(void);
303static void rcu_preempt_note_context_switch(int cpu); 357static void rcu_preempt_note_context_switch(int cpu);
304static int rcu_preempted_readers(struct rcu_node *rnp); 358static int rcu_preempted_readers(struct rcu_node *rnp);
359#ifdef CONFIG_HOTPLUG_CPU
360static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp,
361 unsigned long flags);
362#endif /* #ifdef CONFIG_HOTPLUG_CPU */
305#ifdef CONFIG_RCU_CPU_STALL_DETECTOR 363#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
364static void rcu_print_detail_task_stall(struct rcu_state *rsp);
306static void rcu_print_task_stall(struct rcu_node *rnp); 365static void rcu_print_task_stall(struct rcu_node *rnp);
307#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ 366#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
308static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp); 367static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
@@ -315,10 +374,14 @@ static void rcu_preempt_offline_cpu(int cpu);
315static void rcu_preempt_check_callbacks(int cpu); 374static void rcu_preempt_check_callbacks(int cpu);
316static void rcu_preempt_process_callbacks(void); 375static void rcu_preempt_process_callbacks(void);
317void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); 376void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
377#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU)
378static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp);
379#endif /* #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) */
318static int rcu_preempt_pending(int cpu); 380static int rcu_preempt_pending(int cpu);
319static int rcu_preempt_needs_cpu(int cpu); 381static int rcu_preempt_needs_cpu(int cpu);
320static void __cpuinit rcu_preempt_init_percpu_data(int cpu); 382static void __cpuinit rcu_preempt_init_percpu_data(int cpu);
321static void rcu_preempt_send_cbs_to_orphanage(void); 383static void rcu_preempt_send_cbs_to_orphanage(void);
322static void __init __rcu_init_preempt(void); 384static void __init __rcu_init_preempt(void);
385static void rcu_needs_cpu_flush(void);
323 386
324#endif /* #else #ifdef RCU_TREE_NONCORE */ 387#endif /* #ifndef RCU_TREE_NONCORE */