libkvm: fix process runtime calculation on crashdumps

Fix a long standing bug, where the procs ticks where assumed to be in
us. Instead, read cpu_tick_frequency from the kernel and use the same
logic to convert runtime. This is still too optimistic in that it
assumes cpu_tick_frequency is available and fixed. Since this function
is only called on crashdumps, I think we can live with that. Testing has
shown the values to be correct for different kern.hz inside Virtualbox.

Bump WARNS. Alignment issues on some archs mean this is still at 3.

Reviewed by:	bde
This commit is contained in:
Ulrich Spörlein 2011-01-23 11:08:36 +00:00
parent c10970dd7d
commit de788839e2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=217745
2 changed files with 29 additions and 13 deletions

View File

@ -15,7 +15,7 @@ KVM_ARCH=${MACHINE_ARCH}
KVM_ARCH=${MACHINE_CPUARCH}
.endif
WARNS?= 0
WARNS?= 3
SRCS= kvm.c kvm_${KVM_ARCH}.c kvm_cptime.c kvm_file.c kvm_getloadavg.c \
kvm_getswapinfo.c kvm_pcpu.c kvm_proc.c kvm_vnet.c

View File

@ -88,6 +88,25 @@ __FBSDID("$FreeBSD$");
static int ticks;
static int hz;
static uint64_t cpu_tick_frequency;
/*
* From sys/kern/kern_tc.c. Depends on cpu_tick_frequency, which is
* read/initialized before this function is ever called.
*/
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);
}
/*
* Read proc's from memory file into buffer bp, which has space to hold
@ -113,7 +132,6 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
struct thread mtd;
struct proc proc;
struct proc pproc;
struct timeval tv;
struct sysentvec sysent;
char svname[KI_EMULNAMELEN];
@ -367,15 +385,7 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
kp->ki_lockname, LOCKNAMELEN);
kp->ki_lockname[LOCKNAMELEN] = 0;
}
/*
* XXX: This is plain wrong, rux_runtime has nothing
* to do with struct bintime, rux_runtime is just a 64-bit
* integer counter of cputicks. What we need here is a way
* to convert cputicks to usecs. The kernel does it in
* kern/kern_tc.c, but the function can't be just copied.
*/
bintime2timeval(&proc.p_rux.rux_runtime, &tv);
kp->ki_runtime = (u_int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
kp->ki_runtime = cputick2usec(proc.p_rux.rux_runtime);
kp->ki_pid = proc.p_pid;
kp->ki_siglist = proc.p_siglist;
SIGSETOR(kp->ki_siglist, mtd.td_siglist);
@ -542,14 +552,15 @@ kvm_getprocs(kvm_t *kd, int op, int arg, int *cnt)
liveout:
nprocs = size == 0 ? 0 : size / kd->procbase->ki_structsize;
} else {
struct nlist nl[6], *p;
struct nlist nl[7], *p;
nl[0].n_name = "_nprocs";
nl[1].n_name = "_allproc";
nl[2].n_name = "_zombproc";
nl[3].n_name = "_ticks";
nl[4].n_name = "_hz";
nl[5].n_name = 0;
nl[5].n_name = "_cpu_tick_frequency";
nl[6].n_name = 0;
if (kvm_nlist(kd, nl) != 0) {
for (p = nl; p->n_type != 0; ++p)
@ -570,6 +581,11 @@ kvm_getprocs(kvm_t *kd, int op, int arg, int *cnt)
_kvm_err(kd, kd->program, "can't read hz");
return (0);
}
if (KREAD(kd, nl[5].n_value, &cpu_tick_frequency)) {
_kvm_err(kd, kd->program,
"can't read cpu_tick_frequency");
return (0);
}
size = nprocs * sizeof(struct kinfo_proc);
kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size);
if (kd->procbase == 0)