[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250730022347.71722-4-yuzhuo@google.com>
Date: Tue, 29 Jul 2025 19:23:46 -0700
From: Yuzhuo Jing <yuzhuo@...gle.com>
To: Ian Rogers <irogers@...gle.com>, Yuzhuo Jing <yzj@...ch.edu>, Jonathan Corbet <corbet@....net>,
Davidlohr Bueso <dave@...olabs.net>, "Paul E . McKenney" <paulmck@...nel.org>,
Josh Triplett <josh@...htriplett.org>, Frederic Weisbecker <frederic@...nel.org>,
Neeraj Upadhyay <neeraj.upadhyay@...nel.org>, Joel Fernandes <joelagnelf@...dia.com>,
Boqun Feng <boqun.feng@...il.com>, Uladzislau Rezki <urezki@...il.com>,
Steven Rostedt <rostedt@...dmis.org>, Mathieu Desnoyers <mathieu.desnoyers@...icios.com>,
Lai Jiangshan <jiangshanlai@...il.com>, Zqiang <qiang.zhang@...ux.dev>,
Andrew Morton <akpm@...ux-foundation.org>, Ingo Molnar <mingo@...nel.org>,
Borislav Petkov <bp@...en8.de>, Arnd Bergmann <arnd@...db.de>, Frank van der Linden <fvdl@...gle.com>,
linux-doc@...r.kernel.org, linux-kernel@...r.kernel.org, rcu@...r.kernel.org
Cc: Yuzhuo Jing <yuzhuo@...gle.com>
Subject: [PATCH v1 3/4] rcuscale: Add file based start/finish control
In addition to the existing timing-based (holdoff, writer_holdoff)
start control, add file-based controls to debugfs.
This patch adds an option "block_start", which holds all worker threads
until the "rcuscale/should_start" debugfs file is written with a
non-zero integer. A new "test_complete" file is added to the debugfs
folder, with file content "0" indicating experiment has not finished and
"1" indicating finished. This is useful for start/finish control by
external test tools.
Signed-off-by: Yuzhuo Jing <yuzhuo@...gle.com>
---
.../admin-guide/kernel-parameters.txt | 5 ++
kernel/rcu/rcuscale.c | 79 +++++++++++++++++++
2 files changed, 84 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 7b62a84a19d4..5e233e511f81 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -5487,6 +5487,11 @@
Default is 0.
+ rcuscale.block_start= [KNL]
+ Block the experiment start until "1" is written to the
+ rcuscale/should_start file in debugfs. This is useful
+ for start/finish control by external tools.
+
rcuscale.gp_async= [KNL]
Measure performance of asynchronous
grace-period primitives such as call_rcu().
diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c
index 7c88d461ed2c..43bcaeac457f 100644
--- a/kernel/rcu/rcuscale.c
+++ b/kernel/rcu/rcuscale.c
@@ -87,6 +87,7 @@ MODULE_AUTHOR("Paul E. McKenney <paulmck@...ux.ibm.com>");
# define RCUSCALE_SHUTDOWN 1
#endif
+torture_param(bool, block_start, false, "Block all threads after creation and wait for should_start");
torture_param(bool, gp_async, false, "Use asynchronous GP wait primitives");
torture_param(int, gp_async_max, 1000, "Max # outstanding waits per writer");
torture_param(bool, gp_exp, false, "Use expedited GP wait primitives");
@@ -146,6 +147,12 @@ static struct dentry *debugfs_writer_durations;
static struct dentry *debugfs_reader_tasks;
static struct dentry *debugfs_writer_tasks;
static struct dentry *debugfs_kfree_tasks;
+static struct dentry *debugfs_should_start;
+static struct dentry *debugfs_test_complete;
+
+static DECLARE_COMPLETION(start_barrier);
+static bool should_start;
+static bool test_complete;
#define MAX_MEAS 10000
#define MIN_MEAS 100
@@ -457,6 +464,23 @@ static void rcu_scale_wait_shutdown(void)
schedule_timeout_uninterruptible(1);
}
+/*
+ * Wait start_barrier if block_start is enabled. Exit early if shutdown
+ * is requested.
+ *
+ * Return: true if caller should exit; false if caller should continue.
+ */
+static bool wait_start_barrier(void)
+{
+ if (!block_start)
+ return false;
+ while (wait_for_completion_interruptible(&start_barrier)) {
+ if (torture_must_stop())
+ return true;
+ }
+ return false;
+}
+
/*
* RCU scalability reader kthread. Repeatedly does empty RCU read-side
* critical section, minimizing update-side interference. However, the
@@ -475,6 +499,11 @@ rcu_scale_reader(void *arg)
set_user_nice(current, MAX_NICE);
atomic_inc(&n_rcu_scale_reader_started);
+ if (wait_start_barrier()) {
+ torture_kthread_stopping("rcu_scale_reader");
+ return 0;
+ }
+
do {
local_irq_save(flags);
idx = cur_ops->readlock();
@@ -560,6 +589,11 @@ rcu_scale_writer(void *arg)
current->flags |= PF_NO_SETAFFINITY;
sched_set_fifo_low(current);
+ if (wait_start_barrier()) {
+ torture_kthread_stopping("rcu_scale_writer");
+ return 0;
+ }
+
if (holdoff)
schedule_timeout_idle(holdoff * HZ);
@@ -755,6 +789,11 @@ kfree_scale_thread(void *arg)
set_user_nice(current, MAX_NICE);
kfree_rcu_test_both = (kfree_rcu_test_single == kfree_rcu_test_double);
+ if (wait_start_barrier()) {
+ torture_kthread_stopping("kfree_scale_thread");
+ return 0;
+ }
+
start_time = ktime_get_mono_fast_ns();
if (atomic_inc_return(&n_kfree_scale_thread_started) >= kfree_nrealthreads) {
@@ -1118,6 +1157,32 @@ static const struct file_operations kfrees_fops = {
.release = seq_release,
};
+/*
+ * For the "should_start" writable file, reuse debugfs integer parsing, but
+ * override write function to also send complete_all if should_start is
+ * changed to 1.
+ *
+ * Any non-zero value written to this file is converted to 1.
+ */
+static int should_start_set(void *data, u64 val)
+{
+ *(bool *)data = !!val;
+
+ if (block_start && !!val)
+ complete_all(&start_barrier);
+
+ return 0;
+}
+
+static int bool_get(void *data, u64 *val)
+{
+ *val = *(bool *)data;
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(should_start_fops, bool_get, should_start_set, "%llu");
+DEFINE_DEBUGFS_ATTRIBUTE(test_complete_fops, bool_get, NULL, "%llu");
+
/*
* Create an rcuscale directory exposing run states and results.
*/
@@ -1153,6 +1218,15 @@ static int register_debugfs(void)
debugfs_dir, NULL, &kfrees_fops))
goto fail;
+ if (try_create_file(debugfs_should_start, "should_start", 0644,
+ debugfs_dir, &should_start, &should_start_fops))
+ goto fail;
+
+ /* Future: add notification method for readers waiting on file change. */
+ if (try_create_file(debugfs_test_complete, "test_complete", 0444,
+ debugfs_dir, &test_complete, &test_complete_fops))
+ goto fail;
+
return 0;
fail:
pr_err("rcu-scale: Failed to create debugfs file.");
@@ -1176,6 +1250,8 @@ do { \
try_remove(debugfs_reader_tasks);
try_remove(debugfs_writer_tasks);
try_remove(debugfs_kfree_tasks);
+ try_remove(debugfs_should_start);
+ try_remove(debugfs_test_complete);
/* Remove directory after files. */
try_remove(debugfs_dir);
@@ -1372,6 +1448,9 @@ rcu_scale_init(void)
atomic_set(&n_rcu_scale_writer_finished, 0);
rcu_scale_print_module_parms(cur_ops, "Start of test");
+ if (!block_start)
+ should_start = true;
+
/* Start up the kthreads. */
if (shutdown) {
--
2.50.1.552.g942d659e1b-goog
Powered by blists - more mailing lists