aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcu/tree.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2018-04-26 14:52:09 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2018-07-12 17:27:46 -0400
commitde30ad512a668b56e7ad7a5a7c379d7c5d138a94 (patch)
treeb738dc4cef2074311f09b55da11f1a74a72acf72 /kernel/rcu/tree.c
parent609af1cdf040f8d3f3986755586f7833eaa96d2c (diff)
rcu: Introduce grace-period sequence numbers
This commit adds grace-period sequence numbers (->gp_seq) to the rcu_state, rcu_node, and rcu_data structures, and updates them. It also checks for consistency between rsp->gpnum and rsp->gp_seq. These ->gp_seq counters will eventually replace the existing ->gpnum and ->completed counters, allowing a single memory access to determine whether or not a grace period is in progress and if so, which one. This in turn will enable changes that will reduce ->lock contention on the leaf rcu_node structures. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcu/tree.c')
-rw-r--r--kernel/rcu/tree.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index a9a4a260ea7d..467cd8e5c6ff 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -97,6 +97,7 @@ struct rcu_state sname##_state = { \
97 .gp_state = RCU_GP_IDLE, \ 97 .gp_state = RCU_GP_IDLE, \
98 .gpnum = 0UL - 300UL, \ 98 .gpnum = 0UL - 300UL, \
99 .completed = 0UL - 300UL, \ 99 .completed = 0UL - 300UL, \
100 .gp_seq = (0UL - 300UL) << RCU_SEQ_CTR_SHIFT, \
100 .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \ 101 .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
101 .name = RCU_STATE_NAME(sname), \ 102 .name = RCU_STATE_NAME(sname), \
102 .abbr = sabbr, \ 103 .abbr = sabbr, \
@@ -1849,6 +1850,8 @@ static bool __note_gp_changes(struct rcu_state *rsp, struct rcu_node *rnp,
1849 WRITE_ONCE(rdp->gpwrap, false); 1850 WRITE_ONCE(rdp->gpwrap, false);
1850 rcu_gpnum_ovf(rnp, rdp); 1851 rcu_gpnum_ovf(rnp, rdp);
1851 } 1852 }
1853 if (rdp->gp_seq != rnp->gp_seq)
1854 rdp->gp_seq = rnp->gp_seq;
1852 return ret; 1855 return ret;
1853} 1856}
1854 1857
@@ -1910,7 +1913,10 @@ static bool rcu_gp_init(struct rcu_state *rsp)
1910 /* Advance to a new grace period and initialize state. */ 1913 /* Advance to a new grace period and initialize state. */
1911 record_gp_stall_check_time(rsp); 1914 record_gp_stall_check_time(rsp);
1912 /* Record GP times before starting GP, hence smp_store_release(). */ 1915 /* Record GP times before starting GP, hence smp_store_release(). */
1916 WARN_ON_ONCE(rsp->gpnum << RCU_SEQ_CTR_SHIFT != rsp->gp_seq);
1913 smp_store_release(&rsp->gpnum, rsp->gpnum + 1); 1917 smp_store_release(&rsp->gpnum, rsp->gpnum + 1);
1918 smp_mb(); /* Pairs with barriers in stall-warning code. */
1919 rcu_seq_start(&rsp->gp_seq);
1914 trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start")); 1920 trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start"));
1915 raw_spin_unlock_irq_rcu_node(rnp); 1921 raw_spin_unlock_irq_rcu_node(rnp);
1916 1922
@@ -1984,6 +1990,7 @@ static bool rcu_gp_init(struct rcu_state *rsp)
1984 WRITE_ONCE(rnp->gpnum, rsp->gpnum); 1990 WRITE_ONCE(rnp->gpnum, rsp->gpnum);
1985 if (WARN_ON_ONCE(rnp->completed != rsp->completed)) 1991 if (WARN_ON_ONCE(rnp->completed != rsp->completed))
1986 WRITE_ONCE(rnp->completed, rsp->completed); 1992 WRITE_ONCE(rnp->completed, rsp->completed);
1993 WRITE_ONCE(rnp->gp_seq, rsp->gp_seq);
1987 if (rnp == rdp->mynode) 1994 if (rnp == rdp->mynode)
1988 (void)__note_gp_changes(rsp, rnp, rdp); 1995 (void)__note_gp_changes(rsp, rnp, rdp);
1989 rcu_preempt_boost_start_gp(rnp); 1996 rcu_preempt_boost_start_gp(rnp);
@@ -2050,6 +2057,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
2050{ 2057{
2051 unsigned long gp_duration; 2058 unsigned long gp_duration;
2052 bool needgp = false; 2059 bool needgp = false;
2060 unsigned long new_gp_seq;
2053 struct rcu_data *rdp; 2061 struct rcu_data *rdp;
2054 struct rcu_node *rnp = rcu_get_root(rsp); 2062 struct rcu_node *rnp = rcu_get_root(rsp);
2055 struct swait_queue_head *sq; 2063 struct swait_queue_head *sq;
@@ -2079,12 +2087,15 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
2079 * all of the rcu_node structures before the beginning of the next 2087 * all of the rcu_node structures before the beginning of the next
2080 * grace period is recorded in any of the rcu_node structures. 2088 * grace period is recorded in any of the rcu_node structures.
2081 */ 2089 */
2090 new_gp_seq = rsp->gp_seq;
2091 rcu_seq_end(&new_gp_seq);
2082 rcu_for_each_node_breadth_first(rsp, rnp) { 2092 rcu_for_each_node_breadth_first(rsp, rnp) {
2083 raw_spin_lock_irq_rcu_node(rnp); 2093 raw_spin_lock_irq_rcu_node(rnp);
2084 if (WARN_ON_ONCE(rcu_preempt_blocked_readers_cgp(rnp))) 2094 if (WARN_ON_ONCE(rcu_preempt_blocked_readers_cgp(rnp)))
2085 dump_blkd_tasks(rnp, 10); 2095 dump_blkd_tasks(rnp, 10);
2086 WARN_ON_ONCE(rnp->qsmask); 2096 WARN_ON_ONCE(rnp->qsmask);
2087 WRITE_ONCE(rnp->completed, rsp->gpnum); 2097 WRITE_ONCE(rnp->completed, rsp->gpnum);
2098 WRITE_ONCE(rnp->gp_seq, new_gp_seq);
2088 rdp = this_cpu_ptr(rsp->rda); 2099 rdp = this_cpu_ptr(rsp->rda);
2089 if (rnp == rdp->mynode) 2100 if (rnp == rdp->mynode)
2090 needgp = __note_gp_changes(rsp, rnp, rdp) || needgp; 2101 needgp = __note_gp_changes(rsp, rnp, rdp) || needgp;
@@ -2098,10 +2109,11 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
2098 rcu_gp_slow(rsp, gp_cleanup_delay); 2109 rcu_gp_slow(rsp, gp_cleanup_delay);
2099 } 2110 }
2100 rnp = rcu_get_root(rsp); 2111 rnp = rcu_get_root(rsp);
2101 raw_spin_lock_irq_rcu_node(rnp); /* Order GP before ->completed update. */ 2112 raw_spin_lock_irq_rcu_node(rnp); /* GP before rsp->gp_seq update. */
2102 2113
2103 /* Declare grace period done. */ 2114 /* Declare grace period done. */
2104 WRITE_ONCE(rsp->completed, rsp->gpnum); 2115 WRITE_ONCE(rsp->completed, rsp->gpnum);
2116 rcu_seq_end(&rsp->gp_seq);
2105 trace_rcu_grace_period(rsp->name, rsp->completed, TPS("end")); 2117 trace_rcu_grace_period(rsp->name, rsp->completed, TPS("end"));
2106 rsp->gp_state = RCU_GP_IDLE; 2118 rsp->gp_state = RCU_GP_IDLE;
2107 /* Check for GP requests since above loop. */ 2119 /* Check for GP requests since above loop. */
@@ -3612,6 +3624,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp)
3612 rdp->beenonline = true; /* We have now been online. */ 3624 rdp->beenonline = true; /* We have now been online. */
3613 rdp->gpnum = rnp->completed; /* Make CPU later note any new GP. */ 3625 rdp->gpnum = rnp->completed; /* Make CPU later note any new GP. */
3614 rdp->completed = rnp->completed; 3626 rdp->completed = rnp->completed;
3627 rdp->gp_seq = rnp->gp_seq;
3615 rdp->cpu_no_qs.b.norm = true; 3628 rdp->cpu_no_qs.b.norm = true;
3616 rdp->rcu_qs_ctr_snap = per_cpu(rcu_dynticks.rcu_qs_ctr, cpu); 3629 rdp->rcu_qs_ctr_snap = per_cpu(rcu_dynticks.rcu_qs_ctr, cpu);
3617 rdp->core_needs_qs = false; 3630 rdp->core_needs_qs = false;
@@ -3991,6 +4004,7 @@ static void __init rcu_init_one(struct rcu_state *rsp)
3991 &rcu_fqs_class[i], fqs[i]); 4004 &rcu_fqs_class[i], fqs[i]);
3992 rnp->gpnum = rsp->gpnum; 4005 rnp->gpnum = rsp->gpnum;
3993 rnp->completed = rsp->completed; 4006 rnp->completed = rsp->completed;
4007 rnp->gp_seq = rsp->gp_seq;
3994 rnp->completedqs = rsp->completed; 4008 rnp->completedqs = rsp->completed;
3995 rnp->qsmask = 0; 4009 rnp->qsmask = 0;
3996 rnp->qsmaskinit = 0; 4010 rnp->qsmaskinit = 0;