Re: [PATCH v10 01/21] rcuref: Provide rcuref_is_dead().
From: Joel Fernandes
Date: Thu Mar 13 2025 - 00:23:26 EST
On Wed, Mar 12, 2025 at 04:16:14PM +0100, Sebastian Andrzej Siewior wrote:
> rcuref_read() returns the number of references that are currently held.
> If 0 is returned then it is not safe to assume that the object ca be
> scheduled for deconstruction because it is marked DEAD. This happens if
> the return value of rcuref_put() is ignored and assumptions are made.
>
> If 0 is returned then the counter transitioned from 0 to RCUREF_NOREF.
> If rcuref_put() did not return to the caller then the counter did not
> yet transition from RCUREF_NOREF to RCUREF_DEAD. This means that there
> is still a chance that the counter counter will transition from
> RCUREF_NOREF to 0 meaning it is still valid and must not be
> deconstructed. In this brief window rcuref_read() will return 0.
>
> Provide rcuref_is_dead() to determine if the counter is marked as
> RCUREF_DEAD.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
> ---
> include/linux/rcuref.h | 22 +++++++++++++++++++++-
> 1 file changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/rcuref.h b/include/linux/rcuref.h
> index 6322d8c1c6b42..2fb2af6d98249 100644
> --- a/include/linux/rcuref.h
> +++ b/include/linux/rcuref.h
> @@ -30,7 +30,11 @@ static inline void rcuref_init(rcuref_t *ref, unsigned int cnt)
> * rcuref_read - Read the number of held reference counts of a rcuref
> * @ref: Pointer to the reference count
> *
> - * Return: The number of held references (0 ... N)
> + * Return: The number of held references (0 ... N). The value 0 does not
> + * indicate that it is safe to schedule the object, protected by this reference
> + * counter, for deconstruction.
> + * If you want to know if the reference counter has been marked DEAD (as
> + * signaled by rcuref_put()) please use rcuread_is_dead().
> */
> static inline unsigned int rcuref_read(rcuref_t *ref)
> {
> @@ -40,6 +44,22 @@ static inline unsigned int rcuref_read(rcuref_t *ref)
> return c >= RCUREF_RELEASED ? 0 : c + 1;
> }
>
> +/**
> + * rcuref_is_dead - Check if the rcuref has been already marked dead
> + * @ref: Pointer to the reference count
> + *
> + * Return: True if the object has been marked DEAD. This signals that a previous
> + * invocation of rcuref_put() returned true on this reference counter meaning
> + * the protected object can safely be scheduled for deconstruction.
> + * Otherwise, returns false.
> + */
> +static inline bool rcuref_is_dead(rcuref_t *ref)
> +{
> + unsigned int c = atomic_read(&ref->refcnt);
> +
> + return (c >= RCUREF_RELEASED) && (c < RCUREF_NOREF);
> +}
> +
> extern __must_check bool rcuref_get_slowpath(rcuref_t *ref);
>
This makes sense to me, another way I guess to determine if it is dead is
actually to do a get() and see if it fails? Though that would be more
expensive and silly.
FWIW for this patch,
Reviewed-by: Joel Fernandes <joelagnelf@xxxxxxxxxx>
thanks,
- Joel