kern_tc.c/cputick2usec()

(which is used to calculate cputime from cpu ticks) has some imprecision and,
worse, huge timestep (about 20 minutes on 4GHz CPU) near 53.4 days of elapsed
time.

kern_time.c/cputick2timespec() (it is used for clock_gettime() for
querying process or thread consumed cpu time) Uses cputick2usec()
and then needlessly converting usec to nsec, obviously losing
precision even with fixed cputick2usec().

kern_time.c/kern_clock_getres() uses some weird (anyway wrong)
formula for getting cputick resolution.

PR:		262215
Reviewed by:	gnn
Differential Revision:	https://reviews.freebsd.org/D34558
This commit is contained in:
firk
2022-03-21 09:33:11 -04:00
committed by Sebastian Huber
parent 3612dc7d61
commit 0c36cb6101

View File

@@ -2617,20 +2617,14 @@ cpu_tickrate(void)
* years) and in 64 bits at 4 GHz (146 years), but if we do a multiply * years) and in 64 bits at 4 GHz (146 years), but if we do a multiply
* before divide conversion (to retain precision) we find that the * before divide conversion (to retain precision) we find that the
* margin shrinks to 1.5 hours (one millionth of 146y). * margin shrinks to 1.5 hours (one millionth of 146y).
* With a three prong approach we never lose significant bits, no
* matter what the cputick rate and length of timeinterval is.
*/ */
uint64_t uint64_t
cputick2usec(uint64_t tick) cputick2usec(uint64_t tick)
{ {
uint64_t tr;
if (tick > 18446744073709551LL) /* floor(2^64 / 1000) */ tr = cpu_tickrate();
return (tick / (cpu_tickrate() / 1000000LL)); return ((tick / tr) * 1000000ULL) + ((tick % tr) * 1000000ULL) / tr;
else if (tick > 18446744073709LL) /* floor(2^64 / 1000000) */
return ((tick * 1000LL) / (cpu_tickrate() / 1000LL));
else
return ((tick * 1000000LL) / cpu_tickrate());
} }
cpu_tick_f *cpu_ticks = tc_cpu_ticks; cpu_tick_f *cpu_ticks = tc_cpu_ticks;