From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: paulmck@kernel.org
Cc: Boqun Feng <boqun.feng@gmail.com>, linux-kernel@vger.kernel.org
Subject: Re: [RFC PATCH v5 1/2] hazptr: Implement Hazard Pointers
Date: Sat, 27 Jun 2026 11:21:28 -0400 [thread overview]
Message-ID: <7741b89e-e36e-4288-ad85-83a413529526@efficios.com> (raw)
In-Reply-To: <6623407f-8219-4a9a-8c6d-f17e0e73f828@efficios.com>
[-- Attachment #1: Type: text/plain, Size: 1919 bytes --]
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:
> [...]
>>>> 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.
> That OOPS is very instructive. I think I found the root cause.
>
> 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 !
Can you try with the attached POC diff ?
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com
[-- Attachment #2: hazptr-fix-handoff.patch --]
[-- Type: text/x-patch, Size: 2776 bytes --]
diff --git a/include/linux/hazptr.h b/include/linux/hazptr.h
index 461f481a480b..d96414575739 100644
--- a/include/linux/hazptr.h
+++ b/include/linux/hazptr.h
@@ -98,6 +98,41 @@ bool hazptr_slot_is_backup(struct hazptr_ctx *ctx, struct hazptr_slot *slot)
return slot == &ctx->backup_slot.slot;
}
+/* Internal helper. */
+static inline
+void hazptr_promote_to_backup_slot(struct hazptr_ctx *ctx, struct hazptr_slot *slot)
+{
+ struct hazptr_slot *backup_slot;
+
+ backup_slot = hazptr_chain_backup_slot(ctx);
+ /*
+ * Move hazard pointer from the per-CPU slot to the
+ * backup slot. This requires hazard pointer
+ * synchronize to iterate on per-CPU slots with
+ * load-acquire before iterating on the overflow list.
+ */
+ WRITE_ONCE(backup_slot->addr, slot->addr);
+ /*
+ * store-release orders store to backup slot addr before
+ * store to per-CPU slot addr.
+ */
+ smp_store_release(&slot->addr, NULL);
+ /* Use the backup slot for context. */
+ ctx->slot = backup_slot;
+}
+
+static inline
+void hazptr_detach_from_task(struct hazptr_ctx *ctx)
+{
+ struct hazptr_slot *slot;
+
+ guard(preempt)();
+ slot = ctx->slot;
+ if (unlikely(hazptr_slot_is_backup(ctx, slot)))
+ return;
+ hazptr_promote_to_backup_slot(ctx, slot);
+}
+
static inline
void hazptr_note_context_switch(void)
{
@@ -106,27 +141,11 @@ void hazptr_note_context_switch(void)
for (idx = 0; idx < NR_HAZPTR_PERCPU_SLOTS; idx++) {
struct hazptr_slot_item *item = &percpu_slots->items[idx];
- struct hazptr_slot *slot = &item->slot, *backup_slot;
- struct hazptr_ctx *ctx;
+ struct hazptr_slot *slot = &item->slot;
if (!slot->addr)
continue;
- ctx = item->ctx.ctx;
- backup_slot = hazptr_chain_backup_slot(ctx);
- /*
- * Move hazard pointer from the per-CPU slot to the
- * backup slot. This requires hazard pointer
- * synchronize to iterate on per-CPU slots with
- * load-acquire before iterating on the overflow list.
- */
- WRITE_ONCE(backup_slot->addr, slot->addr);
- /*
- * store-release orders store to backup slot addr before
- * store to per-CPU slot addr.
- */
- smp_store_release(&slot->addr, NULL);
- /* Use the backup slot for context. */
- ctx->slot = backup_slot;
+ hazptr_promote_to_backup_slot(item->ctx.ctx, slot);
}
}
diff --git a/kernel/rcu/hazptrtorture.c b/kernel/rcu/hazptrtorture.c
index 311b387d6ae7..93b383887fc5 100644
--- a/kernel/rcu/hazptrtorture.c
+++ b/kernel/rcu/hazptrtorture.c
@@ -427,6 +427,7 @@ static void hazptr_torture_defer(struct hazptr_pending *hppp, struct torture_ran
int cpu = torture_random(trsp) % nr_cpu_ids;
struct llist_head *llhp;
+ hazptr_detach_from_task(&hppp->hpp_hc);
guard(preempt)();
cpu = cpumask_next_wrap(cpu, cpu_online_mask);
llhp = per_cpu_ptr(&hazptr_pending, cpu);
next prev parent reply other threads:[~2026-06-27 15:21 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-23 20:44 [RFC PATCH v5 0/2] " Mathieu Desnoyers
2026-02-23 20:44 ` [RFC PATCH v5 1/2] hazptr: Implement " Mathieu Desnoyers
2026-06-26 23:06 ` Paul E. McKenney
2026-06-27 3:56 ` Mathieu Desnoyers
2026-06-27 4:14 ` Paul E. McKenney
2026-06-27 12:56 ` Mathieu Desnoyers
2026-06-27 15:21 ` Mathieu Desnoyers [this message]
2026-06-27 17:36 ` Paul E. McKenney
2026-07-07 19:40 ` Mathieu Desnoyers
2026-07-07 21:42 ` Paul E. McKenney
2026-07-08 22:55 ` Paul E. McKenney
2026-07-09 2:45 ` Mathieu Desnoyers
2026-07-09 3:28 ` Paul E. McKenney
2026-07-09 16:02 ` Paul E. McKenney
2026-07-09 16:03 ` Mathieu Desnoyers
2026-07-09 16:06 ` Paul E. McKenney
2026-02-23 20:44 ` [RFC PATCH v5 2/2] hazptr: Add refscale test Mathieu Desnoyers
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=7741b89e-e36e-4288-ad85-83a413529526@efficios.com \
--to=mathieu.desnoyers@efficios.com \
--cc=boqun.feng@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=paulmck@kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox