All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: Eric Dumazet <edumazet@google.com>,
	Anna-Maria Behnsen <anna-maria@linutronix.de>,
	Frederic Weisbecker <frederic@kernel.org>
Cc: linux-kernel <linux-kernel@vger.kernel.org>,
	Benjamin Segall <bsegall@google.com>,
	Eric Dumazet <eric.dumazet@gmail.com>,
	Eric Dumazet <edumazet@google.com>
Subject: Re: [PATCH V2 3/4] posix-timers: Initialise timer->it_signal in posix_timer_add()
Date: Thu, 20 Feb 2025 09:19:28 +0100	[thread overview]
Message-ID: <87r03thvu7.ffs@tglx> (raw)
In-Reply-To: <20250219125522.2535263-4-edumazet@google.com>

On Wed, Feb 19 2025 at 12:55, Eric Dumazet wrote:
> Instead of leaving a NULL value in timer->it_signal,
> set it to the current sig pointer, but with the low order bit set.

And that low order bit set does what?

> This fixes a potential race, in the unlikely case a thread
> was preempted long enough that other threads created more than
> 2^31 itimers.

and then what happens?

> Rename __posix_timers_find() to posix_timers_find()

That's not what the patch does. It renames to posix_sig_owner(). Aside
of that the rename is not relevant to the problem itself.

> Mask the low order bit in posix_timers_find().

What for?

I pointed you before to the changelog documentation, which clearly says:

  A good structure is to explain the context, the problem and the
  solution in separate paragraphs and this order.

It's not asked too much to write proper change logs.

> Signed-off-by: Eric Dumazet <edumazet@google.com>
> ---
>  kernel/time/posix-timers.c | 28 +++++++++++++++++++++-------
>  1 file changed, 21 insertions(+), 7 deletions(-)
>
> diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
> index 1f73ea955756..ed27c7eab456 100644
> --- a/kernel/time/posix-timers.c
> +++ b/kernel/time/posix-timers.c
> @@ -72,15 +72,22 @@ static int hash(struct signal_struct *sig, unsigned int nr)
>  	return hash_32(hash32_ptr(sig) ^ nr, HASH_BITS(posix_timers_hashtable));
>  }
>  
> -static struct k_itimer *__posix_timers_find(struct hlist_head *head,
> +static struct signal_struct *posix_sig_owner(const struct k_itimer *timer)
> +{
> +	/* timer->it_signal can be set concurrently */
> +	unsigned long val = (unsigned long)READ_ONCE(timer->it_signal);
> +
> +	return (struct signal_struct *)(val & ~1UL);
> +}
> +
> +static struct k_itimer *posix_timers_find(struct hlist_head *head,
>  					    struct signal_struct *sig,
>  					    timer_t id)
>  {
>  	struct k_itimer *timer;
>  
>  	hlist_for_each_entry_rcu(timer, head, t_hash, lockdep_is_held(&hash_lock)) {
> -		/* timer->it_signal can be set concurrently */
> -		if ((READ_ONCE(timer->it_signal) == sig) && (timer->it_id == id))
> +		if ((posix_sig_owner(timer) == sig) && (timer->it_id == id))
>  			return timer;
>  	}
>  	return NULL;
> @@ -90,8 +97,14 @@ static struct k_itimer *posix_timer_by_id(timer_t id)
>  {
>  	struct signal_struct *sig = current->signal;
>  	struct hlist_head *head = &posix_timers_hashtable[hash(sig, id)];
> +	struct k_itimer *timer;
>  
> -	return __posix_timers_find(head, sig, id);
> +	hlist_for_each_entry_rcu(timer, head, t_hash) {
> +		/* timer->it_signal can be set concurrently */
> +		if ((READ_ONCE(timer->it_signal) == sig) && (timer->it_id == id))
> +			return timer;
> +	}
> +	return NULL;
>  }
>  
>  static int posix_timer_add(struct k_itimer *timer)
> @@ -113,8 +126,9 @@ static int posix_timer_add(struct k_itimer *timer)
>  		head = &posix_timers_hashtable[hash(sig, id)];
>  
>  		spin_lock(&hash_lock);
> -		if (!__posix_timers_find(head, sig, id)) {
> +		if (!posix_timers_find(head, sig, id)) {
>  			timer->it_id = (timer_t)id;
> +			timer->it_signal = (struct signal_struct *)((unsigned long)sig | 1UL);
>  			hlist_add_head_rcu(&timer->t_hash, head);
>  			spin_unlock(&hash_lock);
>  			return id;
> @@ -453,7 +467,7 @@ static int do_timer_create(clockid_t which_clock, struct sigevent *event,
>  	}
>  	/*
>  	 * After succesful copy out, the timer ID is visible to user space
> -	 * now but not yet valid because new_timer::signal is still NULL.
> +	 * now but not yet valid because new_timer::signal low order bit is 1.
>  	 *
>  	 * Complete the initialization with the clock specific create
>  	 * callback.
> @@ -463,7 +477,7 @@ static int do_timer_create(clockid_t which_clock, struct sigevent *event,
>  		goto out;
>  
>  	spin_lock_irq(&current->sighand->siglock);
> -	/* This makes the timer valid in the hash table */
> +	/* This makes the timer valid in the hash table, clearing low order bit. */

Clearing the low order bit of what? This is a full write and not a clear
low order bit operation.

>  	WRITE_ONCE(new_timer->it_signal, current->signal);
>  	hlist_add_head(&new_timer->list, &current->signal->posix_timers);
>  	spin_unlock_irq(&current->sighand->siglock);

Thanks,

        tglx

  reply	other threads:[~2025-02-20  8:19 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-19 12:55 [PATCH V2 0/4] posix-timers: Reduce spinlock contention Eric Dumazet
2025-02-19 12:55 ` [PATCH V2 1/4] posix-timers: Make next_posix_timer_id an atomic_t Eric Dumazet
2025-02-20  8:09   ` Thomas Gleixner
2025-02-20  8:49     ` Eric Dumazet
2025-02-20 14:04       ` Thomas Gleixner
2025-02-20 14:32         ` Thomas Gleixner
2025-02-20 15:55           ` Eric Dumazet
2025-02-20 16:19             ` Thomas Gleixner
2025-02-19 12:55 ` [PATCH V2 2/4] posix-timers: Initialise timer->it_id in posix_timer_add() Eric Dumazet
2025-02-20  8:12   ` Thomas Gleixner
2025-02-20  8:48     ` Eric Dumazet
2025-02-20 14:10       ` Thomas Gleixner
2025-02-19 12:55 ` [PATCH V2 3/4] posix-timers: Initialise timer->it_signal " Eric Dumazet
2025-02-20  8:19   ` Thomas Gleixner [this message]
2025-02-20  8:44     ` Eric Dumazet
2025-02-20 14:13       ` Thomas Gleixner
2025-02-19 12:55 ` [PATCH V2 4/4] posix-timers: Use RCU " Eric Dumazet
2025-02-19 19:38   ` David Laight
2025-02-19 19:46     ` Eric Dumazet
2025-02-24  9:33   ` Thomas Gleixner
2025-02-24  9:58     ` Eric Dumazet

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=87r03thvu7.ffs@tglx \
    --to=tglx@linutronix.de \
    --cc=anna-maria@linutronix.de \
    --cc=bsegall@google.com \
    --cc=edumazet@google.com \
    --cc=eric.dumazet@gmail.com \
    --cc=frederic@kernel.org \
    --cc=linux-kernel@vger.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.