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.

posix-timers: Add proper state tracking

Right now the state tracking is done by two struct members:

- it_active:
A boolean which tracks armed/disarmed state

- it_signal_seq:
A sequence counter which is used to invalidate settings
and prevent rearming

Replace it_active with it_status and keep properly track about the states
in one place.

This allows to reuse it_signal_seq to track reprogramming, disarm and
delete operations in order to drop signals which are related to the state
previous of those operations.

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/20241001083835.670337048@linutronix.de

+30 -19
+2 -2
include/linux/posix-timers.h
··· 147 147 * @kclock: Pointer to the k_clock struct handling this timer 148 148 * @it_clock: The posix timer clock id 149 149 * @it_id: The posix timer id for identifying the timer 150 - * @it_active: Marker that timer is active 150 + * @it_status: The status of the timer 151 151 * @it_overrun: The overrun counter for pending signals 152 152 * @it_overrun_last: The overrun at the time of the last delivered signal 153 153 * @it_signal_seq: Sequence count to control signal delivery ··· 168 168 const struct k_clock *kclock; 169 169 clockid_t it_clock; 170 170 timer_t it_id; 171 - int it_active; 171 + int it_status; 172 172 s64 it_overrun; 173 173 s64 it_overrun_last; 174 174 unsigned int it_signal_seq;
+1 -1
kernel/time/alarmtimer.c
··· 585 585 */ 586 586 ptr->it_overrun += __alarm_forward_now(alarm, ptr->it_interval, true); 587 587 ++ptr->it_signal_seq; 588 - ptr->it_active = 1; 588 + ptr->it_status = POSIX_TIMER_ARMED; 589 589 result = ALARMTIMER_RESTART; 590 590 } 591 591 spin_unlock_irqrestore(&ptr->it_lock, flags);
+8 -7
kernel/time/posix-cpu-timers.c
··· 453 453 struct cpu_timer *ctmr = &timer->it.cpu; 454 454 struct posix_cputimer_base *base; 455 455 456 - timer->it_active = 0; 457 456 if (!cpu_timer_dequeue(ctmr)) 458 457 return; 459 458 ··· 493 494 */ 494 495 WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node)); 495 496 } else { 496 - if (timer->it.cpu.firing) 497 + if (timer->it.cpu.firing) { 497 498 ret = TIMER_RETRY; 498 - else 499 + } else { 499 500 disarm_timer(timer, p); 500 - 501 + timer->it_status = POSIX_TIMER_DISARMED; 502 + } 501 503 unlock_task_sighand(p, &flags); 502 504 } 503 505 ··· 560 560 struct cpu_timer *ctmr = &timer->it.cpu; 561 561 u64 newexp = cpu_timer_getexpires(ctmr); 562 562 563 - timer->it_active = 1; 563 + timer->it_status = POSIX_TIMER_ARMED; 564 564 if (!cpu_timer_enqueue(&base->tqhead, ctmr)) 565 565 return; 566 566 ··· 586 586 { 587 587 struct cpu_timer *ctmr = &timer->it.cpu; 588 588 589 - timer->it_active = 0; 589 + timer->it_status = POSIX_TIMER_DISARMED; 590 + 590 591 if (unlikely(timer->sigq == NULL)) { 591 592 /* 592 593 * This a special case for clock_nanosleep, ··· 672 671 ret = TIMER_RETRY; 673 672 } else { 674 673 cpu_timer_dequeue(ctmr); 675 - timer->it_active = 0; 674 + timer->it_status = POSIX_TIMER_DISARMED; 676 675 } 677 676 678 677 /*
+13 -9
kernel/time/posix-timers.c
··· 272 272 if (timr->it_interval && timr->it_signal_seq == info->si_sys_private) { 273 273 timr->kclock->timer_rearm(timr); 274 274 275 - timr->it_active = 1; 275 + timr->it_status = POSIX_TIMER_ARMED; 276 276 timr->it_overrun_last = timr->it_overrun; 277 277 timr->it_overrun = -1LL; 278 278 ++timr->it_signal_seq; ··· 292 292 293 293 int posix_timer_queue_signal(struct k_itimer *timr) 294 294 { 295 + enum posix_timer_state state = POSIX_TIMER_DISARMED; 295 296 int ret, si_private = 0; 296 297 enum pid_type type; 297 298 298 299 lockdep_assert_held(&timr->it_lock); 299 300 300 - timr->it_active = 0; 301 - if (timr->it_interval) 301 + if (timr->it_interval) { 302 + state = POSIX_TIMER_REQUEUE_PENDING; 302 303 si_private = ++timr->it_signal_seq; 304 + } 305 + timr->it_status = state; 303 306 304 307 type = !(timr->it_sigev_notify & SIGEV_THREAD_ID) ? PIDTYPE_TGID : PIDTYPE_PID; 305 308 ret = send_sigqueue(timr->sigq, timr->it_pid, type, si_private); ··· 370 367 timr->it_overrun += hrtimer_forward(timer, now, timr->it_interval); 371 368 ret = HRTIMER_RESTART; 372 369 ++timr->it_signal_seq; 373 - timr->it_active = 1; 370 + timr->it_status = POSIX_TIMER_ARMED; 374 371 } 375 372 } 376 373 ··· 643 640 /* interval timer ? */ 644 641 if (iv) { 645 642 cur_setting->it_interval = ktime_to_timespec64(iv); 646 - } else if (!timr->it_active) { 643 + } else if (timr->it_status == POSIX_TIMER_DISARMED) { 647 644 /* 648 645 * SIGEV_NONE oneshot timers are never queued and therefore 649 - * timr->it_active is always false. The check below 646 + * timr->it_status is always DISARMED. The check below 650 647 * vs. remaining time will handle this case. 651 648 * 652 649 * For all other timers there is nothing to update here, so ··· 891 888 if (kc->timer_try_to_cancel(timr) < 0) 892 889 return TIMER_RETRY; 893 890 894 - timr->it_active = 0; 891 + timr->it_status = POSIX_TIMER_DISARMED; 895 892 posix_timer_set_common(timr, new_setting); 896 893 897 894 /* Keep timer disarmed when it_value is zero */ ··· 904 901 sigev_none = timr->it_sigev_notify == SIGEV_NONE; 905 902 906 903 kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none); 907 - timr->it_active = !sigev_none; 904 + if (!sigev_none) 905 + timr->it_status = POSIX_TIMER_ARMED; 908 906 return 0; 909 907 } 910 908 ··· 1004 1000 timer->it_interval = 0; 1005 1001 if (kc->timer_try_to_cancel(timer) < 0) 1006 1002 return TIMER_RETRY; 1007 - timer->it_active = 0; 1003 + timer->it_status = POSIX_TIMER_DISARMED; 1008 1004 return 0; 1009 1005 } 1010 1006
+6
kernel/time/posix-timers.h
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 2 #define TIMER_RETRY 1 3 3 4 + enum posix_timer_state { 5 + POSIX_TIMER_DISARMED, 6 + POSIX_TIMER_ARMED, 7 + POSIX_TIMER_REQUEUE_PENDING, 8 + }; 9 + 4 10 struct k_clock { 5 11 int (*clock_getres)(const clockid_t which_clock, 6 12 struct timespec64 *tp);