From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: paulmck@kernel.org
Cc: Boqun Feng <boqun@kernel.org>, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/2] hazptr: Introduce CONFIG_HAZPTR_DEBUG misuse detection
Date: Thu, 9 Jul 2026 19:22:18 -0400 [thread overview]
Message-ID: <2d801522-6a77-47ad-8daf-d23cc85cbb7a@efficios.com> (raw)
In-Reply-To: <2c7f97fa-8429-4fbb-bb33-53e015629f01@paulmck-laptop>
On 2026-07-09 19:05, Paul E. McKenney wrote:
> On Thu, Jul 09, 2026 at 05:47:00PM -0400, Mathieu Desnoyers wrote:
[...]
>>> + */
>>> static inline
>>> void hazptr_detach_from_task(struct hazptr_ctx *ctx)
>>> {
>>> @@ -160,17 +178,29 @@ void hazptr_note_context_switch(void)
>>> }
>>> }
>>> -/*
>>> - * hazptr_acquire: Load pointer at address and protect with hazard pointer.
>>> +/**
>>> + * hazptr_acquire - Load pointer at address and protect with hazard pointer.
>>> + *
>>> + * @ctx: The hazard-pointer context to be passed to hazptr_release().
>>> + * @addr_p: Pointer to the pointer that is to be hazard-pointer protected.
>>> *
>>> * Load @addr_p, and protect the loaded pointer with hazard pointer.
>>> - * When using hazptr_acquire from interrupt handlers, the acquired slots
>>> - * need to be released before returning from the interrupt handler.
>>
>> I see that you removed wording of a major constraint here which allowed
>> use of hazptr locally in a interrupt handler: the need to pair the
>> acquire/release within the handler.
>
> I did indeed remove that wording. You could do something like this:
>
> Task Context IRQ Handler Interrupts Task
> ------------ ---------------------------
> preempt_disable();
> ihp = __this_cpu_read(irq_hc); ihp = __this_cpu_read(irq_hc);
> p = hazptr_acquire(ihp, &gp);
> lp = xchg(p, NULL);
> if (lp) {
> do_something(lp);
> hazptr_release(ihp, lp);
> }
> preempt_enable();
>
> If I understand the rules correctly (ha!), this is perfectly legal
> and does not require a hazptr_detach_from_task().
>
I am concerned about it, because I knowingly just used preempt disable
to protect hazptr_acquire from the scheduler, but not from interrupt
handlers, because it's faster than irqoff.
I am concerned that this use of hazptr_acquire could confuse the
thread-level hazptr_acquire, let's dig:
void *hazptr_acquire(struct hazptr_ctx *ctx, void * const *addr_p)
{
struct hazptr_percpu_slots *percpu_slots;
struct hazptr_slot_item *slot_item;
struct hazptr_slot *slot;
void *addr;
guard(preempt)();
percpu_slots = this_cpu_ptr(&hazptr_percpu_slots);
slot_item = &percpu_slots->items[0];
slot = &slot_item->slot;
[...]
from here --------------------
if (unlikely(slot->addr))
return __hazptr_acquire(ctx, addr_p);
WRITE_ONCE(slot->addr, HAZPTR_WILDCARD); /* Store B */
/* Memory ordering: Store B before Load A. */
smp_mb();
/*
* Load @addr_p after storing wildcard to the hazard pointer slot.
*/
addr = READ_ONCE(*addr_p); /* Load A */
/*
* We don't care about ordering of Store C. It will simply
* replace the wildcard by a more specific address. If addr is
* NULL, we simply store NULL into the slot.
*/
WRITE_ONCE(slot->addr, addr); /* Store C */
to here ----------------------------
I designed hazptr_acquire so a _nested_ interrupt which _brings back_
the slot addr to its original state will work. Now let's see if
that's still OK if the interrupt handler leaves the slot->addr
populated with an address.
And no. If the interrupt happens right before "Store B", its
reserved slot address is overwritten by the thread. That's incorrect.
So as it is today, the irq handler needs to vacate the slot before it
returns, either through a hazptr release or a detach.
That being said, this is the code as it is today. If someone finds a
clever way to support this use-case and keep it fast and not too complex,
I'm all ears! :)
One possible way to make it work would be to install the HAZPTR_WILDCARD
with a local-cmpxchg expecting a NULL slot->addr. This would close this
race window. But it comes at a non-null overhead price. Another alternative
on x86 would be to use a lock prefixed cmpxchg, which has an implied smp_mb
on success, which may be in the same ballpark as the sequence of WRITE_ONCE+
explicit smp_mb().
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com
next prev parent reply other threads:[~2026-07-09 23:22 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-09 18:29 [PATCH 1/2] hazptrtorture: Fix hazptr ownership issue Mathieu Desnoyers
2026-07-09 18:29 ` [PATCH 2/2] hazptr: Introduce CONFIG_HAZPTR_DEBUG misuse detection Mathieu Desnoyers
2026-07-09 18:47 ` Paul E. McKenney
2026-07-09 18:56 ` Mathieu Desnoyers
2026-07-09 20:44 ` Paul E. McKenney
2026-07-09 21:47 ` Mathieu Desnoyers
2026-07-09 23:05 ` Paul E. McKenney
2026-07-09 23:22 ` Mathieu Desnoyers [this message]
2026-07-09 23:48 ` Paul E. McKenney
2026-07-10 0:10 ` Mathieu Desnoyers
2026-07-10 19:07 ` Paul E. McKenney
2026-07-11 13:48 ` Mathieu Desnoyers
2026-07-11 23:55 ` Paul E. McKenney
2026-07-14 19:16 ` Mathieu Desnoyers
2026-07-14 20:54 ` Paul E. McKenney
2026-07-14 21:06 ` Mathieu Desnoyers
2026-07-14 21:31 ` Paul E. McKenney
2026-07-09 23:57 ` Boqun Feng
2026-07-10 0:03 ` Mathieu Desnoyers
2026-07-09 20:45 ` Paul E. McKenney
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=2d801522-6a77-47ad-8daf-d23cc85cbb7a@efficios.com \
--to=mathieu.desnoyers@efficios.com \
--cc=boqun@kernel.org \
--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
Powered by JetHome