Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

signal: Replace resched_timer logic

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@xmission.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Link: https://lore.kernel.org/all/20241105064213.652658158@linutronix.de

+24 -15
+3 -2
include/linux/posix-timers.h
··· 110 110 void posixtimer_rearm_itimer(struct task_struct *p); 111 111 bool posixtimer_init_sigqueue(struct sigqueue *q); 112 112 int posixtimer_send_sigqueue(struct k_itimer *tmr); 113 - bool posixtimer_deliver_signal(struct kernel_siginfo *info); 113 + bool posixtimer_deliver_signal(struct kernel_siginfo *info, struct sigqueue *timer_sigq); 114 114 void posixtimer_free_timer(struct k_itimer *timer); 115 115 116 116 /* Init task static initializer */ ··· 135 135 static inline void posix_cputimers_group_init(struct posix_cputimers *pct, 136 136 u64 cpu_limit) { } 137 137 static inline void posixtimer_rearm_itimer(struct task_struct *p) { } 138 - static inline bool posixtimer_deliver_signal(struct kernel_siginfo *info) { return false; } 138 + static inline bool posixtimer_deliver_signal(struct kernel_siginfo *info, 139 + struct sigqueue *timer_sigq) { return false; } 139 140 static inline void posixtimer_free_timer(struct k_itimer *timer) { } 140 141 #endif 141 142
+20 -12
kernel/signal.c
··· 545 545 } 546 546 547 547 static void collect_signal(int sig, struct sigpending *list, kernel_siginfo_t *info, 548 - bool *resched_timer) 548 + struct sigqueue **timer_sigq) 549 549 { 550 550 struct sigqueue *q, *first = NULL; 551 551 ··· 568 568 list_del_init(&first->list); 569 569 copy_siginfo(info, &first->info); 570 570 571 - *resched_timer = (first->flags & SIGQUEUE_PREALLOC) && 572 - (info->si_code == SI_TIMER); 573 - 574 - __sigqueue_free(first); 571 + /* 572 + * posix-timer signals are preallocated and freed when the 573 + * timer goes away. Either directly or by clearing 574 + * SIGQUEUE_PREALLOC so that the next delivery will free 575 + * them. Spare the extra round through __sigqueue_free() 576 + * which is ignoring preallocated signals. 577 + */ 578 + if (unlikely((first->flags & SIGQUEUE_PREALLOC) && (info->si_code == SI_TIMER))) 579 + *timer_sigq = first; 580 + else 581 + __sigqueue_free(first); 575 582 } else { 576 583 /* 577 584 * Ok, it wasn't in the queue. This must be ··· 595 588 } 596 589 597 590 static int __dequeue_signal(struct sigpending *pending, sigset_t *mask, 598 - kernel_siginfo_t *info, bool *resched_timer) 591 + kernel_siginfo_t *info, struct sigqueue **timer_sigq) 599 592 { 600 593 int sig = next_signal(pending, mask); 601 594 602 595 if (sig) 603 - collect_signal(sig, pending, info, resched_timer); 596 + collect_signal(sig, pending, info, timer_sigq); 604 597 return sig; 605 598 } 606 599 ··· 612 605 int dequeue_signal(sigset_t *mask, kernel_siginfo_t *info, enum pid_type *type) 613 606 { 614 607 struct task_struct *tsk = current; 615 - bool resched_timer = false; 608 + struct sigqueue *timer_sigq; 616 609 int signr; 617 610 618 611 lockdep_assert_held(&tsk->sighand->siglock); 619 612 620 613 again: 621 614 *type = PIDTYPE_PID; 622 - signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer); 615 + timer_sigq = NULL; 616 + signr = __dequeue_signal(&tsk->pending, mask, info, &timer_sigq); 623 617 if (!signr) { 624 618 *type = PIDTYPE_TGID; 625 619 signr = __dequeue_signal(&tsk->signal->shared_pending, 626 - mask, info, &resched_timer); 620 + mask, info, &timer_sigq); 627 621 628 622 if (unlikely(signr == SIGALRM)) 629 623 posixtimer_rearm_itimer(tsk); ··· 650 642 current->jobctl |= JOBCTL_STOP_DEQUEUED; 651 643 } 652 644 653 - if (IS_ENABLED(CONFIG_POSIX_TIMERS) && unlikely(resched_timer)) { 654 - if (!posixtimer_deliver_signal(info)) 645 + if (IS_ENABLED(CONFIG_POSIX_TIMERS) && unlikely(timer_sigq)) { 646 + if (!posixtimer_deliver_signal(info, timer_sigq)) 655 647 goto again; 656 648 } 657 649
+1 -1
kernel/time/posix-timers.c
··· 254 254 * This function is called from the signal delivery code. It decides 255 255 * whether the signal should be dropped and rearms interval timers. 256 256 */ 257 - bool posixtimer_deliver_signal(struct kernel_siginfo *info) 257 + bool posixtimer_deliver_signal(struct kernel_siginfo *info, struct sigqueue *timer_sigq) 258 258 { 259 259 struct k_itimer *timr; 260 260 unsigned long flags;