[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250219193832.6c3fa40f@pumpkin>
Date: Wed, 19 Feb 2025 19:38:32 +0000
From: David Laight <david.laight.linux@...il.com>
To: Eric Dumazet <edumazet@...gle.com>
Cc: Anna-Maria Behnsen <anna-maria@...utronix.de>, Frederic Weisbecker
<frederic@...nel.org>, Thomas Gleixner <tglx@...utronix.de>, linux-kernel
<linux-kernel@...r.kernel.org>, Benjamin Segall <bsegall@...gle.com>, Eric
Dumazet <eric.dumazet@...il.com>
Subject: Re: [PATCH V2 4/4] posix-timers: Use RCU in posix_timer_add()
On Wed, 19 Feb 2025 12:55:22 +0000
Eric Dumazet <edumazet@...gle.com> wrote:
> If many posix timers are hashed in posix_timers_hashtable,
> hash_lock can be held for long durations.
>
> This can be really bad in some cases as Thomas
> explained in https://lore.kernel.org/all/87ednpyyeo.ffs@tglx/
>
> We can perform all searches under RCU, then acquire
> the lock only when there is a good chance to need it,
> and after cpu caches were populated.
>
> Also add a cond_resched() in the possible long loop.
Since this code fragment has a 'free choice' of the timer id, why not
select an empty table slot and then pick a value that maps to it?
You can run a free-list through the empty table slots so the allocate
is (almost always) fixed cost and trivial.
The only complexity arises when the table is full and needs to be
reallocated twice as large.
The high bits of the 'id' can be incremented every time the id is allocated
so stale ids can be detected (until a quite large number of allocate/free).
David
>
> Signed-off-by: Eric Dumazet <edumazet@...gle.com>
> ---
> kernel/time/posix-timers.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
> index ed27c7eab456..bd73bc4707c1 100644
> --- a/kernel/time/posix-timers.c
> +++ b/kernel/time/posix-timers.c
> @@ -125,7 +125,19 @@ static int posix_timer_add(struct k_itimer *timer)
>
> head = &posix_timers_hashtable[hash(sig, id)];
>
> + rcu_read_lock();
> + if (posix_timers_find(head, sig, id)) {
> + rcu_read_unlock();
> + cond_resched();
> + continue;
> + }
> + rcu_read_unlock();
> spin_lock(&hash_lock);
> + /*
> + * We must perform the lookup under hash_lock protection
> + * because another thread could have used the same id.
> + * This is very unlikely, but possible.
> + */
> if (!posix_timers_find(head, sig, id)) {
> timer->it_id = (timer_t)id;
> timer->it_signal = (struct signal_struct *)((unsigned long)sig | 1UL);
Powered by blists - more mailing lists