Re: [RFC PATCH v5 1/2] hazptr: Implement Hazard Pointers
From: Mathieu Desnoyers
Date: Tue Jul 07 2026 - 15:40:58 EST
On 2026-06-27 13:36, Paul E. McKenney wrote:
On Sat, Jun 27, 2026 at 11:21:28AM -0400, Mathieu Desnoyers wrote:
On 2026-06-27 08:56, Mathieu Desnoyers wrote:
On 2026-06-27 00:14, Paul E. McKenney wrote:
On Fri, Jun 26, 2026 at 11:56:13PM -0400, Mathieu Desnoyers wrote:[...]
On 2026-06-26 19:06, Paul E. McKenney wrote:
That OOPS is very instructive. I think I found the root cause.Initial runs suggest that hazard pointers cannot be acquired by one
task and released by another. Is that expected behavior, or is my test
improperly passing the hazard pointers? If the latter, we should of
course document the proper hazard-pointer-passing mechanism.
This is unexpected. I've looked at your test code quickly and could
not figure out what's wrong though. But it's late. How do you observe
that it fails ?
Not an emergency, so your schedule is my schedule. Especially given
that I am mostly taking this coming week off. And that it took me such
a long time to get this torture test done. ;-)
I run either scenario (PREEMPT or NOPREEMPT) with:
--bootarg "hazptrtorture.onoff_interval=3333
hazptrtorture.stat_interval=15"
I get the following on the console, and things go downhill from there.
I get the same thing when I turn off CPU hotplug, for whatever that is
worth.
I need to add an API to hazptr so users wishing to explicitly transfer
ownership of the hazptr ctx to another thread can do so.
Currently the scheduler hook is responsible for moving the hazptr
ctx from per-cpu to the backup slots, which makes it entirely movable
afterwards.
But this assumes the ctx is thread-local. Once you explicitly move
ownership of that ctx to another thread, you race with the scheduler of
the original thread.
Let me see what I can do to fix that.
Thanks a lot for the test-case !
Glad it helped? ;-)
Can you try with the attached POC diff ?
This increases the kernel's life significantly, but still fails as
shown below. This is the NOPREEMPT scenario as follows:
tools/testing/selftests/rcutorture/bin/kvm.sh --torture hazptr --allcpus --duration 5m --bootargs "hazptrtorture.onoff_interval=3333 hazptrtorture.nwriters=1 hazptrtorture.stat_interval=15" --trust-make
The PREEMPT failure gets similar failures, and the above command runs
both of these scenarios.
Re-reviewing kernel/rcu/hazptrtorture.c, I found the following issues:
In my patch provided earlier in this thread, I was missing a "detach
from task" call within hazptr_torture_reader_tail, because it calls
an IPI to do the hazptr release on a remote CPU. e.g.:
diff --git a/kernel/rcu/hazptrtorture.c b/kernel/rcu/hazptrtorture.c
index 311b387d6ae7..ae9ccd89ff87 100644
--- a/kernel/rcu/hazptrtorture.c
+++ b/kernel/rcu/hazptrtorture.c
@@ -411,6 +411,7 @@ hazptr_torture_reader_tail(struct hazptr_pending *hppp, struct torture_random_st
preempt_enable();
if (irq_release && !(torture_random(trsp) % irq_release)) {
guard(preempt)();
+ hazptr_detach_from_task(&hppp->hpp_hc);
cpu = cpumask_next_wrap(smp_processor_id(), cpu_online_mask);
smp_call_function_single(cpu, hazptr_torture_release, hppp, 1);
} else {
@@ -428,6 +429,7 @@ static void hazptr_torture_defer(struct hazptr_pending *hppp, struct torture_ran
struct llist_head *llhp;
guard(preempt)();
+ hazptr_detach_from_task(&hppp->hpp_hc);
cpu = cpumask_next_wrap(cpu, cpu_online_mask);
llhp = per_cpu_ptr(&hazptr_pending, cpu);
llist_add(&hppp->hpp_node, llhp);
Moreover, I think the whole ownership model of hazptr_torture_do_pending
is broken wrt hazptr requirements. We would need to "detach from task" each
of the hazptr before handing them off to such a remote drain, otherwise
the remote drain iteration on all cpus would basically have to hold the
runqueue locks for each of those cpus to prevent the scheduler from
racing against either hazptr_detach_from_task or hazptr release.
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com