Skip to content

Commit 9a7b015

Browse files
committed
Merge tag 'posix-timers-2024-07-29' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks into timers/core
Pull updates for posix timers and related signal code from Frederic Weisbecker: * Prepare posix timers selftests for upcoming changes: - Check signal behaviour sanity against SIG_IGN - Check signal behaviour sanity against timer reprogramm/deletion - Check SIGEV_NONE pending expiry read - Check interval timer read on a pending SIGNAL - Check correct overrun count after signal block/unblock * Various consolidations: - timer get/set - signal queue * Fixes: - Correctly read SIGEV_NONE timers - Forward expiry while reading expired interval timers with pending signal - Don't arm SIGEV_NONE timers * Various cleanups all over the place
2 parents 8400291 + 7f8af7b commit 9a7b015

File tree

12 files changed

+607
-286
lines changed

12 files changed

+607
-286
lines changed

fs/proc/base.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2456,13 +2456,13 @@ static void *timers_start(struct seq_file *m, loff_t *pos)
24562456
if (!tp->sighand)
24572457
return ERR_PTR(-ESRCH);
24582458

2459-
return seq_list_start(&tp->task->signal->posix_timers, *pos);
2459+
return seq_hlist_start(&tp->task->signal->posix_timers, *pos);
24602460
}
24612461

24622462
static void *timers_next(struct seq_file *m, void *v, loff_t *pos)
24632463
{
24642464
struct timers_private *tp = m->private;
2465-
return seq_list_next(v, &tp->task->signal->posix_timers, pos);
2465+
return seq_hlist_next(v, &tp->task->signal->posix_timers, pos);
24662466
}
24672467

24682468
static void timers_stop(struct seq_file *m, void *v)
@@ -2491,7 +2491,7 @@ static int show_timer(struct seq_file *m, void *v)
24912491
[SIGEV_THREAD] = "thread",
24922492
};
24932493

2494-
timer = list_entry((struct list_head *)v, struct k_itimer, list);
2494+
timer = hlist_entry((struct hlist_node *)v, struct k_itimer, list);
24952495
notify = timer->it_sigev_notify;
24962496

24972497
seq_printf(m, "ID: %d\n", timer->it_id);

fs/signalfd.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, kernel_siginfo_t *info
159159
DECLARE_WAITQUEUE(wait, current);
160160

161161
spin_lock_irq(&current->sighand->siglock);
162-
ret = dequeue_signal(current, &ctx->sigmask, info, &type);
162+
ret = dequeue_signal(&ctx->sigmask, info, &type);
163163
switch (ret) {
164164
case 0:
165165
if (!nonblock)
@@ -174,7 +174,7 @@ static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, kernel_siginfo_t *info
174174
add_wait_queue(&current->sighand->signalfd_wqh, &wait);
175175
for (;;) {
176176
set_current_state(TASK_INTERRUPTIBLE);
177-
ret = dequeue_signal(current, &ctx->sigmask, info, &type);
177+
ret = dequeue_signal(&ctx->sigmask, info, &type);
178178
if (ret != 0)
179179
break;
180180
if (signal_pending(current)) {

include/linux/posix-timers.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ static inline void posix_cputimers_init_work(void) { }
158158
* @rcu: RCU head for freeing the timer.
159159
*/
160160
struct k_itimer {
161-
struct list_head list;
161+
struct hlist_node list;
162162
struct hlist_node t_hash;
163163
spinlock_t it_lock;
164164
const struct k_clock *kclock;

include/linux/sched/signal.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ struct signal_struct {
137137

138138
/* POSIX.1b Interval Timers */
139139
unsigned int next_posix_timer_id;
140-
struct list_head posix_timers;
140+
struct hlist_head posix_timers;
141141

142142
/* ITIMER_REAL timer for the process */
143143
struct hrtimer real_timer;
@@ -276,8 +276,7 @@ static inline void signal_set_stop_flags(struct signal_struct *sig,
276276
extern void flush_signals(struct task_struct *);
277277
extern void ignore_signals(struct task_struct *);
278278
extern void flush_signal_handlers(struct task_struct *, int force_default);
279-
extern int dequeue_signal(struct task_struct *task, sigset_t *mask,
280-
kernel_siginfo_t *info, enum pid_type *type);
279+
extern int dequeue_signal(sigset_t *mask, kernel_siginfo_t *info, enum pid_type *type);
281280

282281
static inline int kernel_dequeue_signal(void)
283282
{
@@ -287,7 +286,7 @@ static inline int kernel_dequeue_signal(void)
287286
int ret;
288287

289288
spin_lock_irq(&task->sighand->siglock);
290-
ret = dequeue_signal(task, &task->blocked, &__info, &__type);
289+
ret = dequeue_signal(&task->blocked, &__info, &__type);
291290
spin_unlock_irq(&task->sighand->siglock);
292291

293292
return ret;

init/init_task.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static struct signal_struct init_signals = {
2929
.cred_guard_mutex = __MUTEX_INITIALIZER(init_signals.cred_guard_mutex),
3030
.exec_update_lock = __RWSEM_INITIALIZER(init_signals.exec_update_lock),
3131
#ifdef CONFIG_POSIX_TIMERS
32-
.posix_timers = LIST_HEAD_INIT(init_signals.posix_timers),
32+
.posix_timers = HLIST_HEAD_INIT,
3333
.cputimer = {
3434
.cputime_atomic = INIT_CPUTIME_ATOMIC,
3535
},

kernel/fork.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1861,7 +1861,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
18611861
prev_cputime_init(&sig->prev_cputime);
18621862

18631863
#ifdef CONFIG_POSIX_TIMERS
1864-
INIT_LIST_HEAD(&sig->posix_timers);
1864+
INIT_HLIST_HEAD(&sig->posix_timers);
18651865
hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
18661866
sig->real_timer.function = it_real_fn;
18671867
#endif

kernel/signal.c

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -618,20 +618,18 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
618618
}
619619

620620
/*
621-
* Dequeue a signal and return the element to the caller, which is
622-
* expected to free it.
623-
*
624-
* All callers have to hold the siglock.
621+
* Try to dequeue a signal. If a deliverable signal is found fill in the
622+
* caller provided siginfo and return the signal number. Otherwise return
623+
* 0.
625624
*/
626-
int dequeue_signal(struct task_struct *tsk, sigset_t *mask,
627-
kernel_siginfo_t *info, enum pid_type *type)
625+
int dequeue_signal(sigset_t *mask, kernel_siginfo_t *info, enum pid_type *type)
628626
{
627+
struct task_struct *tsk = current;
629628
bool resched_timer = false;
630629
int signr;
631630

632-
/* We only dequeue private signals from ourselves, we don't let
633-
* signalfd steal them
634-
*/
631+
lockdep_assert_held(&tsk->sighand->siglock);
632+
635633
*type = PIDTYPE_PID;
636634
signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer);
637635
if (!signr) {
@@ -1940,10 +1938,11 @@ struct sigqueue *sigqueue_alloc(void)
19401938

19411939
void sigqueue_free(struct sigqueue *q)
19421940
{
1943-
unsigned long flags;
19441941
spinlock_t *lock = &current->sighand->siglock;
1942+
unsigned long flags;
19451943

1946-
BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
1944+
if (WARN_ON_ONCE(!(q->flags & SIGQUEUE_PREALLOC)))
1945+
return;
19471946
/*
19481947
* We must hold ->siglock while testing q->list
19491948
* to serialize with collect_signal() or with
@@ -1971,7 +1970,10 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type)
19711970
unsigned long flags;
19721971
int ret, result;
19731972

1974-
BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
1973+
if (WARN_ON_ONCE(!(q->flags & SIGQUEUE_PREALLOC)))
1974+
return 0;
1975+
if (WARN_ON_ONCE(q->info.si_code != SI_TIMER))
1976+
return 0;
19751977

19761978
ret = -1;
19771979
rcu_read_lock();
@@ -2006,7 +2008,6 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type)
20062008
* If an SI_TIMER entry is already queue just increment
20072009
* the overrun count.
20082010
*/
2009-
BUG_ON(q->info.si_code != SI_TIMER);
20102011
q->info.si_overrun++;
20112012
result = TRACE_SIGNAL_ALREADY_PENDING;
20122013
goto out;
@@ -2793,8 +2794,7 @@ bool get_signal(struct ksignal *ksig)
27932794
type = PIDTYPE_PID;
27942795
signr = dequeue_synchronous_signal(&ksig->info);
27952796
if (!signr)
2796-
signr = dequeue_signal(current, &current->blocked,
2797-
&ksig->info, &type);
2797+
signr = dequeue_signal(&current->blocked, &ksig->info, &type);
27982798

27992799
if (!signr)
28002800
break; /* will return 0 */
@@ -3648,7 +3648,7 @@ static int do_sigtimedwait(const sigset_t *which, kernel_siginfo_t *info,
36483648
signotset(&mask);
36493649

36503650
spin_lock_irq(&tsk->sighand->siglock);
3651-
sig = dequeue_signal(tsk, &mask, info, &type);
3651+
sig = dequeue_signal(&mask, info, &type);
36523652
if (!sig && timeout) {
36533653
/*
36543654
* None ready, temporarily unblock those we're interested
@@ -3667,7 +3667,7 @@ static int do_sigtimedwait(const sigset_t *which, kernel_siginfo_t *info,
36673667
spin_lock_irq(&tsk->sighand->siglock);
36683668
__set_task_blocked(tsk, &tsk->real_blocked);
36693669
sigemptyset(&tsk->real_blocked);
3670-
sig = dequeue_signal(tsk, &mask, info, &type);
3670+
sig = dequeue_signal(&mask, info, &type);
36713671
}
36723672
spin_unlock_irq(&tsk->sighand->siglock);
36733673

kernel/time/alarmtimer.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -574,15 +574,10 @@ static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
574574
it.alarm.alarmtimer);
575575
enum alarmtimer_restart result = ALARMTIMER_NORESTART;
576576
unsigned long flags;
577-
int si_private = 0;
578577

579578
spin_lock_irqsave(&ptr->it_lock, flags);
580579

581-
ptr->it_active = 0;
582-
if (ptr->it_interval)
583-
si_private = ++ptr->it_requeue_pending;
584-
585-
if (posix_timer_event(ptr, si_private) && ptr->it_interval) {
580+
if (posix_timer_queue_signal(ptr) && ptr->it_interval) {
586581
/*
587582
* Handle ignored signals and rearm the timer. This will go
588583
* away once we handle ignored signals proper. Ensure that

0 commit comments

Comments
 (0)