[patch V5 16/26] signal: Replace resched_timer logic

From: Thomas Gleixner
Date: Tue Oct 01 2024 - 04:45:29 EST


In preparation for handling ignored posix timer signals correctly and
embedding the sigqueue struct into struct k_itimer, hand down a pointer to
the sigqueue struct into posix_timer_deliver_signal() instead of just
having a boolean flag.

No functional change.

Suggested-by: Eric W. Biederman <ebiederm@xxxxxxxxxxxx>
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
---
V5: New patch
---
include/linux/posix-timers.h | 5 +++--
kernel/signal.c | 24 ++++++++++++------------
kernel/time/posix-timers.c | 2 +-
3 files changed, 16 insertions(+), 15 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -110,7 +110,7 @@ static inline void posix_cputimers_rt_wa
void posixtimer_rearm_itimer(struct task_struct *p);
bool posixtimer_init_sigqueue(struct sigqueue *q);
int posixtimer_send_sigqueue(struct k_itimer *tmr);
-bool posixtimer_deliver_signal(struct kernel_siginfo *info);
+bool posixtimer_deliver_signal(struct kernel_siginfo *info, struct sigqueue *timer_sigq);
void posixtimer_free_timer(struct k_itimer *timer);

/* Init task static initializer */
@@ -135,7 +135,8 @@ static inline void posix_cputimers_init(
static inline void posix_cputimers_group_init(struct posix_cputimers *pct,
u64 cpu_limit) { }
static inline void posixtimer_rearm_itimer(struct task_struct *p) { }
-static inline bool posixtimer_deliver_signal(struct kernel_siginfo *info) { return false; }
+static inline bool posixtimer_deliver_signal(struct kernel_siginfo *info,
+ struct sigqueue *timer_sigq) { return false; }
static inline void posixtimer_free_timer(struct k_itimer *timer) { }
#endif

--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -545,7 +545,7 @@ bool unhandled_signal(struct task_struct
}

static void collect_signal(int sig, struct sigpending *list, kernel_siginfo_t *info,
- bool *resched_timer)
+ struct sigqueue **timer_sigq)
{
struct sigqueue *q, *first = NULL;

@@ -568,10 +568,10 @@ static void collect_signal(int sig, stru
list_del_init(&first->list);
copy_siginfo(info, &first->info);

- *resched_timer = (first->flags & SIGQUEUE_PREALLOC) &&
- (info->si_code == SI_TIMER);
-
- __sigqueue_free(first);
+ if (unlikely((first->flags & SIGQUEUE_PREALLOC) && (info->si_code == SI_TIMER)))
+ *timer_sigq = first;
+ else
+ __sigqueue_free(first);
} else {
/*
* Ok, it wasn't in the queue. This must be
@@ -588,12 +588,12 @@ static void collect_signal(int sig, stru
}

static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
- kernel_siginfo_t *info, bool *resched_timer)
+ kernel_siginfo_t *info, struct sigqueue **timer_sigq)
{
int sig = next_signal(pending, mask);

if (sig)
- collect_signal(sig, pending, info, resched_timer);
+ collect_signal(sig, pending, info, timer_sigq);
return sig;
}

@@ -604,19 +604,19 @@ static int __dequeue_signal(struct sigpe
*/
int dequeue_signal(sigset_t *mask, kernel_siginfo_t *info, enum pid_type *type)
{
+ struct sigqueue *timer_sigq = NULL;
struct task_struct *tsk = current;
- bool resched_timer = false;
int signr;

lockdep_assert_held(&tsk->sighand->siglock);

again:
*type = PIDTYPE_PID;
- signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer);
+ signr = __dequeue_signal(&tsk->pending, mask, info, &timer_sigq);
if (!signr) {
*type = PIDTYPE_TGID;
signr = __dequeue_signal(&tsk->signal->shared_pending,
- mask, info, &resched_timer);
+ mask, info, &timer_sigq);

if (unlikely(signr == SIGALRM))
posixtimer_rearm_itimer(tsk);
@@ -642,8 +642,8 @@ int dequeue_signal(sigset_t *mask, kerne
current->jobctl |= JOBCTL_STOP_DEQUEUED;
}

- if (IS_ENABLED(CONFIG_POSIX_TIMERS) && unlikely(resched_timer)) {
- if (!posixtimer_deliver_signal(info))
+ if (IS_ENABLED(CONFIG_POSIX_TIMERS) && unlikely(timer_sigq)) {
+ if (!posixtimer_deliver_signal(info, timer_sigq))
goto again;
}

--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -253,7 +253,7 @@ static void common_hrtimer_rearm(struct
* This function is called from the signal delivery code. It decides
* whether the signal should be dropped and rearms interval timers.
*/
-bool posixtimer_deliver_signal(struct kernel_siginfo *info)
+bool posixtimer_deliver_signal(struct kernel_siginfo *info, struct sigqueue *timer_sigq)
{
struct k_itimer *timr;
unsigned long flags;