diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2024-11-05 09:14:36 +0100 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2024-11-07 02:14:43 +0100 |
commit | 5d916a0988eed5217c103932ff4887c9ae83c89c (patch) | |
tree | 0b5c34dca31f6f7b191dd579cb60580ecc8421f3 /kernel/time | |
parent | 4cf7bf2a2f1a8ace4a49a1138c8123fdb5990093 (diff) |
posix-timers: Add a refcount to struct k_itimer
To cure the SIG_IGN handling for posix interval timers, the preallocated
sigqueue needs to be embedded into struct k_itimer to prevent life time
races of all sorts.
To make that work correctly it needs reference counting so that timer
deletion does not free the timer prematuraly when there is a signal queued
or delivered concurrently.
Add a rcuref to the posix timer part.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/all/20241105064213.304756440@linutronix.de
Diffstat (limited to 'kernel/time')
-rw-r--r-- | kernel/time/posix-timers.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 66ed49efc02f..53bd3c4de92c 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -417,10 +417,11 @@ static struct k_itimer * alloc_posix_timer(void) return NULL; } clear_siginfo(&tmr->sigq->info); + rcuref_init(&tmr->rcuref, 1); return tmr; } -static void posix_timer_free(struct k_itimer *tmr) +void posixtimer_free_timer(struct k_itimer *tmr) { put_pid(tmr->it_pid); sigqueue_free(tmr->sigq); @@ -432,7 +433,7 @@ static void posix_timer_unhash_and_free(struct k_itimer *tmr) spin_lock(&hash_lock); hlist_del_rcu(&tmr->t_hash); spin_unlock(&hash_lock); - posix_timer_free(tmr); + posixtimer_putref(tmr); } static int common_timer_create(struct k_itimer *new_timer) @@ -467,7 +468,7 @@ static int do_timer_create(clockid_t which_clock, struct sigevent *event, */ new_timer_id = posix_timer_add(new_timer); if (new_timer_id < 0) { - posix_timer_free(new_timer); + posixtimer_free_timer(new_timer); return new_timer_id; } |