mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
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()
This commit is contained in:
@@ -112,12 +112,6 @@ static inline void hrtimer_set_expires_range_ns(struct hrtimer *timer, ktime_t t
|
||||
timer->node.expires = ktime_add_safe(time, ns_to_ktime(delta));
|
||||
}
|
||||
|
||||
static inline void hrtimer_set_expires_tv64(struct hrtimer *timer, s64 tv64)
|
||||
{
|
||||
timer->node.expires = tv64;
|
||||
timer->_softexpires = tv64;
|
||||
}
|
||||
|
||||
static inline void hrtimer_add_expires(struct hrtimer *timer, ktime_t time)
|
||||
{
|
||||
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)
|
||||
return timer->_softexpires;
|
||||
}
|
||||
|
||||
static inline s64 hrtimer_get_expires_tv64(const struct hrtimer *timer)
|
||||
{
|
||||
return timer->node.expires;
|
||||
}
|
||||
static inline s64 hrtimer_get_softexpires_tv64(const struct hrtimer *timer)
|
||||
{
|
||||
return timer->_softexpires;
|
||||
}
|
||||
|
||||
static inline s64 hrtimer_get_expires_ns(const struct hrtimer *timer)
|
||||
{
|
||||
return ktime_to_ns(timer->node.expires);
|
||||
|
||||
@@ -6,26 +6,6 @@
|
||||
#include <linux/timerqueue.h>
|
||||
#include <linux/seqlock.h>
|
||||
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
|
||||
/*
|
||||
* The resolution of the clocks. The resolution value is returned in
|
||||
* the clock_getres() system call to give application programmers an
|
||||
* idea of the (in)accuracy of timers. Timer values are rounded up to
|
||||
* this resolution values.
|
||||
*/
|
||||
# define HIGH_RES_NSEC 1
|
||||
# define KTIME_HIGH_RES (HIGH_RES_NSEC)
|
||||
# define MONOTONIC_RES_NSEC HIGH_RES_NSEC
|
||||
# define KTIME_MONOTONIC_RES KTIME_HIGH_RES
|
||||
|
||||
#else
|
||||
|
||||
# define MONOTONIC_RES_NSEC LOW_RES_NSEC
|
||||
# define KTIME_MONOTONIC_RES KTIME_LOW_RES
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
# define __hrtimer_clock_base_align ____cacheline_aligned
|
||||
#else
|
||||
|
||||
@@ -115,6 +115,15 @@ extern void timecounter_init(struct timecounter *tc,
|
||||
*/
|
||||
extern u64 timecounter_read(struct timecounter *tc);
|
||||
|
||||
/*
|
||||
* This is like cyclecounter_cyc2ns(), but it is used for computing a
|
||||
* time previous to the time stored in the cycle counter.
|
||||
*/
|
||||
static inline u64 cc_cyc2ns_backwards(const struct cyclecounter *cc, u64 cycles, u64 frac)
|
||||
{
|
||||
return ((cycles * cc->mult) - frac) >> cc->shift;
|
||||
}
|
||||
|
||||
/**
|
||||
* timecounter_cyc2time - convert a cycle counter to same
|
||||
* time base as values returned by
|
||||
@@ -131,7 +140,25 @@ extern u64 timecounter_read(struct timecounter *tc);
|
||||
*
|
||||
* Returns: cycle counter converted to nanoseconds since the initial time stamp
|
||||
*/
|
||||
extern u64 timecounter_cyc2time(const struct timecounter *tc,
|
||||
u64 cycle_tstamp);
|
||||
static inline u64 timecounter_cyc2time(const struct timecounter *tc, u64 cycle_tstamp)
|
||||
{
|
||||
const struct cyclecounter *cc = tc->cc;
|
||||
u64 delta = (cycle_tstamp - tc->cycle_last) & cc->mask;
|
||||
u64 nsec = tc->nsec, frac = tc->frac;
|
||||
|
||||
/*
|
||||
* Instead of always treating cycle_tstamp as more recent than
|
||||
* tc->cycle_last, detect when it is too far in the future and
|
||||
* treat it as old time stamp instead.
|
||||
*/
|
||||
if (unlikely(delta > cc->mask / 2)) {
|
||||
delta = (tc->cycle_last - cycle_tstamp) & cc->mask;
|
||||
nsec -= cc_cyc2ns_backwards(cc, delta, frac);
|
||||
} else {
|
||||
nsec += cyclecounter_cyc2ns(cc, delta, tc->mask, &frac);
|
||||
}
|
||||
|
||||
return nsec;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,6 +49,14 @@
|
||||
|
||||
#include "tick-internal.h"
|
||||
|
||||
/*
|
||||
* The resolution of the clocks. The resolution value is returned in
|
||||
* the clock_getres() system call to give application programmers an
|
||||
* idea of the (in)accuracy of timers. Timer values are rounded up to
|
||||
* this resolution values.
|
||||
*/
|
||||
#define HIGH_RES_NSEC 1
|
||||
|
||||
/*
|
||||
* Masks for selecting the soft and hard context timers from
|
||||
* cpu_base->active
|
||||
@@ -806,7 +814,7 @@ static void hrtimer_reprogram(struct hrtimer *timer, bool reprogram)
|
||||
struct hrtimer_clock_base *base = timer->base;
|
||||
ktime_t expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
|
||||
|
||||
WARN_ON_ONCE(hrtimer_get_expires_tv64(timer) < 0);
|
||||
WARN_ON_ONCE(hrtimer_get_expires(timer) < 0);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
orun = ktime_divns(delta, incr);
|
||||
hrtimer_add_expires_ns(timer, incr * orun);
|
||||
if (hrtimer_get_expires_tv64(timer) > now)
|
||||
if (hrtimer_get_expires(timer) > now)
|
||||
return orun;
|
||||
/*
|
||||
* 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,
|
||||
* are right-of a not yet expired timer, because that
|
||||
* timer will have to trigger a wakeup anyway.
|
||||
*/
|
||||
if (basenow < hrtimer_get_softexpires_tv64(timer))
|
||||
if (basenow < hrtimer_get_softexpires(timer))
|
||||
break;
|
||||
|
||||
__run_hrtimer(cpu_base, base, timer, &basenow, flags);
|
||||
|
||||
@@ -215,7 +215,7 @@ void sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
|
||||
|
||||
update_clock_read_data(&rd);
|
||||
|
||||
if (sched_clock_timer.function != NULL) {
|
||||
if (ACCESS_PRIVATE(&sched_clock_timer, function) != NULL) {
|
||||
/* update timeout for clock wrap */
|
||||
hrtimer_start(&sched_clock_timer, cd.wrap_kt,
|
||||
HRTIMER_MODE_REL_HARD);
|
||||
|
||||
@@ -344,6 +344,9 @@ static bool check_tick_dependency(atomic_t *dep)
|
||||
{
|
||||
int val = atomic_read(dep);
|
||||
|
||||
if (likely(!tracepoint_enabled(tick_stop)))
|
||||
return !val;
|
||||
|
||||
if (val & TICK_DEP_MASK_POSIX_TIMER) {
|
||||
trace_tick_stop(0, TICK_DEP_MASK_POSIX_TIMER);
|
||||
return true;
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
#include <linux/time.h>
|
||||
|
||||
/*
|
||||
* Traditional implementation of leap year evaluation.
|
||||
* Traditional implementation of leap year evaluation, but note that long
|
||||
* is a signed type and the tests do cover negative year values. So this
|
||||
* can't use the is_leap_year() helper from rtc.h.
|
||||
*/
|
||||
static bool is_leap(long year)
|
||||
{
|
||||
|
||||
@@ -62,38 +62,3 @@ u64 timecounter_read(struct timecounter *tc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timecounter_read);
|
||||
|
||||
/*
|
||||
* This is like cyclecounter_cyc2ns(), but it is used for computing a
|
||||
* time previous to the time stored in the cycle counter.
|
||||
*/
|
||||
static u64 cc_cyc2ns_backwards(const struct cyclecounter *cc,
|
||||
u64 cycles, u64 mask, u64 frac)
|
||||
{
|
||||
u64 ns = (u64) cycles;
|
||||
|
||||
ns = ((ns * cc->mult) - frac) >> cc->shift;
|
||||
|
||||
return ns;
|
||||
}
|
||||
|
||||
u64 timecounter_cyc2time(const struct timecounter *tc,
|
||||
u64 cycle_tstamp)
|
||||
{
|
||||
u64 delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
|
||||
u64 nsec = tc->nsec, frac = tc->frac;
|
||||
|
||||
/*
|
||||
* Instead of always treating cycle_tstamp as more recent
|
||||
* than tc->cycle_last, detect when it is too far in the
|
||||
* future and treat it as old time stamp instead.
|
||||
*/
|
||||
if (delta > tc->cc->mask / 2) {
|
||||
delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
|
||||
nsec -= cc_cyc2ns_backwards(tc->cc, delta, tc->mask, frac);
|
||||
} else {
|
||||
nsec += cyclecounter_cyc2ns(tc->cc, delta, tc->mask, &frac);
|
||||
}
|
||||
|
||||
return nsec;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timecounter_cyc2time);
|
||||
|
||||
Reference in New Issue
Block a user