From: Frederic Weisbecker <frederic@kernel.org>
To: "Paul E . McKenney" <paulmck@kernel.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
Frederic Weisbecker <frederic@kernel.org>,
Uladzislau Rezki <urezki@gmail.com>,
Boqun Feng <boqun.feng@gmail.com>,
Lai Jiangshan <jiangshanlai@gmail.com>,
Neeraj Upadhyay <neeraju@codeaurora.org>,
Josh Triplett <josh@joshtriplett.org>,
Joel Fernandes <joel@joelfernandes.org>
Subject: [PATCH 4/5] srcu: Queue a callback in case of early started poll
Date: Fri, 9 Apr 2021 00:39:01 +0200 [thread overview]
Message-ID: <20210408223902.6405-5-frederic@kernel.org> (raw)
In-Reply-To: <20210408223902.6405-1-frederic@kernel.org>
If SRCU polling is used before SRCU initialization, it won't benefit
from the callback requeue performed after rcu_init_geometry() in order
to fix the node hierarchy reshuffle. This is because polling start grace
periods that don't rely on callbacks. Therefore the grace period started
may be lost upon srcu_init().
To fix this, queue an empty callback in case of early use of
start_poll_synchronize_srcu() so that it can later get requeued with
the preserved order against other early calls to either call_srcu()
or start_poll_synchronize_srcu().
Since it can be called early any number of time, have at least two
struct rcu_head per ssp dedicated to this early enqueue. The two first
calls to start_poll_synchronize_srcu() will each start one new grace
period, if no call_srcu() happen before or in-between. Any subsequent
early call to start_poll_synchronize_srcu() will wait for the second
grace period so there is no need to queue empty callbacks beyond the
second call.
Suggested-by: Paul E . McKenney <paulmck@kernel.org>
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Lai Jiangshan <jiangshanlai@gmail.com>
Cc: Neeraj Upadhyay <neeraju@codeaurora.org>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Joel Fernandes <joel@joelfernandes.org>
Cc: Uladzislau Rezki <urezki@gmail.com>
---
include/linux/srcutree.h | 1 +
kernel/rcu/srcutree.c | 37 ++++++++++++++++++++++++++++++++++++-
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/include/linux/srcutree.h b/include/linux/srcutree.h
index a2422c442470..9d4fbfc2c109 100644
--- a/include/linux/srcutree.h
+++ b/include/linux/srcutree.h
@@ -84,6 +84,7 @@ struct srcu_struct {
struct delayed_work work;
struct lockdep_map dep_map;
struct list_head early_init;
+ struct rcu_head early_poll[2];
};
/* Values for state variable (bottom bits of ->srcu_gp_seq). */
diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
index 7ca1bd0067c4..2fa35e5bfbc9 100644
--- a/kernel/rcu/srcutree.c
+++ b/kernel/rcu/srcutree.c
@@ -190,6 +190,8 @@ static void reset_srcu_struct(struct srcu_struct *ssp)
{
int cpu;
struct lockdep_map dep_map;
+ struct rcu_head early_poll[2];
+ int i;
struct rcu_cblist pendcbs;
struct rcu_head *rhp;
struct srcu_data __percpu *sda;
@@ -218,10 +220,16 @@ static void reset_srcu_struct(struct srcu_struct *ssp)
sda = ssp->sda;
/* Save the lockdep map, it may not suffer double-initialization */
dep_map = ssp->dep_map;
+ /* Save the early_poll callback links. They may be queued to pendcbs */
+ for (i = 0; i < ARRAY_SIZE(ssp->early_poll); i++)
+ early_poll[i] = ssp->early_poll[i];
memset(ssp, 0, sizeof(*ssp));
ssp->sda = sda;
ssp->dep_map = dep_map;
+ for (i = 0; i < ARRAY_SIZE(ssp->early_poll); i++)
+ ssp->early_poll[i] = early_poll[i];
+
spin_lock_init(&ACCESS_PRIVATE(ssp, lock));
init_srcu_struct_fields(ssp, true);
@@ -1079,6 +1087,10 @@ unsigned long get_state_synchronize_srcu(struct srcu_struct *ssp)
}
EXPORT_SYMBOL_GPL(get_state_synchronize_srcu);
+static void early_poll_func(struct rcu_head *rhp)
+{
+}
+
/**
* start_poll_synchronize_srcu - Provide cookie and start grace period
* @ssp: srcu_struct to provide cookie for.
@@ -1091,7 +1103,30 @@ EXPORT_SYMBOL_GPL(get_state_synchronize_srcu);
*/
unsigned long start_poll_synchronize_srcu(struct srcu_struct *ssp)
{
- return srcu_gp_start_if_needed(ssp, NULL, true);
+ struct rcu_head *rhp = NULL;
+
+ /*
+ * After rcu_init_geometry(), we need to reset the ssp and restart
+ * the early started grace periods. Callbacks can be requeued but
+ * callback-less grace periods are harder to track, especially if
+ * we want to preserve the order among all the early calls to
+ * call_srcu() and start_poll_synchronize_srcu(). So queue empty
+ * callbacks to solve this. We may initialize at most two grace periods
+ * that early, no need to queue more than two callbacks per ssp, any
+ * further early call to start_poll_synchronize_srcu() will wait for
+ * the second grace period.
+ */
+ if (!srcu_init_done) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(ssp->early_poll); i++) {
+ if (!ssp->early_poll[i].func) {
+ rhp = &ssp->early_poll[i];
+ rhp->func = early_poll_func;
+ break;
+ }
+ }
+ }
+ return srcu_gp_start_if_needed(ssp, rhp, true);
}
EXPORT_SYMBOL_GPL(start_poll_synchronize_srcu);
--
2.25.1
next prev parent reply other threads:[~2021-04-08 22:39 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-08 22:38 [PATCH 0/5] srcu: Fix boot stall v2 Frederic Weisbecker
2021-04-08 22:38 ` [PATCH 1/5] srcu: Unconditionally embed struct lockdep_map Frederic Weisbecker
2021-04-08 22:38 ` [PATCH 2/5] srcu: Initialize SRCU after timers Frederic Weisbecker
2021-04-09 20:05 ` Paul E. McKenney
2021-04-08 22:39 ` [PATCH 3/5] srcu: Fix broken node geometry after early ssp init Frederic Weisbecker
2021-04-08 22:39 ` Frederic Weisbecker [this message]
2021-04-08 22:39 ` [PATCH 5/5] srcu: Early test SRCU polling start Frederic Weisbecker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210408223902.6405-5-frederic@kernel.org \
--to=frederic@kernel.org \
--cc=boqun.feng@gmail.com \
--cc=jiangshanlai@gmail.com \
--cc=joel@joelfernandes.org \
--cc=josh@joshtriplett.org \
--cc=linux-kernel@vger.kernel.org \
--cc=neeraju@codeaurora.org \
--cc=paulmck@kernel.org \
--cc=urezki@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.