mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 21:05:08 +00:00
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:
parent
cab496e16c
commit
bb53dd56c3
|
@ -94,15 +94,10 @@ static uint64_t cpu_tick_frequency;
|
|||
static uint64_t
|
||||
cputick2usec(uint64_t tick)
|
||||
{
|
||||
|
||||
if (cpu_tick_frequency == 0)
|
||||
return (0);
|
||||
if (tick > 18446744073709551) /* floor(2^64 / 1000) */
|
||||
return (tick / (cpu_tick_frequency / 1000000));
|
||||
else if (tick > 18446744073709) /* floor(2^64 / 1000000) */
|
||||
return ((tick * 1000) / (cpu_tick_frequency / 1000));
|
||||
else
|
||||
return ((tick * 1000000) / cpu_tick_frequency);
|
||||
return ((tick / cpu_tick_frequency) * 1000000ULL) +
|
||||
((tick % cpu_tick_frequency) * 1000000ULL) / cpu_tick_frequency;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2155,20 +2155,14 @@ cpu_tickrate(void)
|
|||
* 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
|
||||
* 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
|
||||
cputick2usec(uint64_t tick)
|
||||
{
|
||||
|
||||
if (tick > 18446744073709551LL) /* floor(2^64 / 1000) */
|
||||
return (tick / (cpu_tickrate() / 1000000LL));
|
||||
else if (tick > 18446744073709LL) /* floor(2^64 / 1000000) */
|
||||
return ((tick * 1000LL) / (cpu_tickrate() / 1000LL));
|
||||
else
|
||||
return ((tick * 1000000LL) / cpu_tickrate());
|
||||
uint64_t tr;
|
||||
tr = cpu_tickrate();
|
||||
return ((tick / tr) * 1000000ULL) + ((tick % tr) * 1000000ULL) / tr;
|
||||
}
|
||||
|
||||
cpu_tick_f *cpu_ticks = tc_cpu_ticks;
|
||||
|
|
|
@ -245,9 +245,10 @@ sys_clock_gettime(struct thread *td, struct clock_gettime_args *uap)
|
|||
static inline void
|
||||
cputick2timespec(uint64_t runtime, struct timespec *ats)
|
||||
{
|
||||
runtime = cputick2usec(runtime);
|
||||
ats->tv_sec = runtime / 1000000;
|
||||
ats->tv_nsec = runtime % 1000000 * 1000;
|
||||
uint64_t tr;
|
||||
tr = cpu_tickrate();
|
||||
ats->tv_sec = runtime / tr;
|
||||
ats->tv_nsec = ((runtime % tr) * 1000000000ULL) / tr;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -477,10 +478,7 @@ kern_clock_getres(struct thread *td, clockid_t clock_id, struct timespec *ts)
|
|||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
case CLOCK_PROCESS_CPUTIME_ID:
|
||||
cputime:
|
||||
/* sync with cputick2usec */
|
||||
ts->tv_nsec = 1000000 / cpu_tickrate();
|
||||
if (ts->tv_nsec == 0)
|
||||
ts->tv_nsec = 1000;
|
||||
ts->tv_nsec = 1000000000 / cpu_tickrate() + 1;
|
||||
break;
|
||||
default:
|
||||
if ((int)clock_id < 0)
|
||||
|
|
Loading…
Reference in a new issue