Skip to content

Commit a31a300

Browse files
committed
posix-timers: Use guards in a few places
Switch locking and RCU to guards where applicable. Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Frederic Weisbecker <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent f6d0c3d commit a31a300

File tree

1 file changed

+30
-38
lines changed

1 file changed

+30
-38
lines changed

kernel/time/posix-timers.c

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,8 @@ void posixtimer_free_timer(struct k_itimer *tmr)
397397

398398
static void posix_timer_unhash_and_free(struct k_itimer *tmr)
399399
{
400-
spin_lock(&hash_lock);
401-
hlist_del_rcu(&tmr->t_hash);
402-
spin_unlock(&hash_lock);
400+
scoped_guard (spinlock, &hash_lock)
401+
hlist_del_rcu(&tmr->t_hash);
403402
posixtimer_putref(tmr);
404403
}
405404

@@ -443,9 +442,8 @@ static int do_timer_create(clockid_t which_clock, struct sigevent *event,
443442
new_timer->it_overrun = -1LL;
444443

445444
if (event) {
446-
rcu_read_lock();
447-
new_timer->it_pid = get_pid(good_sigevent(event));
448-
rcu_read_unlock();
445+
scoped_guard (rcu)
446+
new_timer->it_pid = get_pid(good_sigevent(event));
449447
if (!new_timer->it_pid) {
450448
error = -EINVAL;
451449
goto out;
@@ -579,22 +577,18 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags)
579577
* can't change, but timr::it_signal becomes NULL during
580578
* destruction.
581579
*/
582-
rcu_read_lock();
580+
guard(rcu)();
583581
timr = posix_timer_by_id(timer_id);
584582
if (timr) {
585583
spin_lock_irqsave(&timr->it_lock, *flags);
586584
/*
587585
* Validate under timr::it_lock that timr::it_signal is
588586
* still valid. Pairs with #1 above.
589587
*/
590-
if (timr->it_signal == current->signal) {
591-
rcu_read_unlock();
588+
if (timr->it_signal == current->signal)
592589
return timr;
593-
}
594590
spin_unlock_irqrestore(&timr->it_lock, *flags);
595591
}
596-
rcu_read_unlock();
597-
598592
return NULL;
599593
}
600594

@@ -825,16 +819,15 @@ static struct k_itimer *timer_wait_running(struct k_itimer *timer,
825819
timer_t timer_id = READ_ONCE(timer->it_id);
826820

827821
/* Prevent kfree(timer) after dropping the lock */
828-
rcu_read_lock();
829-
unlock_timer(timer, *flags);
830-
831-
/*
832-
* kc->timer_wait_running() might drop RCU lock. So @timer
833-
* cannot be touched anymore after the function returns!
834-
*/
835-
timer->kclock->timer_wait_running(timer);
822+
scoped_guard (rcu) {
823+
unlock_timer(timer, *flags);
824+
/*
825+
* kc->timer_wait_running() might drop RCU lock. So @timer
826+
* cannot be touched anymore after the function returns!
827+
*/
828+
timer->kclock->timer_wait_running(timer);
829+
}
836830

837-
rcu_read_unlock();
838831
/* Relock the timer. It might be not longer hashed. */
839832
return lock_timer(timer_id, flags);
840833
}
@@ -1020,20 +1013,20 @@ SYSCALL_DEFINE1(timer_delete, timer_t, timer_id)
10201013
goto retry_delete;
10211014
}
10221015

1023-
spin_lock(&current->sighand->siglock);
1024-
hlist_del(&timer->list);
1025-
posix_timer_cleanup_ignored(timer);
1026-
/*
1027-
* A concurrent lookup could check timer::it_signal lockless. It
1028-
* will reevaluate with timer::it_lock held and observe the NULL.
1029-
*
1030-
* It must be written with siglock held so that the signal code
1031-
* observes timer->it_signal == NULL in do_sigaction(SIG_IGN),
1032-
* which prevents it from moving a pending signal of a deleted
1033-
* timer to the ignore list.
1034-
*/
1035-
WRITE_ONCE(timer->it_signal, NULL);
1036-
spin_unlock(&current->sighand->siglock);
1016+
scoped_guard (spinlock, &current->sighand->siglock) {
1017+
hlist_del(&timer->list);
1018+
posix_timer_cleanup_ignored(timer);
1019+
/*
1020+
* A concurrent lookup could check timer::it_signal lockless. It
1021+
* will reevaluate with timer::it_lock held and observe the NULL.
1022+
*
1023+
* It must be written with siglock held so that the signal code
1024+
* observes timer->it_signal == NULL in do_sigaction(SIG_IGN),
1025+
* which prevents it from moving a pending signal of a deleted
1026+
* timer to the ignore list.
1027+
*/
1028+
WRITE_ONCE(timer->it_signal, NULL);
1029+
}
10371030

10381031
unlock_timer(timer, flags);
10391032
posix_timer_unhash_and_free(timer);
@@ -1106,9 +1099,8 @@ void exit_itimers(struct task_struct *tsk)
11061099
return;
11071100

11081101
/* Protect against concurrent read via /proc/$PID/timers */
1109-
spin_lock_irq(&tsk->sighand->siglock);
1110-
hlist_move_list(&tsk->signal->posix_timers, &timers);
1111-
spin_unlock_irq(&tsk->sighand->siglock);
1102+
scoped_guard (spinlock_irq, &tsk->sighand->siglock)
1103+
hlist_move_list(&tsk->signal->posix_timers, &timers);
11121104

11131105
/* The timers are not longer accessible via tsk::signal */
11141106
while (!hlist_empty(&timers)) {

0 commit comments

Comments
 (0)