mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
vdso/math64: Add and use __iter_div64_u64_rem()
The vDSO basetimes for CLOCK_MONOTONIC and CLOCK_BOOTTIME are stored in the scaled nanoseconds of tkr_mono, so normalising them requires a division by NSEC_PER_SEC << shift. That divisor does not fit the u32 parameter of __iter_div_u64_rem(), so update_vdso_time_data() open-codes the same iterative division twice. Repeated subtraction is the appropriate form at these two sites because the quotient never exceeds one. accumulate_nsecs_to_secs() keeps xtime_nsec below one scaled second, and the offset added to it is a normalised timespec64 fraction, so the dividend stays below twice the divisor. That bound holds on every architecture, which matters more here than the cost of a division on any particular one. Add __iter_div64_u64_rem(), the u64-divisor counterpart of __iter_div_u64_rem(), and use it at both sites. Return the quotient as a u32 for consistency with the u32-divisor variant; the bound above leaves no use for a wider type. Store the remainder directly into the basetime, as the coarse clocks already do. The CLOCK_BOOTTIME copy of the CLOCK_MONOTONIC values then takes both fields from the same place. Folding the two open-coded loops into one inlined helper removes 16 bytes of vsyscall.o text on x86-64 with gcc 13. No functional change. Suggested-by: David Laight <david.laight.linux@gmail.com> Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com> Signed-off-by: Thomas Gleixner <tglx@kernel.org> Reviewed-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de> Link: https://patch.msgid.link/20261002153104.1347978-3-zhanxusheng@xiaomi.com
This commit is contained in:
parent
c1b910b270
commit
dcd65074e2
|
|
@ -24,6 +24,26 @@ static __always_inline u32 __iter_div_u64_rem(u64 dividend, u32 divisor, u64 *re
|
|||
return ret;
|
||||
}
|
||||
|
||||
static __always_inline u32 __iter_div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
|
||||
{
|
||||
u32 ret = 0;
|
||||
|
||||
while (dividend >= divisor) {
|
||||
/*
|
||||
* Prevent the compiler from optimising this loop into a
|
||||
* modulo operation.
|
||||
*/
|
||||
OPTIMIZER_HIDE_VAR(dividend);
|
||||
|
||||
dividend -= divisor;
|
||||
ret++;
|
||||
}
|
||||
|
||||
*remainder = dividend;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
|
||||
|
||||
#ifndef mul_u64_u32_add_u64_shr
|
||||
|
|
|
|||
|
|
@ -54,14 +54,12 @@ static inline void update_vdso_time_data(struct vdso_time_data *vdata, struct ti
|
|||
|
||||
nsec = tk->tkr_mono.xtime_nsec;
|
||||
nsec += ((u64)tk->wall_to_monotonic.tv_nsec << tk->tkr_mono.shift);
|
||||
while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
|
||||
nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
|
||||
vdso_ts->sec++;
|
||||
}
|
||||
vdso_ts->nsec = nsec;
|
||||
vdso_ts->sec += __iter_div64_u64_rem(nsec, (u64)NSEC_PER_SEC << tk->tkr_mono.shift,
|
||||
&vdso_ts->nsec);
|
||||
|
||||
/* Copy MONOTONIC time for BOOTTIME */
|
||||
sec = vdso_ts->sec;
|
||||
nsec = vdso_ts->nsec;
|
||||
/* Add the boot offset */
|
||||
sec += tk->monotonic_to_boot.tv_sec;
|
||||
nsec += (u64)tk->monotonic_to_boot.tv_nsec << tk->tkr_mono.shift;
|
||||
|
|
@ -69,12 +67,8 @@ static inline void update_vdso_time_data(struct vdso_time_data *vdata, struct ti
|
|||
/* CLOCK_BOOTTIME */
|
||||
vdso_ts = &vc[CS_HRES_COARSE].basetime[CLOCK_BOOTTIME];
|
||||
vdso_ts->sec = sec;
|
||||
|
||||
while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
|
||||
nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
|
||||
vdso_ts->sec++;
|
||||
}
|
||||
vdso_ts->nsec = nsec;
|
||||
vdso_ts->sec += __iter_div64_u64_rem(nsec, (u64)NSEC_PER_SEC << tk->tkr_mono.shift,
|
||||
&vdso_ts->nsec);
|
||||
|
||||
/* CLOCK_MONOTONIC_RAW */
|
||||
vdso_ts = &vc[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user