summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2024-11-05 11:14:32 +0300
committerThomas Gleixner <tglx@linutronix.de>2024-11-07 04:14:43 +0300
commitb06b0345fff3678517acd0f1837d52477ba30944 (patch)
treebd129efa8e7596f745917ad597d7101a0e396585
parent513793bc6ab331b947111e8efaf8fcef33fb83e5 (diff)
downloadlinux-b06b0345fff3678517acd0f1837d52477ba30944.tar.xz
posix-timers: Make signal overrun accounting sensible
The handling of the timer overrun in the signal code is inconsistent as it takes previous overruns into account. This is just wrong as after the reprogramming of a timer the overrun count starts over from a clean state, i.e. 0. Don't touch info::si_overrun in send_sigqueue() and only store the overrun value at signal delivery time, which is computed from the timer itself relative to the expiry time. 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.106738193@linutronix.de
-rw-r--r--kernel/signal.c6
-rw-r--r--kernel/time/posix-timers.c11
2 files changed, 6 insertions, 11 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 68e6bc70ccf2..ba7159b25d51 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1968,15 +1968,9 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type, int s
ret = 0;
if (unlikely(!list_empty(&q->list))) {
- /*
- * If an SI_TIMER entry is already queue just increment
- * the overrun count.
- */
- q->info.si_overrun++;
result = TRACE_SIGNAL_ALREADY_PENDING;
goto out;
}
- q->info.si_overrun = 0;
signalfd_notify(t, sig);
pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending;
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index b380e25d4947..66ed49efc02f 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -233,11 +233,12 @@ __initcall(init_posix_timers);
* The siginfo si_overrun field and the return value of timer_getoverrun(2)
* are of type int. Clamp the overrun value to INT_MAX
*/
-static inline int timer_overrun_to_int(struct k_itimer *timr, int baseval)
+static inline int timer_overrun_to_int(struct k_itimer *timr)
{
- s64 sum = timr->it_overrun_last + (s64)baseval;
+ if (timr->it_overrun_last > (s64)INT_MAX)
+ return INT_MAX;
- return sum > (s64)INT_MAX ? INT_MAX : (int)sum;
+ return (int)timr->it_overrun_last;
}
static void common_hrtimer_rearm(struct k_itimer *timr)
@@ -280,7 +281,7 @@ bool posixtimer_deliver_signal(struct kernel_siginfo *info)
timr->it_overrun = -1LL;
++timr->it_signal_seq;
- info->si_overrun = timer_overrun_to_int(timr, info->si_overrun);
+ info->si_overrun = timer_overrun_to_int(timr);
}
ret = true;
@@ -774,7 +775,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_t, timer_id)
if (!timr)
return -EINVAL;
- overrun = timer_overrun_to_int(timr, 0);
+ overrun = timer_overrun_to_int(timr);
unlock_timer(timr, flags);
return overrun;