aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2009-09-23 12:50:42 -0400
committerIngo Molnar <mingo@elte.hu>2009-09-23 13:46:29 -0400
commit1eba8f84380bede3c602bd7758dea96925cead01 (patch)
tree32dd97671016c9fdc24d75be50cc8540e6cc0730
parentfc2219d49ef1606e7fd2c88af2b423b01ff3d319 (diff)
rcu: Clean up code based on review feedback from Josh Triplett, part 2
These issues identified during an old-fashioned face-to-face code review extending over many hours. o Add comments for tricky parts of code, and correct comments that have passed their sell-by date. o Get rid of the vestiges of rcu_init_sched(), which is no longer needed now that PREEMPT_RCU is gone. o Move the #include of rcutree_plugin.h to the end of rcutree.c, which means that, rather than having a random collection of forward declarations, the new set of forward declarations document the set of plugins. The new home for this #include also allows __rcu_init_preempt() to move into rcutree_plugin.h. o Fix rcu_preempt_check_callbacks() to be static. Suggested-by: Josh Triplett <josh@joshtriplett.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: laijs@cn.fujitsu.com Cc: dipankar@in.ibm.com Cc: akpm@linux-foundation.org Cc: mathieu.desnoyers@polymtl.ca Cc: josh@joshtriplett.org Cc: dvhltc@us.ibm.com Cc: niv@us.ibm.com Cc: peterz@infradead.org Cc: rostedt@goodmis.org Cc: Valdis.Kletnieks@vt.edu Cc: dhowells@redhat.com LKML-Reference: <12537246443924-git-send-email-> Signed-off-by: Ingo Molnar <mingo@elte.hu> Peter Zijlstra <peterz@infradead.org>
-rw-r--r--include/linux/rcupdate.h4
-rw-r--r--include/linux/rcutree.h6
-rw-r--r--init/main.c1
-rw-r--r--kernel/rcutree.c72
-rw-r--r--kernel/rcutree.h31
-rw-r--r--kernel/rcutree_plugin.h23
6 files changed, 82 insertions, 55 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 6fe0363724e9..70331218e4b4 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -196,6 +196,8 @@ static inline void rcu_read_lock_sched(void)
196 __acquire(RCU_SCHED); 196 __acquire(RCU_SCHED);
197 rcu_read_acquire(); 197 rcu_read_acquire();
198} 198}
199
200/* Used by lockdep and tracing: cannot be traced, cannot call lockdep. */
199static inline notrace void rcu_read_lock_sched_notrace(void) 201static inline notrace void rcu_read_lock_sched_notrace(void)
200{ 202{
201 preempt_disable_notrace(); 203 preempt_disable_notrace();
@@ -213,6 +215,8 @@ static inline void rcu_read_unlock_sched(void)
213 __release(RCU_SCHED); 215 __release(RCU_SCHED);
214 preempt_enable(); 216 preempt_enable();
215} 217}
218
219/* Used by lockdep and tracing: cannot be traced, cannot call lockdep. */
216static inline notrace void rcu_read_unlock_sched_notrace(void) 220static inline notrace void rcu_read_unlock_sched_notrace(void)
217{ 221{
218 __release(RCU_SCHED); 222 __release(RCU_SCHED);
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 88109c87f29c..19a3b06943e0 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -90,10 +90,6 @@ extern long rcu_batches_completed(void);
90extern long rcu_batches_completed_bh(void); 90extern long rcu_batches_completed_bh(void);
91extern long rcu_batches_completed_sched(void); 91extern long rcu_batches_completed_sched(void);
92 92
93static inline void rcu_init_sched(void)
94{
95}
96
97#ifdef CONFIG_NO_HZ 93#ifdef CONFIG_NO_HZ
98void rcu_enter_nohz(void); 94void rcu_enter_nohz(void);
99void rcu_exit_nohz(void); 95void rcu_exit_nohz(void);
@@ -106,7 +102,7 @@ static inline void rcu_exit_nohz(void)
106} 102}
107#endif /* CONFIG_NO_HZ */ 103#endif /* CONFIG_NO_HZ */
108 104
109/* A context switch is a grace period for rcutree. */ 105/* A context switch is a grace period for RCU-sched and RCU-bh. */
110static inline int rcu_blocking_is_gp(void) 106static inline int rcu_blocking_is_gp(void)
111{ 107{
112 return num_online_cpus() == 1; 108 return num_online_cpus() == 1;
diff --git a/init/main.c b/init/main.c
index 34971becbd3c..833d675677d1 100644
--- a/init/main.c
+++ b/init/main.c
@@ -782,7 +782,6 @@ static void __init do_initcalls(void)
782 */ 782 */
783static void __init do_basic_setup(void) 783static void __init do_basic_setup(void)
784{ 784{
785 rcu_init_sched(); /* needed by module_init stage. */
786 init_workqueues(); 785 init_workqueues();
787 cpuset_init_smp(); 786 cpuset_init_smp();
788 usermodehelper_init(); 787 usermodehelper_init();
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index f85b6842d1e1..53a5ef0ca911 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -81,24 +81,29 @@ DEFINE_PER_CPU(struct rcu_data, rcu_sched_data);
81struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state); 81struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state);
82DEFINE_PER_CPU(struct rcu_data, rcu_bh_data); 82DEFINE_PER_CPU(struct rcu_data, rcu_bh_data);
83 83
84extern long rcu_batches_completed_sched(void); 84/* Forward declarations for rcutree_plugin.h */
85static struct rcu_node *rcu_get_root(struct rcu_state *rsp); 85static inline void rcu_bootup_announce(void);
86static void cpu_quiet_msk(unsigned long mask, struct rcu_state *rsp, 86long rcu_batches_completed(void);
87 struct rcu_node *rnp, unsigned long flags); 87static void rcu_preempt_note_context_switch(int cpu);
88static void cpu_quiet_msk_finish(struct rcu_state *rsp, unsigned long flags); 88static int rcu_preempted_readers(struct rcu_node *rnp);
89#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
90static void rcu_print_task_stall(struct rcu_node *rnp);
91#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
92static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
89#ifdef CONFIG_HOTPLUG_CPU 93#ifdef CONFIG_HOTPLUG_CPU
90static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp); 94static void rcu_preempt_offline_tasks(struct rcu_state *rsp,
95 struct rcu_node *rnp,
96 struct rcu_data *rdp);
97static void rcu_preempt_offline_cpu(int cpu);
91#endif /* #ifdef CONFIG_HOTPLUG_CPU */ 98#endif /* #ifdef CONFIG_HOTPLUG_CPU */
92static void __rcu_process_callbacks(struct rcu_state *rsp, 99static void rcu_preempt_check_callbacks(int cpu);
93 struct rcu_data *rdp); 100static void rcu_preempt_process_callbacks(void);
94static void __call_rcu(struct rcu_head *head, 101void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
95 void (*func)(struct rcu_head *rcu), 102static int rcu_preempt_pending(int cpu);
96 struct rcu_state *rsp); 103static int rcu_preempt_needs_cpu(int cpu);
97static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp); 104static void __cpuinit rcu_preempt_init_percpu_data(int cpu);
98static void __cpuinit rcu_init_percpu_data(int cpu, struct rcu_state *rsp, 105static void __init __rcu_init_preempt(void);
99 int preemptable);
100 106
101#include "rcutree_plugin.h"
102 107
103/* 108/*
104 * Return true if an RCU grace period is in progress. The ACCESS_ONCE()s 109 * Return true if an RCU grace period is in progress. The ACCESS_ONCE()s
@@ -377,7 +382,7 @@ static long dyntick_recall_completed(struct rcu_state *rsp)
377/* 382/*
378 * Snapshot the specified CPU's dynticks counter so that we can later 383 * Snapshot the specified CPU's dynticks counter so that we can later
379 * credit them with an implicit quiescent state. Return 1 if this CPU 384 * credit them with an implicit quiescent state. Return 1 if this CPU
380 * is already in a quiescent state courtesy of dynticks idle mode. 385 * is in dynticks idle mode, which is an extended quiescent state.
381 */ 386 */
382static int dyntick_save_progress_counter(struct rcu_data *rdp) 387static int dyntick_save_progress_counter(struct rcu_data *rdp)
383{ 388{
@@ -624,9 +629,15 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
624 note_new_gpnum(rsp, rdp); 629 note_new_gpnum(rsp, rdp);
625 630
626 /* 631 /*
627 * Because we are first, we know that all our callbacks will 632 * Because this CPU just now started the new grace period, we know
628 * be covered by this upcoming grace period, even the ones 633 * that all of its callbacks will be covered by this upcoming grace
629 * that were registered arbitrarily recently. 634 * period, even the ones that were registered arbitrarily recently.
635 * Therefore, advance all outstanding callbacks to RCU_WAIT_TAIL.
636 *
637 * Other CPUs cannot be sure exactly when the grace period started.
638 * Therefore, their recently registered callbacks must pass through
639 * an additional RCU_NEXT_READY stage, so that they will be handled
640 * by the next RCU grace period.
630 */ 641 */
631 rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; 642 rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
632 rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; 643 rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];
@@ -886,7 +897,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
886 897
887 /* 898 /*
888 * Move callbacks from the outgoing CPU to the running CPU. 899 * Move callbacks from the outgoing CPU to the running CPU.
889 * Note that the outgoing CPU is now quiscent, so it is now 900 * Note that the outgoing CPU is now quiescent, so it is now
890 * (uncharacteristically) safe to access its rcu_data structure. 901 * (uncharacteristically) safe to access its rcu_data structure.
891 * Note also that we must carefully retain the order of the 902 * Note also that we must carefully retain the order of the
892 * outgoing CPU's callbacks in order for rcu_barrier() to work 903 * outgoing CPU's callbacks in order for rcu_barrier() to work
@@ -1577,25 +1588,6 @@ do { \
1577 } \ 1588 } \
1578} while (0) 1589} while (0)
1579 1590
1580#ifdef CONFIG_TREE_PREEMPT_RCU
1581
1582void __init __rcu_init_preempt(void)
1583{
1584 int i; /* All used by RCU_INIT_FLAVOR(). */
1585 int j;
1586 struct rcu_node *rnp;
1587
1588 RCU_INIT_FLAVOR(&rcu_preempt_state, rcu_preempt_data);
1589}
1590
1591#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
1592
1593void __init __rcu_init_preempt(void)
1594{
1595}
1596
1597#endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */
1598
1599void __init __rcu_init(void) 1591void __init __rcu_init(void)
1600{ 1592{
1601 int i; /* All used by RCU_INIT_FLAVOR(). */ 1593 int i; /* All used by RCU_INIT_FLAVOR(). */
@@ -1612,6 +1604,8 @@ void __init __rcu_init(void)
1612 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); 1604 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
1613} 1605}
1614 1606
1607#include "rcutree_plugin.h"
1608
1615module_param(blimit, int, 0); 1609module_param(blimit, int, 0);
1616module_param(qhimark, int, 0); 1610module_param(qhimark, int, 0);
1617module_param(qlowmark, int, 0); 1611module_param(qlowmark, int, 0);
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 9aa8c8a160d8..a48d11f37b4c 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -79,15 +79,21 @@ struct rcu_dynticks {
79 * Definition for node within the RCU grace-period-detection hierarchy. 79 * Definition for node within the RCU grace-period-detection hierarchy.
80 */ 80 */
81struct rcu_node { 81struct rcu_node {
82 spinlock_t lock; 82 spinlock_t lock; /* Root rcu_node's lock protects some */
83 /* rcu_state fields as well as following. */
83 long gpnum; /* Current grace period for this node. */ 84 long gpnum; /* Current grace period for this node. */
84 /* This will either be equal to or one */ 85 /* This will either be equal to or one */
85 /* behind the root rcu_node's gpnum. */ 86 /* behind the root rcu_node's gpnum. */
86 unsigned long qsmask; /* CPUs or groups that need to switch in */ 87 unsigned long qsmask; /* CPUs or groups that need to switch in */
87 /* order for current grace period to proceed.*/ 88 /* order for current grace period to proceed.*/
89 /* In leaf rcu_node, each bit corresponds to */
90 /* an rcu_data structure, otherwise, each */
91 /* bit corresponds to a child rcu_node */
92 /* structure. */
88 unsigned long qsmaskinit; 93 unsigned long qsmaskinit;
89 /* Per-GP initialization for qsmask. */ 94 /* Per-GP initialization for qsmask. */
90 unsigned long grpmask; /* Mask to apply to parent qsmask. */ 95 unsigned long grpmask; /* Mask to apply to parent qsmask. */
96 /* Only one bit will be set in this mask. */
91 int grplo; /* lowest-numbered CPU or group here. */ 97 int grplo; /* lowest-numbered CPU or group here. */
92 int grphi; /* highest-numbered CPU or group here. */ 98 int grphi; /* highest-numbered CPU or group here. */
93 u8 grpnum; /* CPU/group number for next level up. */ 99 u8 grpnum; /* CPU/group number for next level up. */
@@ -95,6 +101,9 @@ struct rcu_node {
95 struct rcu_node *parent; 101 struct rcu_node *parent;
96 struct list_head blocked_tasks[2]; 102 struct list_head blocked_tasks[2];
97 /* Tasks blocked in RCU read-side critsect. */ 103 /* Tasks blocked in RCU read-side critsect. */
104 /* Grace period number (->gpnum) x blocked */
105 /* by tasks on the (x & 0x1) element of the */
106 /* blocked_tasks[] array. */
98} ____cacheline_internodealigned_in_smp; 107} ____cacheline_internodealigned_in_smp;
99 108
100/* Index values for nxttail array in struct rcu_data. */ 109/* Index values for nxttail array in struct rcu_data. */
@@ -126,19 +135,22 @@ struct rcu_data {
126 * Any of the partitions might be empty, in which case the 135 * Any of the partitions might be empty, in which case the
127 * pointer to that partition will be equal to the pointer for 136 * pointer to that partition will be equal to the pointer for
128 * the following partition. When the list is empty, all of 137 * the following partition. When the list is empty, all of
129 * the nxttail elements point to nxtlist, which is NULL. 138 * the nxttail elements point to the ->nxtlist pointer itself,
139 * which in that case is NULL.
130 * 140 *
131 * [*nxttail[RCU_NEXT_READY_TAIL], NULL = *nxttail[RCU_NEXT_TAIL]):
132 * Entries that might have arrived after current GP ended
133 * [*nxttail[RCU_WAIT_TAIL], *nxttail[RCU_NEXT_READY_TAIL]):
134 * Entries known to have arrived before current GP ended
135 * [*nxttail[RCU_DONE_TAIL], *nxttail[RCU_WAIT_TAIL]):
136 * Entries that batch # <= ->completed - 1: waiting for current GP
137 * [nxtlist, *nxttail[RCU_DONE_TAIL]): 141 * [nxtlist, *nxttail[RCU_DONE_TAIL]):
138 * Entries that batch # <= ->completed 142 * Entries that batch # <= ->completed
139 * The grace period for these entries has completed, and 143 * The grace period for these entries has completed, and
140 * the other grace-period-completed entries may be moved 144 * the other grace-period-completed entries may be moved
141 * here temporarily in rcu_process_callbacks(). 145 * here temporarily in rcu_process_callbacks().
146 * [*nxttail[RCU_DONE_TAIL], *nxttail[RCU_WAIT_TAIL]):
147 * Entries that batch # <= ->completed - 1: waiting for current GP
148 * [*nxttail[RCU_WAIT_TAIL], *nxttail[RCU_NEXT_READY_TAIL]):
149 * Entries known to have arrived before current GP ended
150 * [*nxttail[RCU_NEXT_READY_TAIL], *nxttail[RCU_NEXT_TAIL]):
151 * Entries that might have arrived after current GP ended
152 * Note that the value of *nxttail[RCU_NEXT_TAIL] will
153 * always be NULL, as this is the end of the list.
142 */ 154 */
143 struct rcu_head *nxtlist; 155 struct rcu_head *nxtlist;
144 struct rcu_head **nxttail[RCU_NEXT_SIZE]; 156 struct rcu_head **nxttail[RCU_NEXT_SIZE];
@@ -216,6 +228,9 @@ struct rcu_state {
216 /* Force QS state. */ 228 /* Force QS state. */
217 long gpnum; /* Current gp number. */ 229 long gpnum; /* Current gp number. */
218 long completed; /* # of last completed gp. */ 230 long completed; /* # of last completed gp. */
231
232 /* End of fields guarded by root rcu_node's lock. */
233
219 spinlock_t onofflock; /* exclude on/offline and */ 234 spinlock_t onofflock; /* exclude on/offline and */
220 /* starting new GP. */ 235 /* starting new GP. */
221 spinlock_t fqslock; /* Only one task forcing */ 236 spinlock_t fqslock; /* Only one task forcing */
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 8ff1ba7b3c43..65250219ab6d 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -419,6 +419,18 @@ static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
419} 419}
420 420
421/* 421/*
422 * Initialize preemptable RCU's state structures.
423 */
424static void __init __rcu_init_preempt(void)
425{
426 int i; /* All used by RCU_INIT_FLAVOR(). */
427 int j;
428 struct rcu_node *rnp;
429
430 RCU_INIT_FLAVOR(&rcu_preempt_state, rcu_preempt_data);
431}
432
433/*
422 * Check for a task exiting while in a preemptable-RCU read-side 434 * Check for a task exiting while in a preemptable-RCU read-side
423 * critical section, clean up if so. No need to issue warnings, 435 * critical section, clean up if so. No need to issue warnings,
424 * as debug_check_no_locks_held() already does this if lockdep 436 * as debug_check_no_locks_held() already does this if lockdep
@@ -518,7 +530,7 @@ static void rcu_preempt_offline_cpu(int cpu)
518 * Because preemptable RCU does not exist, it never has any callbacks 530 * Because preemptable RCU does not exist, it never has any callbacks
519 * to check. 531 * to check.
520 */ 532 */
521void rcu_preempt_check_callbacks(int cpu) 533static void rcu_preempt_check_callbacks(int cpu)
522{ 534{
523} 535}
524 536
@@ -526,7 +538,7 @@ void rcu_preempt_check_callbacks(int cpu)
526 * Because preemptable RCU does not exist, it never has any callbacks 538 * Because preemptable RCU does not exist, it never has any callbacks
527 * to process. 539 * to process.
528 */ 540 */
529void rcu_preempt_process_callbacks(void) 541static void rcu_preempt_process_callbacks(void)
530{ 542{
531} 543}
532 544
@@ -563,4 +575,11 @@ static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
563{ 575{
564} 576}
565 577
578/*
579 * Because preemptable RCU does not exist, it need not be initialized.
580 */
581static void __init __rcu_init_preempt(void)
582{
583}
584
566#endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */ 585#endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */