diff options
author | Lai Jiangshan <laijs@cn.fujitsu.com> | 2010-06-28 04:25:04 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2010-08-19 20:18:01 -0400 |
commit | 394f99a9007d4274f7076bb8553ab0ff9707688b (patch) | |
tree | 7d379f91321cec58b87fd5f5089947872689d591 /kernel/rcutree.c | |
parent | e546f485e1d7520ca0200502cdcc11b503f4805c (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.c | 42 |
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 | |||
712 | rcu_start_gp(struct rcu_state *rsp, unsigned long flags) | 712 | rcu_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) | |||
960 | static void rcu_send_cbs_to_orphanage(struct rcu_state *rsp) | 960 | static 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 | */ |
1868 | static void __init rcu_init_one(struct rcu_state *rsp) | 1869 | static 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) \ | ||
1936 | do { \ | ||
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 | |||
1945 | void __init rcu_init(void) | 1933 | void __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 | ||