All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: Boqun Feng <boqun.feng@gmail.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	paulmck <paulmck@kernel.org>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	Maged Michael <maged.michael@gmail.com>
Subject: Re: [RFC] Synchronized Shared Pointers for the Linux kernel
Date: Fri, 11 Oct 2024 11:15:23 -0400	[thread overview]
Message-ID: <613e258c-e74b-46dc-970b-de9c78672c76@efficios.com> (raw)
In-Reply-To: <ZwhfPS4yyFx_Qrbu@boqun-archlinux>

On 2024-10-11 01:11, Boqun Feng wrote:
> On Thu, Oct 10, 2024 at 03:16:25PM -0400, Mathieu Desnoyers wrote:
>> Hi,
>>
>> I've created a new API (sharedptr.h) for the use-case of
>> providing existence object guarantees (e.g. for Rust)
>> when dereferencing pointers which can be concurrently updated.
>> I call this "Synchronized Shared Pointers".
>>
>> This should be an elegant solution to Greg's refcount
>> existence use-case as well.
>>
>> The current implementation can be found here:
>>
>> https://github.com/compudj/linux-dev/commit/64c3756b88776fe534629c70f6a1d27fad27e9ba
>>
>> Patch added inline below for feedback.
>>
>> Thanks!
>>
>> Mathieu
>>

[...]

>> + */
>> +static inline
>> +struct sharedptr sharedptr_copy_from_sync(const struct syncsharedptr *ssp)
>> +{
>> +	struct sharedptr_node *spn, *hp;
>> +	struct hazptr_slot *slot;
>> +	struct sharedptr sp;
>> +
>> +	preempt_disable();
> 
> Disabling preemption acts as an RCU read-side critical section, so I
> guess the immediate question is why (or when) not use RCU ;-)

That's a very relevant question indeed! Why use hazard pointers rather
than RCU in this particular use-case ?

You are right that I could add a rcu_read_lock()/rcu_read_unlock()
around sharedptr_copy_from_sync(), and pair this with a call_rcu()
in node_release, which would effectively replace hazard pointers
by RCU.

Please keep in mind that the current implementation of this API
is minimalist. I mean to extend this, and this is where the benefits
of hazard pointers over RCU should become clearer:

1) With hazard pointers, AFAIU we can modify the sharedptr_delete
    and syncsharedptr_delete to issue hazptr_scan() _before_
    decrementing to 0, e.g.

       unsigned int old, new;

       WRITE_ONCE(sp->spn, NULL);
       old = spn->refcount;
       do {
               new = old - 1;
               if (!new)
                       hazptr_scan(&hazptr_domain_sharedptr, spn, NULL);
       } while (!atomic_try_cmpxchg(&spn->refcount->refs, &old, new);
       if (!new)
               sharedptr_node_release(spn);

    And therefore modify sharedptr_copy_from_sync to use a refcount_inc
    rather than a refcount_inc_not_zero, because the reference count
    can never be 0 while a hazard pointer to the object exists.

    This modification would make hazard pointers act as if they
    *are* holding a reference count on the object.

This improvement brings us to a more important benefit:

2) If we increase the number of available hazptr slots per cpu
    (e.g. to 8 or more), then we can start using hazard pointers as
    reference counter replacement (fast-path).

    This will allow introducing a new type of sharedptr object, which
    could be named "thread sharedptr", meant to hold a reference for a
    relatively short period of time, on a single thread, where the thread
    is still allowed to be preempted or block while holding the thread
    sharedptr.

    The per-cpu hazard pointer slots would point to per-thread sharedptr
    structures, which would hold the protected hazard pointer slot.

    When the application means to keep the reference for longer,
    to store it into a data structure or pass it around to another
    thread, then it should copy the thread-sharedptr to a normal
    sharedptr, which will make sure a reference is taken on the
    object.

    The thread sharedptr is tied to the thread using it. Because the
    hazard pointer context would be in a well-defined per-thread area
    (rather than just on the stack), we can do the following when
    scanning for hazard pointers: force the thread sharedptr to promote
    to a reference counter increment on the object, thus allowing the
    hazard pointer scan to progress. This allows freeing up the per-cpu
    slot immediately.

    If all per-cpu hazard pointer slots are used, the thread sharedptr
    would automatically fall-back to reference counter.

    We could even add a per-cpu timer which would track how old are each
    per-CPU hazard pointer slots, and promote them to a reference counter
    increment based on their age if needed.

This would effectively allow implementing a "per-thread shared pointer"
fast-path, which would scale better than just reference counters on large
multi-core systems.

Thanks,

Mathieu

-- 
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com


      reply	other threads:[~2024-10-11 15:17 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-10 19:16 [RFC] Synchronized Shared Pointers for the Linux kernel Mathieu Desnoyers
2024-10-10 23:11 ` Boqun Feng
2024-10-11 15:15   ` Mathieu Desnoyers [this message]

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=613e258c-e74b-46dc-970b-de9c78672c76@efficios.com \
    --to=mathieu.desnoyers@efficios.com \
    --cc=boqun.feng@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maged.michael@gmail.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.