* [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping
@ 2026-10-19 16:20 Andrea Parri
2026-10-19 16:22 ` Bradley Morgan
2026-10-20 18:49 ` Paul E. McKenney
0 siblings, 2 replies; 11+ messages in thread
From: Andrea Parri @ 2026-10-19 16:20 UTC (permalink / raw)
To: Paul E. McKenney
Cc: Andrea Parri, Frederic Weisbecker, Neeraj Upadhyay,
Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Bradley Morgan, Kunwu Chan, rcu, linux-kernel
hazptrtorture can hang at shutdown when deferral is enabled, as in the
PREEMPT scenario: the writer stays in ->sync() and kthread_stop() on it
never returns, until kvm.sh kills QEMU:
[ 1800.899278] hazptr-torture: Stopping hazptr_torture_do_pending task
[ 1800.899447] hazptr-torture: Stopping hazptr_torture_writer task
[ 1812.713870] hazptr-torture: rtc: 00000000225df70a ver: 12436 HTWS_SYNC tfle: 0 rta: 12437 rtaf: 0 rtf: 12427 onoff: 48783/48783:48786/48786 3,254:3,280 611671:731494 (HZ=1000) acq: 5720353149 rel: 5720210186 acqirq: 571927 relirq: 714778 reldefer: 714139 relundefer 714114
[ 1812.713971] hazptr-torture: hazptr_torture_stats is stopping
Summary: Potential hang (QEMU killed)
!!! PID 1393523 hung at 1980 vs. 1800 seconds
hazptr_torture_cleanup() stops the do_pending kthread before the writer
and the readers. Once torture_must_stop(), do_pending makes one last
pass and leaves its loop, but unless stutter_will_wait(), that pass
releases the deferred hazard pointers of a single CPU.
Readers can also still defer after that pass, from the iteration they
are in when torture_must_stop() becomes true. Stopped readers hold no
hazard pointer, so the writer waits on one of the 25 deferred hazard
pointers above (reldefer - relundefer) that nothing releases.
Keep do_pending running until hazptr_torture_cleanup() stops it, after
the writer and the readers, releasing the deferred hazard pointers of
all CPUs on each pass once torture_must_stop() and once more on exit.
It now also sleeps between those passes, and kthread_stop() wakes it.
This should be safe because readers defer only from their own loop,
which they have left once torture_stop_kthread() returns for them, and
the hazptr_torture_acquire() IPI runs synchronously within that loop.
With this change, a 30-minute PREEMPT run on x86_64 with 8 CPUs ends
with "End of test: SUCCESS" and with as many hazard pointers released
from the pending lists as were deferred (reldefer: 960658 relundefer
960658).
Fixes: f23d7b47ced9 ("hazptrtorture: Add kthread to release deferred hazard pointers")
Assisted-by: LLM
Signed-off-by: Andrea Parri <parri.andrea@gmail.com>
---
kernel/rcu/hazptrtorture.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/kernel/rcu/hazptrtorture.c b/kernel/rcu/hazptrtorture.c
index 7c8b5899fb011..5153720074644 100644
--- a/kernel/rcu/hazptrtorture.c
+++ b/kernel/rcu/hazptrtorture.c
@@ -547,18 +547,25 @@ static int hazptr_torture_do_pending(void *arg)
DEFINE_TORTURE_RANDOM(rand);
VERBOSE_TOROUT_STRING("hazptr_torture_do_pending task started");
- do {
- if (stutter_will_wait()) {
+ /*
+ * Run until hazptr_torture_cleanup() stops this kthread, not just
+ * until torture_must_stop(): the writer can be waiting in ->sync()
+ * for a deferred hazard pointer while it is being stopped.
+ */
+ while (!kthread_should_stop()) {
+ if (torture_must_stop() || stutter_will_wait()) {
for_each_possible_cpu(cpu)
hazptr_torture_do_one_pending(cpu, &rand);
} else {
cpu = cpumask_next_wrap(cpu, cpu_possible_mask);
hazptr_torture_do_one_pending(cpu, &rand);
}
- if (!torture_must_stop())
- torture_hrtimeout_ms(kthread_do_pending_ms, USEC_PER_MSEC, &rand);
+ torture_hrtimeout_ms(kthread_do_pending_ms, USEC_PER_MSEC, &rand);
// Omit stutter_wait() because this function needs to do cleanup.
- } while (!torture_must_stop());
+ }
+ /* The readers have stopped, so nothing new can be deferred. */
+ for_each_possible_cpu(cpu)
+ hazptr_torture_do_one_pending(cpu, &rand);
torture_kthread_stopping("hazptr_torture_do_pending");
return 0;
}
@@ -773,7 +780,6 @@ hazptr_torture_cleanup(void)
return;
}
- torture_stop_kthread(hazptr_torture_do_pending, do_pending_task);
torture_stop_kthread(hazptr_torture_preempt, preempt_task);
torture_stop_kthread(hazptr_torture_writer, writer_task);
@@ -785,6 +791,12 @@ hazptr_torture_cleanup(void)
reader_tasks = NULL;
}
+ /*
+ * Stop do_pending only after the writer and the readers: the writer
+ * may be waiting on hazard pointers that readers deferred.
+ */
+ torture_stop_kthread(hazptr_torture_do_pending, do_pending_task);
+
torture_stop_kthread(hazptr_torture_stats, stats_task);
/* Do torture-type-specific cleanup operations. */
--
2.53.0
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping 2026-10-19 16:20 [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping Andrea Parri @ 2026-10-19 16:22 ` Bradley Morgan 2026-10-19 17:32 ` Andrea Parri 2026-10-20 18:49 ` Paul E. McKenney 1 sibling, 1 reply; 11+ messages in thread From: Bradley Morgan @ 2026-10-19 16:22 UTC (permalink / raw) To: Andrea Parri, Paul E. McKenney Cc: Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang, Kunwu Chan, rcu, linux-kernel On 19 October 2026 17:20:03 BST, Andrea Parri <parri.andrea@gmail.com> wrote: >hazptrtorture can hang at shutdown when deferral is enabled, as in the >PREEMPT scenario: the writer stays in ->sync() and kthread_stop() on it >never returns, until kvm.sh kills QEMU: > > [ 1800.899278] hazptr-torture: Stopping hazptr_torture_do_pending task > [ 1800.899447] hazptr-torture: Stopping hazptr_torture_writer task > [ 1812.713870] hazptr-torture: rtc: 00000000225df70a ver: 12436 HTWS_SYNC tfle: 0 rta: 12437 rtaf: 0 rtf: 12427 onoff: 48783/48783:48786/48786 3,254:3,280 611671:731494 (HZ=1000) acq: 5720353149 rel: 5720210186 acqirq: 571927 relirq: 714778 reldefer: 714139 relundefer 714114 > [ 1812.713971] hazptr-torture: hazptr_torture_stats is stopping > > Summary: Potential hang (QEMU killed) > !!! PID 1393523 hung at 1980 vs. 1800 seconds > >hazptr_torture_cleanup() stops the do_pending kthread before the writer >and the readers. Once torture_must_stop(), do_pending makes one last >pass and leaves its loop, but unless stutter_will_wait(), that pass >releases the deferred hazard pointers of a single CPU. > >Readers can also still defer after that pass, from the iteration they >are in when torture_must_stop() becomes true. Stopped readers hold no >hazard pointer, so the writer waits on one of the 25 deferred hazard >pointers above (reldefer - relundefer) that nothing releases. > >Keep do_pending running until hazptr_torture_cleanup() stops it, after >the writer and the readers, releasing the deferred hazard pointers of >all CPUs on each pass once torture_must_stop() and once more on exit. >It now also sleeps between those passes, and kthread_stop() wakes it. > >This should be safe because readers defer only from their own loop, >which they have left once torture_stop_kthread() returns for them, and >the hazptr_torture_acquire() IPI runs synchronously within that loop. > >With this change, a 30-minute PREEMPT run on x86_64 with 8 CPUs ends >with "End of test: SUCCESS" and with as many hazard pointers released >from the pending lists as were deferred (reldefer: 960658 relundefer >960658). > >Fixes: f23d7b47ced9 ("hazptrtorture: Add kthread to release deferred hazard pointers") >Assisted-by: LLM Why not put this into a series? >Signed-off-by: Andrea Parri <parri.andrea@gmail.com> >--- > kernel/rcu/hazptrtorture.c | 24 ++++++++++++++++++------ > 1 file changed, 18 insertions(+), 6 deletions(-) > >diff --git a/kernel/rcu/hazptrtorture.c b/kernel/rcu/hazptrtorture.c >index 7c8b5899fb011..5153720074644 100644 >--- a/kernel/rcu/hazptrtorture.c >+++ b/kernel/rcu/hazptrtorture.c >@@ -547,18 +547,25 @@ static int hazptr_torture_do_pending(void *arg) > DEFINE_TORTURE_RANDOM(rand); > > VERBOSE_TOROUT_STRING("hazptr_torture_do_pending task started"); >- do { >- if (stutter_will_wait()) { >+ /* >+ * Run until hazptr_torture_cleanup() stops this kthread, not just >+ * until torture_must_stop(): the writer can be waiting in ->sync() >+ * for a deferred hazard pointer while it is being stopped. >+ */ Could this be shorter? >+ while (!kthread_should_stop()) { >+ if (torture_must_stop() || stutter_will_wait()) { > for_each_possible_cpu(cpu) > hazptr_torture_do_one_pending(cpu, &rand); > } else { > cpu = cpumask_next_wrap(cpu, cpu_possible_mask); > hazptr_torture_do_one_pending(cpu, &rand); > } >- if (!torture_must_stop()) >- torture_hrtimeout_ms(kthread_do_pending_ms, USEC_PER_MSEC, &rand); >+ torture_hrtimeout_ms(kthread_do_pending_ms, USEC_PER_MSEC, &rand); > // Omit stutter_wait() because this function needs to do cleanup. >- } while (!torture_must_stop()); >+ } >+ /* The readers have stopped, so nothing new can be deferred. */ >+ for_each_possible_cpu(cpu) Is the comment needed? I don't know if it's nessesary. >+ hazptr_torture_do_one_pending(cpu, &rand); > torture_kthread_stopping("hazptr_torture_do_pending"); > return 0; > } >@@ -773,7 +780,6 @@ hazptr_torture_cleanup(void) > return; > } > >- torture_stop_kthread(hazptr_torture_do_pending, do_pending_task); > torture_stop_kthread(hazptr_torture_preempt, preempt_task); > torture_stop_kthread(hazptr_torture_writer, writer_task); > >@@ -785,6 +791,12 @@ hazptr_torture_cleanup(void) > reader_tasks = NULL; > } > >+ /* >+ * Stop do_pending only after the writer and the readers: the writer >+ * may be waiting on hazard pointers that readers deferred. >+ */ May we shorten this? Feel free to bikeshed that one. >+ torture_stop_kthread(hazptr_torture_do_pending, do_pending_task); >+ > torture_stop_kthread(hazptr_torture_stats, stats_task); > > /* Do torture-type-specific cleanup operations. */ > > --- Thanks! "I'm not a very positive person" - Linus torvalds ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping 2026-10-19 16:22 ` Bradley Morgan @ 2026-10-19 17:32 ` Andrea Parri 2026-10-20 18:36 ` Paul E. McKenney 0 siblings, 1 reply; 11+ messages in thread From: Andrea Parri @ 2026-10-19 17:32 UTC (permalink / raw) To: Bradley Morgan Cc: Andrea Parri, Paul E. McKenney, Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang, Kunwu Chan, rcu, linux-kernel On Mon, Oct 19, 2026 at 05:22:54PM +0100, Bradley Morgan wrote: > On 19 October 2026 17:20:03 BST, Andrea Parri <parri.andrea@gmail.com> > wrote: [...] > >Fixes: f23d7b47ced9 ("hazptrtorture: Add kthread to release deferred hazard pointers") > >Assisted-by: LLM > > Why not put this into a series? The two patches fix unrelated bugs, touch different files, and apply in either order, so I posted them separately. But both are for -rcu/dev, and the test notes in the hazptr patch rely on this one. I'll send the next version as a two-patch series with this patch first, unless Paul prefers separate submissions. [...] > >+ /* > >+ * Run until hazptr_torture_cleanup() stops this kthread, not just > >+ * until torture_must_stop(): the writer can be waiting in ->sync() > >+ * for a deferred hazard pointer while it is being stopped. > >+ */ > > Could this be shorter? Yes. The comment in hazptr_torture_cleanup() already says why, so this one can just point there: /* Keep going until hazptr_torture_cleanup() stops us, see there. */ [...] > >+ /* The readers have stopped, so nothing new can be deferred. */ > >+ for_each_possible_cpu(cpu) > > Is the comment needed? I don't know if it's nessesary. I'd keep it. A reader can defer after the last pass in the loop, and kthread_stop() can then end the loop without another pass, so this pass is needed; the comment says why one pass is enough. > >+ /* > >+ * Stop do_pending only after the writer and the readers: the writer > >+ * may be waiting on hazard pointers that readers deferred. > >+ */ > > May we shorten this? Feel free to bikeshed that one. Sure: /* The writer may wait on hazard pointers that readers deferred. */ Thanks for the review, Andrea ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping 2026-10-19 17:32 ` Andrea Parri @ 2026-10-20 18:36 ` Paul E. McKenney 2026-10-20 18:40 ` Bradley Morgan 0 siblings, 1 reply; 11+ messages in thread From: Paul E. McKenney @ 2026-10-20 18:36 UTC (permalink / raw) To: Andrea Parri Cc: Bradley Morgan, Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang, Kunwu Chan, rcu, linux-kernel On Mon, Oct 19, 2026 at 07:32:28PM +0200, Andrea Parri wrote: > On Mon, Oct 19, 2026 at 05:22:54PM +0100, Bradley Morgan wrote: > > On 19 October 2026 17:20:03 BST, Andrea Parri <parri.andrea@gmail.com> > > wrote: > > [...] > > > >Fixes: f23d7b47ced9 ("hazptrtorture: Add kthread to release deferred hazard pointers") > > >Assisted-by: LLM > > > > Why not put this into a series? > > The two patches fix unrelated bugs, touch different files, and apply in > either order, so I posted them separately. But both are for -rcu/dev, > and the test notes in the hazptr patch rely on this one. I'll send the > next version as a two-patch series with this patch first, unless Paul > prefers separate submissions. I am fine either way. But whatever you do, please do *not* put them into the same patch. ;-) > [...] > > > >+ /* > > >+ * Run until hazptr_torture_cleanup() stops this kthread, not just > > >+ * until torture_must_stop(): the writer can be waiting in ->sync() > > >+ * for a deferred hazard pointer while it is being stopped. > > >+ */ > > > > Could this be shorter? > > Yes. The comment in hazptr_torture_cleanup() already says why, so this > one can just point there: > > /* Keep going until hazptr_torture_cleanup() stops us, see there. */ > > [...] The longer one is better. > > >+ /* The readers have stopped, so nothing new can be deferred. */ > > >+ for_each_possible_cpu(cpu) > > > > Is the comment needed? I don't know if it's nessesary. > > I'd keep it. A reader can defer after the last pass in the loop, and > kthread_stop() can then end the loop without another pass, so this > pass is needed; the comment says why one pass is enough. > > > >+ /* > > >+ * Stop do_pending only after the writer and the readers: the writer > > >+ * may be waiting on hazard pointers that readers deferred. > > >+ */ > > > > May we shorten this? Feel free to bikeshed that one. > > Sure: > > /* The writer may wait on hazard pointers that readers deferred. */ And same here. I am sure that it is possible to create shorter versions that keep all to the information, but I am OK with Andrea's original versions. Bradley, Andrea is not a native English speaker and I believe that you are, so if you want better wording here, please provide it to him. Perhaps someday he will return the favor should you ever be required to write in Italian (or German or Ladin, for that matter). ;-) Thanx, Paul > Thanks for the review, > Andrea ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping 2026-10-20 18:36 ` Paul E. McKenney @ 2026-10-20 18:40 ` Bradley Morgan 0 siblings, 0 replies; 11+ messages in thread From: Bradley Morgan @ 2026-10-20 18:40 UTC (permalink / raw) To: paulmck, Paul E. McKenney, Andrea Parri Cc: Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang, Kunwu Chan, rcu, linux-kernel On 20 October 2026 19:36:47 BST, "Paul E. McKenney" <paulmck@kernel.org> wrote: >On Mon, Oct 19, 2026 at 07:32:28PM +0200, Andrea Parri wrote: >> On Mon, Oct 19, 2026 at 05:22:54PM +0100, Bradley Morgan wrote: >> > On 19 October 2026 17:20:03 BST, Andrea Parri <parri.andrea@gmail.com> >> > wrote: >> >> [...] >> >> > >Fixes: f23d7b47ced9 ("hazptrtorture: Add kthread to release deferred >hazard pointers") >> > >Assisted-by: LLM >> > >> > Why not put this into a series? >> >> The two patches fix unrelated bugs, touch different files, and apply in >> either order, so I posted them separately. But both are for -rcu/dev, >> and the test notes in the hazptr patch rely on this one. I'll send the >> next version as a two-patch series with this patch first, unless Paul >> prefers separate submissions. > >I am fine either way. But whatever you do, please do *not* put them >into the same patch. ;-) > >> [...] >> >> > >+ /* >> > >+ * Run until hazptr_torture_cleanup() stops this kthread, not just >> > >+ * until torture_must_stop(): the writer can be waiting in ->sync() >> > >+ * for a deferred hazard pointer while it is being stopped. >> > >+ */ >> > >> > Could this be shorter? >> >> Yes. The comment in hazptr_torture_cleanup() already says why, so this >> one can just point there: >> >> /* Keep going until hazptr_torture_cleanup() stops us, see there. */ >> >> [...] > >The longer one is better. > >> > >+ /* The readers have stopped, so nothing new can be deferred. */ >> > >+ for_each_possible_cpu(cpu) >> > >> > Is the comment needed? I don't know if it's nessesary. >> >> I'd keep it. A reader can defer after the last pass in the loop, and >> kthread_stop() can then end the loop without another pass, so this >> pass is needed; the comment says why one pass is enough. >> >> > >+ /* >> > >+ * Stop do_pending only after the writer and the readers: the writer >> > >+ * may be waiting on hazard pointers that readers deferred. >> > >+ */ >> > >> > May we shorten this? Feel free to bikeshed that one. >> >> Sure: >> >> /* The writer may wait on hazard pointers that readers deferred. */ > >And same here. > >I am sure that it is possible to create shorter versions that keep all >to the information, but I am OK with Andrea's original versions. > >Bradley, Andrea is not a native English speaker and I believe that >you are, so if you want better wording here, please provide it to him. >Perhaps someday he will return the favor should you ever be required to >write in Italian (or German or Ladin, for that matter). ;-) Well, or he could be my language teacher :) Yeah, if those don't need to be accounted for, I'm fine with this :D Acked-by: Bradley Morgan <brads@mainlining.org> > > Thanx, Paul > >> Thanks for the review, >> Andrea --- Thanks! https://lore.kernel.org/all/EE579805-42F2-4C58-B752-F28779EEB717@grrlz.net/ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping 2026-10-19 16:20 [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping Andrea Parri 2026-10-19 16:22 ` Bradley Morgan @ 2026-10-20 18:49 ` Paul E. McKenney 2026-10-21 9:06 ` Andrea Parri 1 sibling, 1 reply; 11+ messages in thread From: Paul E. McKenney @ 2026-10-20 18:49 UTC (permalink / raw) To: Andrea Parri Cc: Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang, Bradley Morgan, Kunwu Chan, rcu, linux-kernel On Mon, Oct 19, 2026 at 06:20:03PM +0200, Andrea Parri wrote: > hazptrtorture can hang at shutdown when deferral is enabled, as in the > PREEMPT scenario: the writer stays in ->sync() and kthread_stop() on it > never returns, until kvm.sh kills QEMU: > > [ 1800.899278] hazptr-torture: Stopping hazptr_torture_do_pending task > [ 1800.899447] hazptr-torture: Stopping hazptr_torture_writer task > [ 1812.713870] hazptr-torture: rtc: 00000000225df70a ver: 12436 HTWS_SYNC tfle: 0 rta: 12437 rtaf: 0 rtf: 12427 onoff: 48783/48783:48786/48786 3,254:3,280 611671:731494 (HZ=1000) acq: 5720353149 rel: 5720210186 acqirq: 571927 relirq: 714778 reldefer: 714139 relundefer 714114 > [ 1812.713971] hazptr-torture: hazptr_torture_stats is stopping > > Summary: Potential hang (QEMU killed) > !!! PID 1393523 hung at 1980 vs. 1800 seconds > > hazptr_torture_cleanup() stops the do_pending kthread before the writer > and the readers. Once torture_must_stop(), do_pending makes one last > pass and leaves its loop, but unless stutter_will_wait(), that pass > releases the deferred hazard pointers of a single CPU. > > Readers can also still defer after that pass, from the iteration they > are in when torture_must_stop() becomes true. Stopped readers hold no > hazard pointer, so the writer waits on one of the 25 deferred hazard > pointers above (reldefer - relundefer) that nothing releases. > > Keep do_pending running until hazptr_torture_cleanup() stops it, after > the writer and the readers, releasing the deferred hazard pointers of > all CPUs on each pass once torture_must_stop() and once more on exit. > It now also sleeps between those passes, and kthread_stop() wakes it. > > This should be safe because readers defer only from their own loop, > which they have left once torture_stop_kthread() returns for them, and > the hazptr_torture_acquire() IPI runs synchronously within that loop. > > With this change, a 30-minute PREEMPT run on x86_64 with 8 CPUs ends > with "End of test: SUCCESS" and with as many hazard pointers released > from the pending lists as were deferred (reldefer: 960658 relundefer > 960658). > > Fixes: f23d7b47ced9 ("hazptrtorture: Add kthread to release deferred hazard pointers") > Assisted-by: LLM > Signed-off-by: Andrea Parri <parri.andrea@gmail.com> Thank you for digging into this! Some questions and comments interspersed below. Thanx, Paul > --- > kernel/rcu/hazptrtorture.c | 24 ++++++++++++++++++------ > 1 file changed, 18 insertions(+), 6 deletions(-) > > diff --git a/kernel/rcu/hazptrtorture.c b/kernel/rcu/hazptrtorture.c > index 7c8b5899fb011..5153720074644 100644 > --- a/kernel/rcu/hazptrtorture.c > +++ b/kernel/rcu/hazptrtorture.c > @@ -547,18 +547,25 @@ static int hazptr_torture_do_pending(void *arg) > DEFINE_TORTURE_RANDOM(rand); > > VERBOSE_TOROUT_STRING("hazptr_torture_do_pending task started"); > - do { > - if (stutter_will_wait()) { > + /* > + * Run until hazptr_torture_cleanup() stops this kthread, not just > + * until torture_must_stop(): the writer can be waiting in ->sync() > + * for a deferred hazard pointer while it is being stopped. > + */ > + while (!kthread_should_stop()) { > + if (torture_must_stop() || stutter_will_wait()) { > for_each_possible_cpu(cpu) > hazptr_torture_do_one_pending(cpu, &rand); > } else { > cpu = cpumask_next_wrap(cpu, cpu_possible_mask); > hazptr_torture_do_one_pending(cpu, &rand); > } > - if (!torture_must_stop()) > - torture_hrtimeout_ms(kthread_do_pending_ms, USEC_PER_MSEC, &rand); > + torture_hrtimeout_ms(kthread_do_pending_ms, USEC_PER_MSEC, &rand); Is the theory here that a kthread_stop() will wake up this sleep anyway? And if so, would that work if the kthread_stop() already happened? (I do recall adding the torture_must_stop() checks due to delays at kthread_stop() time, but perhaps things have changed since then.) > // Omit stutter_wait() because this function needs to do cleanup. > - } while (!torture_must_stop()); > + } > + /* The readers have stopped, so nothing new can be deferred. */ > + for_each_possible_cpu(cpu) > + hazptr_torture_do_one_pending(cpu, &rand); Very good! But given these two lines, do we need the changes to the loop? > torture_kthread_stopping("hazptr_torture_do_pending"); > return 0; > } > @@ -773,7 +780,6 @@ hazptr_torture_cleanup(void) > return; > } > > - torture_stop_kthread(hazptr_torture_do_pending, do_pending_task); > torture_stop_kthread(hazptr_torture_preempt, preempt_task); > torture_stop_kthread(hazptr_torture_writer, writer_task); > > @@ -785,6 +791,12 @@ hazptr_torture_cleanup(void) > reader_tasks = NULL; > } > > + /* > + * Stop do_pending only after the writer and the readers: the writer > + * may be waiting on hazard pointers that readers deferred. > + */ > + torture_stop_kthread(hazptr_torture_do_pending, do_pending_task); > + And this change looks good. > torture_stop_kthread(hazptr_torture_stats, stats_task); > > /* Do torture-type-specific cleanup operations. */ > > -- > 2.53.0 > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping 2026-10-20 18:49 ` Paul E. McKenney @ 2026-10-21 9:06 ` Andrea Parri 2026-10-21 16:50 ` Paul E. McKenney 0 siblings, 1 reply; 11+ messages in thread From: Andrea Parri @ 2026-10-21 9:06 UTC (permalink / raw) To: Paul E. McKenney Cc: Andrea Parri, Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang, Bradley Morgan, Kunwu Chan, rcu, linux-kernel On Tue, Oct 20, 2026 at 11:49:08AM -0700, Paul E. McKenney wrote: > On Mon, Oct 19, 2026 at 06:20:03PM +0200, Andrea Parri wrote: [...] > > - if (!torture_must_stop()) > > - torture_hrtimeout_ms(kthread_do_pending_ms, USEC_PER_MSEC, &rand); > > + torture_hrtimeout_ms(kthread_do_pending_ms, USEC_PER_MSEC, &rand); > > Is the theory here that a kthread_stop() will wake up this sleep anyway? > And if so, would that work if the kthread_stop() already happened? > > (I do recall adding the torture_must_stop() checks due to delays at > kthread_stop() time, but perhaps things have changed since then.) Yes, that is the theory. torture_hrtimeout_ns() does set_current_state(TASK_IDLE) and then schedule_hrtimeout(), and kthread_stop() sets KTHREAD_SHOULD_STOP before wake_up_process(), which wakes TASK_IDLE sleepers. So: - If kthread_stop() comes while do_pending sleeps, or between its set_current_state() and schedule(), the sleep ends right away. - If kthread_stop() has already happened, i.e., it comes between the kthread_should_stop() check and set_current_state(), the wakeup is lost, but KTHREAD_SHOULD_STOP stays set: do_pending sleeps for one full period and the loop then exits. That is kthread_do_pending_ms plus up to 1ms of fuzz, so 3-4ms by default. For comparison, without this patch do_pending leaves its loop at torture_must_stop() and waits in torture_kthread_stopping(), which sleeps in TASK_UNINTERRUPTIBLE for HZ/20 at a time, so it has the same lost-wakeup window with a 50ms bound instead. The next version says this in the changelog, which in the RFC only says "kthread_stop() wakes it". > > // Omit stutter_wait() because this function needs to do cleanup. > > - } while (!torture_must_stop()); > > + } > > + /* The readers have stopped, so nothing new can be deferred. */ > > + for_each_possible_cpu(cpu) > > + hazptr_torture_do_one_pending(cpu, &rand); > > Very good! > > But given these two lines, do we need the changes to the loop? I believe so, at least for the loop condition. The readers are stopped after the writer, so during the writer's kthread_stop(), the writer can be in ->sync() on a hazard pointer that a still-running reader deferred, possibly from the iteration it was in when torture_must_stop() became true. If the loop still ended at torture_must_stop(), do_pending would make that final pass right away and then wait in torture_kthread_stopping(), so a hazard pointer deferred after that pass would leave the writer in ->sync(), as in the hang above. The other two loop changes follow from that one: the unconditional sleep keeps do_pending from spinning while the writer and the readers are being stopped, and the all-CPU pass once torture_must_stop() only bounds the writer's wait to one period, instead of up to nr_cpu_ids periods. I'm happy to drop the latter if you prefer the simpler loop. > > + /* > > + * Stop do_pending only after the writer and the readers: the writer > > + * may be waiting on hazard pointers that readers deferred. > > + */ > > + torture_stop_kthread(hazptr_torture_do_pending, do_pending_task); > > + > > And this change looks good. Thanks. In the next version, I'll keep the original (longer) comments as you suggested in the other subthread, and post this patch in one series with two patches that make hazptrtorture catch the slot-owner race, as you asked in the slot-owner thread. Thanks, Andrea ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping 2026-10-21 9:06 ` Andrea Parri @ 2026-10-21 16:50 ` Paul E. McKenney 2026-10-22 12:55 ` Andrea Parri 0 siblings, 1 reply; 11+ messages in thread From: Paul E. McKenney @ 2026-10-21 16:50 UTC (permalink / raw) To: Andrea Parri Cc: Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang, Bradley Morgan, Kunwu Chan, rcu, linux-kernel On Wed, Oct 21, 2026 at 11:06:51AM +0200, Andrea Parri wrote: > On Tue, Oct 20, 2026 at 11:49:08AM -0700, Paul E. McKenney wrote: > > On Mon, Oct 19, 2026 at 06:20:03PM +0200, Andrea Parri wrote: > > [...] > > > > - if (!torture_must_stop()) > > > - torture_hrtimeout_ms(kthread_do_pending_ms, USEC_PER_MSEC, &rand); > > > + torture_hrtimeout_ms(kthread_do_pending_ms, USEC_PER_MSEC, &rand); > > > > Is the theory here that a kthread_stop() will wake up this sleep anyway? > > And if so, would that work if the kthread_stop() already happened? > > > > (I do recall adding the torture_must_stop() checks due to delays at > > kthread_stop() time, but perhaps things have changed since then.) > > Yes, that is the theory. torture_hrtimeout_ns() does > set_current_state(TASK_IDLE) and then schedule_hrtimeout(), and > kthread_stop() sets KTHREAD_SHOULD_STOP before wake_up_process(), > which wakes TASK_IDLE sleepers. So: > > - If kthread_stop() comes while do_pending sleeps, or between its > set_current_state() and schedule(), the sleep ends right away. > > - If kthread_stop() has already happened, i.e., it comes between > the kthread_should_stop() check and set_current_state(), the > wakeup is lost, but KTHREAD_SHOULD_STOP stays set: do_pending > sleeps for one full period and the loop then exits. That is > kthread_do_pending_ms plus up to 1ms of fuzz, so 3-4ms by > default. Very good. Except that if someone sets a very long sleep time, that could result in excessive delay for kthread exit, right? Or am I missing a turn in there somewhere? > For comparison, without this patch do_pending leaves its loop at > torture_must_stop() and waits in torture_kthread_stopping(), which > sleeps in TASK_UNINTERRUPTIBLE for HZ/20 at a time, so it has the > same lost-wakeup window with a 50ms bound instead. But that is a fixed wait, without the possibility of a user extending it, correct? > The next version says this in the changelog, which in the RFC only > says "kthread_stop() wakes it". Adding the details would be good, thank you! > > > // Omit stutter_wait() because this function needs to do cleanup. > > > - } while (!torture_must_stop()); > > > + } > > > + /* The readers have stopped, so nothing new can be deferred. */ > > > + for_each_possible_cpu(cpu) > > > + hazptr_torture_do_one_pending(cpu, &rand); > > > > Very good! > > > > But given these two lines, do we need the changes to the loop? > > I believe so, at least for the loop condition. The readers are > stopped after the writer, so during the writer's kthread_stop(), the > writer can be in ->sync() on a hazard pointer that a still-running > reader deferred, possibly from the iteration it was in when > torture_must_stop() became true. If the loop still ended at > torture_must_stop(), do_pending would make that final pass right away > and then wait in torture_kthread_stopping(), so a hazard pointer > deferred after that pass would leave the writer in ->sync(), as in the > hang above. > > The other two loop changes follow from that one: the unconditional > sleep keeps do_pending from spinning while the writer and the readers > are being stopped, and the all-CPU pass once torture_must_stop() only > bounds the writer's wait to one period, instead of up to nr_cpu_ids > periods. I'm happy to drop the latter if you prefer the simpler loop. Should we stop the writer before stopping the readers? Or would that open up some other issue? > > > + /* > > > + * Stop do_pending only after the writer and the readers: the writer > > > + * may be waiting on hazard pointers that readers deferred. > > > + */ > > > + torture_stop_kthread(hazptr_torture_do_pending, do_pending_task); > > > + > > > > And this change looks good. > > Thanks. In the next version, I'll keep the original (longer) comments > as you suggested in the other subthread, and post this patch in one > series with two patches that make hazptrtorture catch the slot-owner > race, as you asked in the slot-owner thread. The comments sound good, and the single-patch/series decision is yours, thank you! Thanx, Paul ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping 2026-10-21 16:50 ` Paul E. McKenney @ 2026-10-22 12:55 ` Andrea Parri 2026-10-22 22:55 ` Paul E. McKenney 0 siblings, 1 reply; 11+ messages in thread From: Andrea Parri @ 2026-10-22 12:55 UTC (permalink / raw) To: Paul E. McKenney Cc: Andrea Parri, Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang, Bradley Morgan, Kunwu Chan, rcu, linux-kernel On Wed, Oct 21, 2026 at 09:50:11AM -0700, Paul E. McKenney wrote: > On Wed, Oct 21, 2026 at 11:06:51AM +0200, Andrea Parri wrote: [...] > > - If kthread_stop() has already happened, i.e., it comes between > > the kthread_should_stop() check and set_current_state(), the > > wakeup is lost, but KTHREAD_SHOULD_STOP stays set: do_pending > > sleeps for one full period and the loop then exits. That is > > kthread_do_pending_ms plus up to 1ms of fuzz, so 3-4ms by > > default. > > Very good. Except that if someone sets a very long sleep time, that > could result in excessive delay for kthread exit, right? Or am I missing > a turn in there somewhere? You are not missing anything: in that case, do_pending sleeps for one full kthread_do_pending_ms period, however long it is. > > For comparison, without this patch do_pending leaves its loop at > > torture_must_stop() and waits in torture_kthread_stopping(), which > > sleeps in TASK_UNINTERRUPTIBLE for HZ/20 at a time, so it has the > > same lost-wakeup window with a 50ms bound instead. > > But that is a fixed wait, without the possibility of a user extending > it, correct? Correct, torture_kthread_stopping() always sleeps for HZ/20 at a time. [...] > Should we stop the writer before stopping the readers? Or would that > open up some other issue? hazptr_torture_cleanup() already stops the writer before the readers, and that order is what lets the writer wait on hazard pointers that readers defer while it is being stopped. If you mean the other way around, stopping the readers first, I believe that works: - Stop the readers, then do_pending, then the writer. - Keep the do_pending loop as it is in -rcu/dev, including the torture_must_stop() check before the sleep, and move this patch's final all-CPU pass after torture_kthread_stopping(), so that it runs once the readers have stopped. The writer can then still wait in ->sync() on a deferred hazard pointer, but only until that final pass, and nothing waits on the writer. The readers do not need the writer to stop: they leave their loop at torture_must_stop(), after at most one stutter_wait(). With that order, the long sleep above can still happen, but only if do_pending passed its torture_must_stop() check before the test began stopping, and had not yet gone to sleep when kthread_stop() came, after all the readers had stopped. Would you prefer that? If so, I will rework this patch along those lines for v1, and rerun the tests. Thanks, Andrea ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping 2026-10-22 12:55 ` Andrea Parri @ 2026-10-22 22:55 ` Paul E. McKenney 2026-10-23 12:07 ` Andrea Parri 0 siblings, 1 reply; 11+ messages in thread From: Paul E. McKenney @ 2026-10-22 22:55 UTC (permalink / raw) To: Andrea Parri Cc: Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang, Bradley Morgan, Kunwu Chan, rcu, linux-kernel On Thu, Oct 22, 2026 at 02:55:55PM +0200, Andrea Parri wrote: > On Wed, Oct 21, 2026 at 09:50:11AM -0700, Paul E. McKenney wrote: > > On Wed, Oct 21, 2026 at 11:06:51AM +0200, Andrea Parri wrote: > > [...] > > > > - If kthread_stop() has already happened, i.e., it comes between > > > the kthread_should_stop() check and set_current_state(), the > > > wakeup is lost, but KTHREAD_SHOULD_STOP stays set: do_pending > > > sleeps for one full period and the loop then exits. That is > > > kthread_do_pending_ms plus up to 1ms of fuzz, so 3-4ms by > > > default. > > > > Very good. Except that if someone sets a very long sleep time, that > > could result in excessive delay for kthread exit, right? Or am I missing > > a turn in there somewhere? > > You are not missing anything: in that case, do_pending sleeps for one > full kthread_do_pending_ms period, however long it is. Then let's please keep the torture_must_stop() check. Yes, there is still a window between the return from torture_must_stop() and the call to torture_hrtimeout_ms(), but maybe that is something to take care of later on. > > > For comparison, without this patch do_pending leaves its loop at > > > torture_must_stop() and waits in torture_kthread_stopping(), which > > > sleeps in TASK_UNINTERRUPTIBLE for HZ/20 at a time, so it has the > > > same lost-wakeup window with a 50ms bound instead. > > > > But that is a fixed wait, without the possibility of a user extending > > it, correct? > > Correct, torture_kthread_stopping() always sleeps for HZ/20 at a time. > > [...] > > > Should we stop the writer before stopping the readers? Or would that > > open up some other issue? > > hazptr_torture_cleanup() already stops the writer before the readers, > and that order is what lets the writer wait on hazard pointers that > readers defer while it is being stopped. OK, that is the other issue that would be opened up. ;-) > If you mean the other way > around, stopping the readers first, I believe that works: > > - Stop the readers, then do_pending, then the writer. > > - Keep the do_pending loop as it is in -rcu/dev, including the > torture_must_stop() check before the sleep, and move this patch's > final all-CPU pass after torture_kthread_stopping(), so that it > runs once the readers have stopped. > > The writer can then still wait in ->sync() on a deferred hazard > pointer, but only until that final pass, and nothing waits on the > writer. The readers do not need the writer to stop: they leave their > loop at torture_must_stop(), after at most one stutter_wait(). > > With that order, the long sleep above can still happen, but only if > do_pending passed its torture_must_stop() check before the test began > stopping, and had not yet gone to sleep when kthread_stop() came, > after all the readers had stopped. > > Would you prefer that? If so, I will rework this patch along those > lines for v1, and rerun the tests. Taking a more careful look, and thank you for bearing with me... Yes, agreed, almost: o Keep the hazptr_torture_do_pending() do-while loop as it is, but add the for_each_possible_cpu() after loop exit. o Stop the readers first, stop hazptr_torture_do_pending() to flush out anything left from the readers, then stop the writer. However, for the "almost", note that the "while (!torture_must_stop())" needs to become "while (!kthread_should_stop())". If this change is not made, then hazptr_torture_do_pending() will exit its do-while loop as soon as hazptr_torture_cleanup() calls torture_cleanup_begin(). This will of course defeat the reordering. Does that work, or am I still missing something? Alternatively, you could keep the current do-while condition and place a loop around your post-do-while code like this: while (!kthread_should_stop()) for_each_possible_cpu(cpu) hazptr_torture_do_one_pending(cpu, &rand); But changing the do-while condition looks cleaner to me. This code will also need adjustment when something like a call_hazptr() is added, presumably along with a hazptr_barrier(), but we can worry about that when it happens. Thanx, Paul ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping 2026-10-22 22:55 ` Paul E. McKenney @ 2026-10-23 12:07 ` Andrea Parri 0 siblings, 0 replies; 11+ messages in thread From: Andrea Parri @ 2026-10-23 12:07 UTC (permalink / raw) To: Paul E. McKenney Cc: Andrea Parri, Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang, Bradley Morgan, Kunwu Chan, rcu, linux-kernel On Thu, Oct 22, 2026 at 03:55:44PM -0700, Paul E. McKenney wrote: > On Thu, Oct 22, 2026 at 02:55:55PM +0200, Andrea Parri wrote: [...] > Then let's please keep the torture_must_stop() check. Yes, there is > still a window between the return from torture_must_stop() and the > call to torture_hrtimeout_ms(), but maybe that is something to take > care of later on. Will do. [...] > Yes, agreed, almost: > > o Keep the hazptr_torture_do_pending() do-while loop as it > is, but add the for_each_possible_cpu() after loop exit. > > o Stop the readers first, stop hazptr_torture_do_pending() > to flush out anything left from the readers, then stop > the writer. > > However, for the "almost", note that the "while (!torture_must_stop())" > needs to become "while (!kthread_should_stop())". If this change is > not made, then hazptr_torture_do_pending() will exit its do-while loop > as soon as hazptr_torture_cleanup() calls torture_cleanup_begin(). > This will of course defeat the reordering. > > Does that work, or am I still missing something? do_pending does leave the loop then, but the final pass goes after torture_kthread_stopping(), not right after the loop: } while (!torture_must_stop()); torture_kthread_stopping("hazptr_torture_do_pending"); /* The readers have stopped, so nothing new can be deferred. */ for_each_possible_cpu(cpu) hazptr_torture_do_one_pending(cpu, &rand); return 0; torture_kthread_stopping() sleeps HZ/20 at a time until kthread_should_stop(), so the pass runs only once hazptr_torture_cleanup() stops do_pending, after the readers. With "while (!kthread_should_stop())" and the torture_must_stop() check before the sleep, do_pending would instead spin without sleeping from torture_cleanup_begin() until it is stopped. > Alternatively, you could keep the current do-while condition and place > a loop around your post-do-while code like this: > > while (!kthread_should_stop()) > for_each_possible_cpu(cpu) > hazptr_torture_do_one_pending(cpu, &rand); > > But changing the do-while condition looks cleaner to me. That loop would spin too. > This code will also need adjustment when something like a call_hazptr() > is added, presumably along with a hazptr_barrier(), but we can worry > about that when it happens. Agreed. I have been running this version locally, with the rest of v1: a 30-minute PREEMPT run, and a 30-minute NOPREEMPT run with torture_type=hazptr, pass. With kthread_do_pending_ms=10000, the shutdown still takes less than 150ms. If it works for you, v1 will have it. Thanks, Andrea ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-10-23 12:08 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-10-19 16:20 [PATCH RFC -rcu/dev] hazptrtorture: Release all deferred hazard pointers before stopping Andrea Parri 2026-10-19 16:22 ` Bradley Morgan 2026-10-19 17:32 ` Andrea Parri 2026-10-20 18:36 ` Paul E. McKenney 2026-10-20 18:40 ` Bradley Morgan 2026-10-20 18:49 ` Paul E. McKenney 2026-10-21 9:06 ` Andrea Parri 2026-10-21 16:50 ` Paul E. McKenney 2026-10-22 12:55 ` Andrea Parri 2026-10-22 22:55 ` Paul E. McKenney 2026-10-23 12:07 ` Andrea Parri
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®