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.

Merge tag 'timers-core-2025-09-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer core updates from Thomas Gleixner:

- Address the inconsistent shutdown sequence of per CPU clockevents on
CPU hotplug, which only removed it from the core but failed to invoke
the actual device driver shutdown callback. This kept the timer
active, which prevented power savings and caused pointless noise in
virtualization.

- Encapsulate the open coded access to the hrtimer clock base, which is
a private implementation detail, so that the implementation can be
changed without breaking a lot of usage sites.

- Enhance the debug output of the clocksource watchdog to provide
better information for analysis.

- The usual set of cleanups and enhancements all over the place

* tag 'timers-core-2025-09-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
time: Fix spelling mistakes in comments
clocksource: Print durations for sync check unconditionally
LoongArch: Remove clockevents shutdown call on offlining
tick: Do not set device to detached state in tick_shutdown()
hrtimer: Reorder branches in hrtimer_clockid_to_base()
hrtimer: Remove hrtimer_clock_base:: Get_time
hrtimer: Use hrtimer_cb_get_time() helper
media: pwm-ir-tx: Avoid direct access to hrtimer clockbase
ALSA: hrtimer: Avoid direct access to hrtimer clockbase
lib: test_objpool: Avoid direct access to hrtimer clockbase
sched/core: Avoid direct access to hrtimer clockbase
timers/itimer: Avoid direct access to hrtimer clockbase
posix-timers: Avoid direct access to hrtimer clockbase
jiffies: Remove obsolete SHIFTED_HZ comment

+54 -62
-2
arch/loongarch/kernel/time.c
··· 112 112 113 113 static int arch_timer_dying(unsigned int cpu) 114 114 { 115 - constant_set_state_shutdown(this_cpu_ptr(&constant_clockevent_device)); 116 - 117 115 /* Clear Timer Interrupt */ 118 116 write_csr_tintclear(CSR_TINTCLR_TI); 119 117
+1 -4
drivers/media/rc/pwm-ir-tx.c
··· 117 117 static enum hrtimer_restart pwm_ir_timer(struct hrtimer *timer) 118 118 { 119 119 struct pwm_ir *pwm_ir = container_of(timer, struct pwm_ir, timer); 120 - ktime_t now; 121 120 122 121 /* 123 122 * If we happen to hit an odd latency spike, loop through the ··· 138 139 hrtimer_add_expires_ns(timer, ns); 139 140 140 141 pwm_ir->txbuf_index++; 141 - 142 - now = timer->base->get_time(); 143 - } while (hrtimer_get_expires_tv64(timer) < now); 142 + } while (hrtimer_expires_remaining(timer) > 0); 144 143 145 144 return HRTIMER_RESTART; 146 145 }
+5 -9
include/linux/hrtimer.h
··· 154 154 return ktime_to_ns(timer->node.expires); 155 155 } 156 156 157 + ktime_t hrtimer_cb_get_time(const struct hrtimer *timer); 158 + 157 159 static inline ktime_t hrtimer_expires_remaining(const struct hrtimer *timer) 158 160 { 159 - return ktime_sub(timer->node.expires, timer->base->get_time()); 160 - } 161 - 162 - static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer) 163 - { 164 - return timer->base->get_time(); 161 + return ktime_sub(timer->node.expires, hrtimer_cb_get_time(timer)); 165 162 } 166 163 167 164 static inline int hrtimer_is_hres_active(struct hrtimer *timer) ··· 197 200 static inline ktime_t 198 201 hrtimer_expires_remaining_adjusted(const struct hrtimer *timer) 199 202 { 200 - return __hrtimer_expires_remaining_adjusted(timer, 201 - timer->base->get_time()); 203 + return __hrtimer_expires_remaining_adjusted(timer, hrtimer_cb_get_time(timer)); 202 204 } 203 205 204 206 #ifdef CONFIG_TIMERFD ··· 359 363 static inline u64 hrtimer_forward_now(struct hrtimer *timer, 360 364 ktime_t interval) 361 365 { 362 - return hrtimer_forward(timer, timer->base->get_time(), interval); 366 + return hrtimer_forward(timer, hrtimer_cb_get_time(timer), interval); 363 367 } 364 368 365 369 /* Precise sleep: */
-2
include/linux/hrtimer_defs.h
··· 41 41 * @seq: seqcount around __run_hrtimer 42 42 * @running: pointer to the currently running hrtimer 43 43 * @active: red black tree root node for the active timers 44 - * @get_time: function to retrieve the current time of the clock 45 44 * @offset: offset of this clock to the monotonic base 46 45 */ 47 46 struct hrtimer_clock_base { ··· 50 51 seqcount_raw_spinlock_t seq; 51 52 struct hrtimer *running; 52 53 struct timerqueue_head active; 53 - ktime_t (*get_time)(void); 54 54 ktime_t offset; 55 55 } __hrtimer_clock_base_align; 56 56
+1 -1
include/linux/jiffies.h
··· 61 61 62 62 extern void register_refined_jiffies(long clock_tick_rate); 63 63 64 - /* TICK_USEC is the time between ticks in usec assuming SHIFTED_HZ */ 64 + /* TICK_USEC is the time between ticks in usec */ 65 65 #define TICK_USEC ((USEC_PER_SEC + HZ/2) / HZ) 66 66 67 67 /* USER_TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
+1 -1
include/vdso/jiffies.h
··· 5 5 #include <asm/param.h> /* for HZ */ 6 6 #include <vdso/time64.h> 7 7 8 - /* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */ 8 + /* TICK_NSEC is the time between ticks in nsec */ 9 9 #define TICK_NSEC ((NSEC_PER_SEC+HZ/2)/HZ) 10 10 11 11 #endif /* __VDSO_JIFFIES_H */
+1 -1
kernel/sched/core.c
··· 919 919 * doesn't make sense and can cause timer DoS. 920 920 */ 921 921 delta = max_t(s64, delay, 10000LL); 922 - rq->hrtick_time = ktime_add_ns(timer->base->get_time(), delta); 922 + rq->hrtick_time = ktime_add_ns(hrtimer_cb_get_time(timer), delta); 923 923 924 924 if (rq == this_rq()) 925 925 __hrtick_restart(rq);
+1 -1
kernel/time/alarmtimer.c
··· 35 35 36 36 /** 37 37 * struct alarm_base - Alarm timer bases 38 - * @lock: Lock for syncrhonized access to the base 38 + * @lock: Lock for synchronized access to the base 39 39 * @timerqueue: Timerqueue head managing the list of events 40 40 * @get_ktime: Function to read the time correlating to the base 41 41 * @get_timespec: Function to read the namespace time correlating to the base
+1 -1
kernel/time/clockevents.c
··· 633 633 raw_spin_lock(&clockevents_lock); 634 634 635 635 tick_broadcast_offline(cpu); 636 - tick_shutdown(cpu); 636 + tick_shutdown(); 637 637 638 638 /* 639 639 * Unregister the clock event devices which were
+3 -4
kernel/time/clocksource.c
··· 144 144 * Default for maximum permissible skew when cs->uncertainty_margin is 145 145 * not specified, and the lower bound even when cs->uncertainty_margin 146 146 * is specified. This is also the default that is used when registering 147 - * clocks with unspecifed cs->uncertainty_margin, so this macro is used 147 + * clocks with unspecified cs->uncertainty_margin, so this macro is used 148 148 * even in CONFIG_CLOCKSOURCE_WATCHDOG=n kernels. 149 149 */ 150 150 #define WATCHDOG_MAX_SKEW (MAX_SKEW_USEC * NSEC_PER_USEC) ··· 407 407 if (!cpumask_empty(&cpus_behind)) 408 408 pr_warn(" CPUs %*pbl behind CPU %d for clocksource %s.\n", 409 409 cpumask_pr_args(&cpus_behind), testcpu, cs->name); 410 - if (!cpumask_empty(&cpus_ahead) || !cpumask_empty(&cpus_behind)) 411 - pr_warn(" CPU %d check durations %lldns - %lldns for clocksource %s.\n", 412 - testcpu, cs_nsec_min, cs_nsec_max, cs->name); 410 + pr_info(" CPU %d check durations %lldns - %lldns for clocksource %s.\n", 411 + testcpu, cs_nsec_min, cs_nsec_max, cs->name); 413 412 } 414 413 EXPORT_SYMBOL_GPL(clocksource_verify_percpu); 415 414
+28 -12
kernel/time/hrtimer.c
··· 59 59 #define HRTIMER_ACTIVE_ALL (HRTIMER_ACTIVE_SOFT | HRTIMER_ACTIVE_HARD) 60 60 61 61 static void retrigger_next_event(void *arg); 62 + static ktime_t __hrtimer_cb_get_time(clockid_t clock_id); 62 63 63 64 /* 64 65 * The timer bases: ··· 77 76 { 78 77 .index = HRTIMER_BASE_MONOTONIC, 79 78 .clockid = CLOCK_MONOTONIC, 80 - .get_time = &ktime_get, 81 79 }, 82 80 { 83 81 .index = HRTIMER_BASE_REALTIME, 84 82 .clockid = CLOCK_REALTIME, 85 - .get_time = &ktime_get_real, 86 83 }, 87 84 { 88 85 .index = HRTIMER_BASE_BOOTTIME, 89 86 .clockid = CLOCK_BOOTTIME, 90 - .get_time = &ktime_get_boottime, 91 87 }, 92 88 { 93 89 .index = HRTIMER_BASE_TAI, 94 90 .clockid = CLOCK_TAI, 95 - .get_time = &ktime_get_clocktai, 96 91 }, 97 92 { 98 93 .index = HRTIMER_BASE_MONOTONIC_SOFT, 99 94 .clockid = CLOCK_MONOTONIC, 100 - .get_time = &ktime_get, 101 95 }, 102 96 { 103 97 .index = HRTIMER_BASE_REALTIME_SOFT, 104 98 .clockid = CLOCK_REALTIME, 105 - .get_time = &ktime_get_real, 106 99 }, 107 100 { 108 101 .index = HRTIMER_BASE_BOOTTIME_SOFT, 109 102 .clockid = CLOCK_BOOTTIME, 110 - .get_time = &ktime_get_boottime, 111 103 }, 112 104 { 113 105 .index = HRTIMER_BASE_TAI_SOFT, 114 106 .clockid = CLOCK_TAI, 115 - .get_time = &ktime_get_clocktai, 116 107 }, 117 108 }, 118 109 .csd = CSD_INIT(retrigger_next_event, NULL) ··· 201 208 /* 202 209 * The offline local CPU can't be the default target if the 203 210 * next remote target event is after this timer. Keep the 204 - * elected new base. An IPI will we issued to reprogram 211 + * elected new base. An IPI will be issued to reprogram 205 212 * it as a last resort. 206 213 */ 207 214 if (!hrtimer_base_is_online(this_cpu_base)) ··· 1246 1253 remove_hrtimer(timer, base, true, force_local); 1247 1254 1248 1255 if (mode & HRTIMER_MODE_REL) 1249 - tim = ktime_add_safe(tim, base->get_time()); 1256 + tim = ktime_add_safe(tim, __hrtimer_cb_get_time(base->clockid)); 1250 1257 1251 1258 tim = hrtimer_update_lowres(timer, tim, mode); 1252 1259 ··· 1567 1574 static inline int hrtimer_clockid_to_base(clockid_t clock_id) 1568 1575 { 1569 1576 switch (clock_id) { 1570 - case CLOCK_REALTIME: 1571 - return HRTIMER_BASE_REALTIME; 1572 1577 case CLOCK_MONOTONIC: 1573 1578 return HRTIMER_BASE_MONOTONIC; 1579 + case CLOCK_REALTIME: 1580 + return HRTIMER_BASE_REALTIME; 1574 1581 case CLOCK_BOOTTIME: 1575 1582 return HRTIMER_BASE_BOOTTIME; 1576 1583 case CLOCK_TAI: ··· 1580 1587 return HRTIMER_BASE_MONOTONIC; 1581 1588 } 1582 1589 } 1590 + 1591 + static ktime_t __hrtimer_cb_get_time(clockid_t clock_id) 1592 + { 1593 + switch (clock_id) { 1594 + case CLOCK_MONOTONIC: 1595 + return ktime_get(); 1596 + case CLOCK_REALTIME: 1597 + return ktime_get_real(); 1598 + case CLOCK_BOOTTIME: 1599 + return ktime_get_boottime(); 1600 + case CLOCK_TAI: 1601 + return ktime_get_clocktai(); 1602 + default: 1603 + WARN(1, "Invalid clockid %d. Using MONOTONIC\n", clock_id); 1604 + return ktime_get(); 1605 + } 1606 + } 1607 + 1608 + ktime_t hrtimer_cb_get_time(const struct hrtimer *timer) 1609 + { 1610 + return __hrtimer_cb_get_time(timer->base->clockid); 1611 + } 1612 + EXPORT_SYMBOL_GPL(hrtimer_cb_get_time); 1583 1613 1584 1614 static void __hrtimer_setup(struct hrtimer *timer, 1585 1615 enum hrtimer_restart (*function)(struct hrtimer *),
+1 -2
kernel/time/itimer.c
··· 163 163 struct hrtimer *tmr = &tsk->signal->real_timer; 164 164 165 165 if (!hrtimer_is_queued(tmr) && tsk->signal->it_real_incr != 0) { 166 - hrtimer_forward(tmr, tmr->base->get_time(), 167 - tsk->signal->it_real_incr); 166 + hrtimer_forward_now(tmr, tsk->signal->it_real_incr); 168 167 hrtimer_restart(tmr); 169 168 } 170 169 }
+3 -4
kernel/time/posix-timers.c
··· 299 299 { 300 300 struct hrtimer *timer = &timr->it.real.timer; 301 301 302 - timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(), 303 - timr->it_interval); 302 + timr->it_overrun += hrtimer_forward_now(timer, timr->it_interval); 304 303 hrtimer_restart(timer); 305 304 } 306 305 ··· 534 535 goto out; 535 536 } 536 537 /* 537 - * After succesful copy out, the timer ID is visible to user space 538 + * After successful copy out, the timer ID is visible to user space 538 539 * now but not yet valid because new_timer::signal low order bit is 1. 539 540 * 540 541 * Complete the initialization with the clock specific create ··· 824 825 hrtimer_setup(&timr->it.real.timer, posix_timer_fn, timr->it_clock, mode); 825 826 826 827 if (!absolute) 827 - expires = ktime_add_safe(expires, timer->base->get_time()); 828 + expires = ktime_add_safe(expires, hrtimer_cb_get_time(timer)); 828 829 hrtimer_set_expires(timer, expires); 829 830 830 831 if (!sigev_none)
+5 -11
kernel/time/tick-common.c
··· 411 411 } 412 412 413 413 /* 414 - * Shutdown an event device on a given cpu: 414 + * Shutdown an event device on the outgoing CPU: 415 415 * 416 - * This is called on a life CPU, when a CPU is dead. So we cannot 417 - * access the hardware device itself. 418 - * We just set the mode and remove it from the lists. 416 + * Called by the dying CPU during teardown, with clockevents_lock held 417 + * and interrupts disabled. 419 418 */ 420 - void tick_shutdown(unsigned int cpu) 419 + void tick_shutdown(void) 421 420 { 422 - struct tick_device *td = &per_cpu(tick_cpu_device, cpu); 421 + struct tick_device *td = this_cpu_ptr(&tick_cpu_device); 423 422 struct clock_event_device *dev = td->evtdev; 424 423 425 424 td->mode = TICKDEV_MODE_PERIODIC; 426 425 if (dev) { 427 - /* 428 - * Prevent that the clock events layer tries to call 429 - * the set mode function! 430 - */ 431 - clockevent_set_state(dev, CLOCK_EVT_STATE_DETACHED); 432 426 clockevents_exchange_device(dev, NULL); 433 427 dev->event_handler = clockevents_handle_noop; 434 428 td->evtdev = NULL;
+1 -1
kernel/time/tick-internal.h
··· 26 26 extern void tick_handle_periodic(struct clock_event_device *dev); 27 27 extern void tick_check_new_device(struct clock_event_device *dev); 28 28 extern void tick_offline_cpu(unsigned int cpu); 29 - extern void tick_shutdown(unsigned int cpu); 29 + extern void tick_shutdown(void); 30 30 extern void tick_suspend(void); 31 31 extern void tick_resume(void); 32 32 extern bool tick_check_replacement(struct clock_event_device *curdev,
-2
kernel/time/timer_list.c
··· 102 102 SEQ_printf(m, " .index: %d\n", base->index); 103 103 104 104 SEQ_printf(m, " .resolution: %u nsecs\n", hrtimer_resolution); 105 - 106 - SEQ_printf(m, " .get_time: %ps\n", base->get_time); 107 105 #ifdef CONFIG_HIGH_RES_TIMERS 108 106 SEQ_printf(m, " .offset: %Lu nsecs\n", 109 107 (unsigned long long) ktime_to_ns(base->offset));
+1 -1
lib/test_objpool.c
··· 164 164 /* do bulk-testings for objects pop/push */ 165 165 item->worker(item, 1); 166 166 167 - hrtimer_forward(hrt, hrt->base->get_time(), item->hrtcycle); 167 + hrtimer_forward_now(hrt, item->hrtcycle); 168 168 return HRTIMER_RESTART; 169 169 } 170 170
-2
scripts/gdb/linux/timerlist.py
··· 56 56 text += " .index: {}\n".format(base['index']) 57 57 58 58 text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution) 59 - 60 - text += " .get_time: {}\n".format(base['get_time']) 61 59 if constants.LX_CONFIG_HIGH_RES_TIMERS: 62 60 text += " .offset: {} nsecs\n".format(base['offset']) 63 61 text += "active timers:\n"
+1 -1
sound/core/hrtimer.c
··· 44 44 } 45 45 46 46 /* calculate the drift */ 47 - delta = ktime_sub(hrt->base->get_time(), hrtimer_get_expires(hrt)); 47 + delta = ktime_sub(hrtimer_cb_get_time(hrt), hrtimer_get_expires(hrt)); 48 48 if (delta > 0) 49 49 ticks += ktime_divns(delta, ticks * resolution); 50 50