aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2010-06-28 04:25:04 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2010-08-19 20:18:01 -0400
commit394f99a9007d4274f7076bb8553ab0ff9707688b (patch)
tree7d379f91321cec58b87fd5f5089947872689d591 /kernel
parente546f485e1d7520ca0200502cdcc11b503f4805c (diff)
rcu: simplify the usage of percpu data
&percpu_data is compatible with allocated percpu data. And we use it and remove the "->rda[NR_CPUS]" array, saving significant storage on systems with large numbers of CPUs. This does add an additional level of indirection and thus an additional cache line referenced, but because ->rda is not used on the read side, this is OK. Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Reviewed-by: Tejun Heo <tj@kernel.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/rcutree.c42
-rw-r--r--kernel/rcutree.h2
-rw-r--r--kernel/rcutree_plugin.h4
-rw-r--r--kernel/rcutree_trace.c2
4 files changed, 19 insertions, 31 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index d5bc43976c5a..5b1c3c231bae 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -712,7 +712,7 @@ static void
712rcu_start_gp(struct rcu_state *rsp, unsigned long flags) 712rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
713 __releases(rcu_get_root(rsp)->lock) 713 __releases(rcu_get_root(rsp)->lock)
714{ 714{
715 struct rcu_data *rdp = rsp->rda[smp_processor_id()]; 715 struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
716 struct rcu_node *rnp = rcu_get_root(rsp); 716 struct rcu_node *rnp = rcu_get_root(rsp);
717 717
718 if (!cpu_needs_another_gp(rsp, rdp) || rsp->fqs_active) { 718 if (!cpu_needs_another_gp(rsp, rdp) || rsp->fqs_active) {
@@ -960,7 +960,7 @@ rcu_check_quiescent_state(struct rcu_state *rsp, struct rcu_data *rdp)
960static void rcu_send_cbs_to_orphanage(struct rcu_state *rsp) 960static void rcu_send_cbs_to_orphanage(struct rcu_state *rsp)
961{ 961{
962 int i; 962 int i;
963 struct rcu_data *rdp = rsp->rda[smp_processor_id()]; 963 struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
964 964
965 if (rdp->nxtlist == NULL) 965 if (rdp->nxtlist == NULL)
966 return; /* irqs disabled, so comparison is stable. */ 966 return; /* irqs disabled, so comparison is stable. */
@@ -984,7 +984,7 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)
984 struct rcu_data *rdp; 984 struct rcu_data *rdp;
985 985
986 raw_spin_lock_irqsave(&rsp->onofflock, flags); 986 raw_spin_lock_irqsave(&rsp->onofflock, flags);
987 rdp = rsp->rda[smp_processor_id()]; 987 rdp = this_cpu_ptr(rsp->rda);
988 if (rsp->orphan_cbs_list == NULL) { 988 if (rsp->orphan_cbs_list == NULL) {
989 raw_spin_unlock_irqrestore(&rsp->onofflock, flags); 989 raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
990 return; 990 return;
@@ -1007,7 +1007,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
1007 unsigned long flags; 1007 unsigned long flags;
1008 unsigned long mask; 1008 unsigned long mask;
1009 int need_report = 0; 1009 int need_report = 0;
1010 struct rcu_data *rdp = rsp->rda[cpu]; 1010 struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
1011 struct rcu_node *rnp; 1011 struct rcu_node *rnp;
1012 1012
1013 /* Exclude any attempts to start a new grace period. */ 1013 /* Exclude any attempts to start a new grace period. */
@@ -1226,7 +1226,8 @@ static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *))
1226 cpu = rnp->grplo; 1226 cpu = rnp->grplo;
1227 bit = 1; 1227 bit = 1;
1228 for (; cpu <= rnp->grphi; cpu++, bit <<= 1) { 1228 for (; cpu <= rnp->grphi; cpu++, bit <<= 1) {
1229 if ((rnp->qsmask & bit) != 0 && f(rsp->rda[cpu])) 1229 if ((rnp->qsmask & bit) != 0 &&
1230 f(per_cpu_ptr(rsp->rda, cpu)))
1230 mask |= bit; 1231 mask |= bit;
1231 } 1232 }
1232 if (mask != 0) { 1233 if (mask != 0) {
@@ -1402,7 +1403,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
1402 * a quiescent state betweentimes. 1403 * a quiescent state betweentimes.
1403 */ 1404 */
1404 local_irq_save(flags); 1405 local_irq_save(flags);
1405 rdp = rsp->rda[smp_processor_id()]; 1406 rdp = this_cpu_ptr(rsp->rda);
1406 rcu_process_gp_end(rsp, rdp); 1407 rcu_process_gp_end(rsp, rdp);
1407 check_for_new_grace_period(rsp, rdp); 1408 check_for_new_grace_period(rsp, rdp);
1408 1409
@@ -1701,7 +1702,7 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
1701{ 1702{
1702 unsigned long flags; 1703 unsigned long flags;
1703 int i; 1704 int i;
1704 struct rcu_data *rdp = rsp->rda[cpu]; 1705 struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
1705 struct rcu_node *rnp = rcu_get_root(rsp); 1706 struct rcu_node *rnp = rcu_get_root(rsp);
1706 1707
1707 /* Set up local state, ensuring consistent view of global state. */ 1708 /* Set up local state, ensuring consistent view of global state. */
@@ -1729,7 +1730,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable)
1729{ 1730{
1730 unsigned long flags; 1731 unsigned long flags;
1731 unsigned long mask; 1732 unsigned long mask;
1732 struct rcu_data *rdp = rsp->rda[cpu]; 1733 struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
1733 struct rcu_node *rnp = rcu_get_root(rsp); 1734 struct rcu_node *rnp = rcu_get_root(rsp);
1734 1735
1735 /* Set up local state, ensuring consistent view of global state. */ 1736 /* Set up local state, ensuring consistent view of global state. */
@@ -1865,7 +1866,8 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp)
1865/* 1866/*
1866 * Helper function for rcu_init() that initializes one rcu_state structure. 1867 * Helper function for rcu_init() that initializes one rcu_state structure.
1867 */ 1868 */
1868static void __init rcu_init_one(struct rcu_state *rsp) 1869static void __init rcu_init_one(struct rcu_state *rsp,
1870 struct rcu_data __percpu *rda)
1869{ 1871{
1870 static char *buf[] = { "rcu_node_level_0", 1872 static char *buf[] = { "rcu_node_level_0",
1871 "rcu_node_level_1", 1873 "rcu_node_level_1",
@@ -1918,37 +1920,23 @@ static void __init rcu_init_one(struct rcu_state *rsp)
1918 } 1920 }
1919 } 1921 }
1920 1922
1923 rsp->rda = rda;
1921 rnp = rsp->level[NUM_RCU_LVLS - 1]; 1924 rnp = rsp->level[NUM_RCU_LVLS - 1];
1922 for_each_possible_cpu(i) { 1925 for_each_possible_cpu(i) {
1923 while (i > rnp->grphi) 1926 while (i > rnp->grphi)
1924 rnp++; 1927 rnp++;
1925 rsp->rda[i]->mynode = rnp; 1928 per_cpu_ptr(rsp->rda, i)->mynode = rnp;
1926 rcu_boot_init_percpu_data(i, rsp); 1929 rcu_boot_init_percpu_data(i, rsp);
1927 } 1930 }
1928} 1931}
1929 1932
1930/*
1931 * Helper macro for __rcu_init() and __rcu_init_preempt(). To be used
1932 * nowhere else! Assigns leaf node pointers into each CPU's rcu_data
1933 * structure.
1934 */
1935#define RCU_INIT_FLAVOR(rsp, rcu_data) \
1936do { \
1937 int i; \
1938 \
1939 for_each_possible_cpu(i) { \
1940 (rsp)->rda[i] = &per_cpu(rcu_data, i); \
1941 } \
1942 rcu_init_one(rsp); \
1943} while (0)
1944
1945void __init rcu_init(void) 1933void __init rcu_init(void)
1946{ 1934{
1947 int cpu; 1935 int cpu;
1948 1936
1949 rcu_bootup_announce(); 1937 rcu_bootup_announce();
1950 RCU_INIT_FLAVOR(&rcu_sched_state, rcu_sched_data); 1938 rcu_init_one(&rcu_sched_state, &rcu_sched_data);
1951 RCU_INIT_FLAVOR(&rcu_bh_state, rcu_bh_data); 1939 rcu_init_one(&rcu_bh_state, &rcu_bh_data);
1952 __rcu_init_preempt(); 1940 __rcu_init_preempt();
1953 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); 1941 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
1954 1942
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 14c040b18ed0..5ce197e87792 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -283,7 +283,7 @@ struct rcu_state {
283 struct rcu_node *level[NUM_RCU_LVLS]; /* Hierarchy levels. */ 283 struct rcu_node *level[NUM_RCU_LVLS]; /* Hierarchy levels. */
284 u32 levelcnt[MAX_RCU_LVLS + 1]; /* # nodes in each level. */ 284 u32 levelcnt[MAX_RCU_LVLS + 1]; /* # nodes in each level. */
285 u8 levelspread[NUM_RCU_LVLS]; /* kids/node in each level. */ 285 u8 levelspread[NUM_RCU_LVLS]; /* kids/node in each level. */
286 struct rcu_data *rda[NR_CPUS]; /* array of rdp pointers. */ 286 struct rcu_data __percpu *rda; /* pointer of percu rcu_data. */
287 287
288 /* The following fields are guarded by the root rcu_node's lock. */ 288 /* The following fields are guarded by the root rcu_node's lock. */
289 289
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 0e4f420245d9..9906f85c7780 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -154,7 +154,7 @@ static void rcu_preempt_note_context_switch(int cpu)
154 (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) { 154 (t->rcu_read_unlock_special & RCU_READ_UNLOCK_BLOCKED) == 0) {
155 155
156 /* Possibly blocking in an RCU read-side critical section. */ 156 /* Possibly blocking in an RCU read-side critical section. */
157 rdp = rcu_preempt_state.rda[cpu]; 157 rdp = per_cpu_ptr(rcu_preempt_state.rda, cpu);
158 rnp = rdp->mynode; 158 rnp = rdp->mynode;
159 raw_spin_lock_irqsave(&rnp->lock, flags); 159 raw_spin_lock_irqsave(&rnp->lock, flags);
160 t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED; 160 t->rcu_read_unlock_special |= RCU_READ_UNLOCK_BLOCKED;
@@ -771,7 +771,7 @@ static void rcu_preempt_send_cbs_to_orphanage(void)
771 */ 771 */
772static void __init __rcu_init_preempt(void) 772static void __init __rcu_init_preempt(void)
773{ 773{
774 RCU_INIT_FLAVOR(&rcu_preempt_state, rcu_preempt_data); 774 rcu_init_one(&rcu_preempt_state, &rcu_preempt_data);
775} 775}
776 776
777/* 777/*
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index 36c95b45738e..458e032a3a30 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -262,7 +262,7 @@ static void print_rcu_pendings(struct seq_file *m, struct rcu_state *rsp)
262 struct rcu_data *rdp; 262 struct rcu_data *rdp;
263 263
264 for_each_possible_cpu(cpu) { 264 for_each_possible_cpu(cpu) {
265 rdp = rsp->rda[cpu]; 265 rdp = per_cpu_ptr(rsp->rda, cpu);
266 if (rdp->beenonline) 266 if (rdp->beenonline)
267 print_one_rcu_pending(m, rdp); 267 print_one_rcu_pending(m, rdp);
268 } 268 }