aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree.c
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/rcutree.c
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/rcutree.c')
-rw-r--r--kernel/rcutree.c42
1 files changed, 15 insertions, 27 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