Skip to content

Commit 353a7e8

Browse files
committed
Merge tag 'timers-core-2026-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer core updates from Thomas Gleixner: - Inline timecounter_cyc2time() as that is now used in the networking hotpath. Inlining it significantly improves performance. - Optimize the tick dependency check in case that the tracepoint is disabled, which improves the hotpath performance in the tick management code, which is a hotpath on transitions in and out of idle. - The usual cleanups and improvements * tag 'timers-core-2026-02-09' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: time/kunit: Document handling of negative years of is_leap() tick/nohz: Optimize check_tick_dependency() with early return time/sched_clock: Use ACCESS_PRIVATE() to evaluate hrtimer::function hrtimer: Drop _tv64() helpers hrtimer: Remove public definition of HIGH_RES_NSEC hrtimer: Remove unused resolution constants time/timecounter: Inline timecounter_cyc2time()
2 parents 48295ab + 2498933 commit 353a7e8

8 files changed

Lines changed: 47 additions & 77 deletions

File tree

include/linux/hrtimer.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,6 @@ static inline void hrtimer_set_expires_range_ns(struct hrtimer *timer, ktime_t t
112112
timer->node.expires = ktime_add_safe(time, ns_to_ktime(delta));
113113
}
114114

115-
static inline void hrtimer_set_expires_tv64(struct hrtimer *timer, s64 tv64)
116-
{
117-
timer->node.expires = tv64;
118-
timer->_softexpires = tv64;
119-
}
120-
121115
static inline void hrtimer_add_expires(struct hrtimer *timer, ktime_t time)
122116
{
123117
timer->node.expires = ktime_add_safe(timer->node.expires, time);
@@ -140,15 +134,6 @@ static inline ktime_t hrtimer_get_softexpires(const struct hrtimer *timer)
140134
return timer->_softexpires;
141135
}
142136

143-
static inline s64 hrtimer_get_expires_tv64(const struct hrtimer *timer)
144-
{
145-
return timer->node.expires;
146-
}
147-
static inline s64 hrtimer_get_softexpires_tv64(const struct hrtimer *timer)
148-
{
149-
return timer->_softexpires;
150-
}
151-
152137
static inline s64 hrtimer_get_expires_ns(const struct hrtimer *timer)
153138
{
154139
return ktime_to_ns(timer->node.expires);

include/linux/hrtimer_defs.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,6 @@
66
#include <linux/timerqueue.h>
77
#include <linux/seqlock.h>
88

9-
#ifdef CONFIG_HIGH_RES_TIMERS
10-
11-
/*
12-
* The resolution of the clocks. The resolution value is returned in
13-
* the clock_getres() system call to give application programmers an
14-
* idea of the (in)accuracy of timers. Timer values are rounded up to
15-
* this resolution values.
16-
*/
17-
# define HIGH_RES_NSEC 1
18-
# define KTIME_HIGH_RES (HIGH_RES_NSEC)
19-
# define MONOTONIC_RES_NSEC HIGH_RES_NSEC
20-
# define KTIME_MONOTONIC_RES KTIME_HIGH_RES
21-
22-
#else
23-
24-
# define MONOTONIC_RES_NSEC LOW_RES_NSEC
25-
# define KTIME_MONOTONIC_RES KTIME_LOW_RES
26-
27-
#endif
28-
299
#ifdef CONFIG_64BIT
3010
# define __hrtimer_clock_base_align ____cacheline_aligned
3111
#else

include/linux/timecounter.h

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,15 @@ extern void timecounter_init(struct timecounter *tc,
115115
*/
116116
extern u64 timecounter_read(struct timecounter *tc);
117117

118+
/*
119+
* This is like cyclecounter_cyc2ns(), but it is used for computing a
120+
* time previous to the time stored in the cycle counter.
121+
*/
122+
static inline u64 cc_cyc2ns_backwards(const struct cyclecounter *cc, u64 cycles, u64 frac)
123+
{
124+
return ((cycles * cc->mult) - frac) >> cc->shift;
125+
}
126+
118127
/**
119128
* timecounter_cyc2time - convert a cycle counter to same
120129
* time base as values returned by
@@ -131,7 +140,25 @@ extern u64 timecounter_read(struct timecounter *tc);
131140
*
132141
* Returns: cycle counter converted to nanoseconds since the initial time stamp
133142
*/
134-
extern u64 timecounter_cyc2time(const struct timecounter *tc,
135-
u64 cycle_tstamp);
143+
static inline u64 timecounter_cyc2time(const struct timecounter *tc, u64 cycle_tstamp)
144+
{
145+
const struct cyclecounter *cc = tc->cc;
146+
u64 delta = (cycle_tstamp - tc->cycle_last) & cc->mask;
147+
u64 nsec = tc->nsec, frac = tc->frac;
148+
149+
/*
150+
* Instead of always treating cycle_tstamp as more recent than
151+
* tc->cycle_last, detect when it is too far in the future and
152+
* treat it as old time stamp instead.
153+
*/
154+
if (unlikely(delta > cc->mask / 2)) {
155+
delta = (tc->cycle_last - cycle_tstamp) & cc->mask;
156+
nsec -= cc_cyc2ns_backwards(cc, delta, frac);
157+
} else {
158+
nsec += cyclecounter_cyc2ns(cc, delta, tc->mask, &frac);
159+
}
160+
161+
return nsec;
162+
}
136163

137164
#endif

kernel/time/hrtimer.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@
4949

5050
#include "tick-internal.h"
5151

52+
/*
53+
* The resolution of the clocks. The resolution value is returned in
54+
* the clock_getres() system call to give application programmers an
55+
* idea of the (in)accuracy of timers. Timer values are rounded up to
56+
* this resolution values.
57+
*/
58+
#define HIGH_RES_NSEC 1
59+
5260
/*
5361
* Masks for selecting the soft and hard context timers from
5462
* cpu_base->active
@@ -806,7 +814,7 @@ static void hrtimer_reprogram(struct hrtimer *timer, bool reprogram)
806814
struct hrtimer_clock_base *base = timer->base;
807815
ktime_t expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
808816

809-
WARN_ON_ONCE(hrtimer_get_expires_tv64(timer) < 0);
817+
WARN_ON_ONCE(hrtimer_get_expires(timer) < 0);
810818

811819
/*
812820
* CLOCK_REALTIME timer might be requested with an absolute
@@ -1053,7 +1061,7 @@ u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
10531061

10541062
orun = ktime_divns(delta, incr);
10551063
hrtimer_add_expires_ns(timer, incr * orun);
1056-
if (hrtimer_get_expires_tv64(timer) > now)
1064+
if (hrtimer_get_expires(timer) > now)
10571065
return orun;
10581066
/*
10591067
* This (and the ktime_add() below) is the
@@ -1835,7 +1843,7 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now,
18351843
* are right-of a not yet expired timer, because that
18361844
* timer will have to trigger a wakeup anyway.
18371845
*/
1838-
if (basenow < hrtimer_get_softexpires_tv64(timer))
1846+
if (basenow < hrtimer_get_softexpires(timer))
18391847
break;
18401848

18411849
__run_hrtimer(cpu_base, base, timer, &basenow, flags);

kernel/time/sched_clock.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ void sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
215215

216216
update_clock_read_data(&rd);
217217

218-
if (sched_clock_timer.function != NULL) {
218+
if (ACCESS_PRIVATE(&sched_clock_timer, function) != NULL) {
219219
/* update timeout for clock wrap */
220220
hrtimer_start(&sched_clock_timer, cd.wrap_kt,
221221
HRTIMER_MODE_REL_HARD);

kernel/time/tick-sched.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,9 @@ static bool check_tick_dependency(atomic_t *dep)
344344
{
345345
int val = atomic_read(dep);
346346

347+
if (likely(!tracepoint_enabled(tick_stop)))
348+
return !val;
349+
347350
if (val & TICK_DEP_MASK_POSIX_TIMER) {
348351
trace_tick_stop(0, TICK_DEP_MASK_POSIX_TIMER);
349352
return true;

kernel/time/time_test.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
#include <linux/time.h>
55

66
/*
7-
* Traditional implementation of leap year evaluation.
7+
* Traditional implementation of leap year evaluation, but note that long
8+
* is a signed type and the tests do cover negative year values. So this
9+
* can't use the is_leap_year() helper from rtc.h.
810
*/
911
static bool is_leap(long year)
1012
{

kernel/time/timecounter.c

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -62,38 +62,3 @@ u64 timecounter_read(struct timecounter *tc)
6262
}
6363
EXPORT_SYMBOL_GPL(timecounter_read);
6464

65-
/*
66-
* This is like cyclecounter_cyc2ns(), but it is used for computing a
67-
* time previous to the time stored in the cycle counter.
68-
*/
69-
static u64 cc_cyc2ns_backwards(const struct cyclecounter *cc,
70-
u64 cycles, u64 mask, u64 frac)
71-
{
72-
u64 ns = (u64) cycles;
73-
74-
ns = ((ns * cc->mult) - frac) >> cc->shift;
75-
76-
return ns;
77-
}
78-
79-
u64 timecounter_cyc2time(const struct timecounter *tc,
80-
u64 cycle_tstamp)
81-
{
82-
u64 delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
83-
u64 nsec = tc->nsec, frac = tc->frac;
84-
85-
/*
86-
* Instead of always treating cycle_tstamp as more recent
87-
* than tc->cycle_last, detect when it is too far in the
88-
* future and treat it as old time stamp instead.
89-
*/
90-
if (delta > tc->cc->mask / 2) {
91-
delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
92-
nsec -= cc_cyc2ns_backwards(tc->cc, delta, tc->mask, frac);
93-
} else {
94-
nsec += cyclecounter_cyc2ns(tc->cc, delta, tc->mask, &frac);
95-
}
96-
97-
return nsec;
98-
}
99-
EXPORT_SYMBOL_GPL(timecounter_cyc2time);

0 commit comments

Comments
 (0)