Add a new routine kvm_getcptime(3) for fetching the equivalent of
'kern.cp_time'. For a live kernel it uses the sysctl. For a crashdump, it first checks to see if the kernel has a 'cp_time' global symbol. If it does, it uses that. If that doesn't work, when it uses the recently added kvm_getmaxcpu(3) and kvm_getpcpu(3) routines to walk all the CPUs and sum up their counters. MFC after: 1 week
This commit is contained in:
parent
10e058a3a2
commit
67b02c52de
@ -9,15 +9,16 @@ CFLAGS+=-DLIBC_SCCS -I${.CURDIR}
|
||||
CFLAGS+=-DSUN4V
|
||||
.endif
|
||||
|
||||
SRCS= kvm.c kvm_${MACHINE_ARCH}.c kvm_file.c kvm_getloadavg.c \
|
||||
SRCS= kvm.c kvm_${MACHINE_ARCH}.c kvm_cptime.c kvm_file.c kvm_getloadavg.c \
|
||||
kvm_getswapinfo.c kvm_pcpu.c kvm_proc.c
|
||||
.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"
|
||||
SRCS+= kvm_minidump_${MACHINE_ARCH}.c
|
||||
.endif
|
||||
INCS= kvm.h
|
||||
|
||||
MAN= kvm.3 kvm_geterr.3 kvm_getfiles.3 kvm_getloadavg.3 kvm_getpcpu.3 \
|
||||
kvm_getprocs.3 kvm_getswapinfo.3 kvm_nlist.3 kvm_open.3
|
||||
MAN= kvm.3 kvm_getcptime.3 kvm_geterr.3 kvm_getfiles.3 kvm_getloadavg.3 \
|
||||
kvm_getpcpu.3 kvm_getprocs.3 kvm_getswapinfo.3 kvm_nlist.3 kvm_open.3 \
|
||||
kvm_read.3
|
||||
|
||||
MLINKS+=kvm_getpcpu.3 kvm_getmaxcpu.3
|
||||
MLINKS+=kvm_getprocs.3 kvm_getargv.3 kvm_getprocs.3 kvm_getenvv.3
|
||||
|
@ -70,6 +70,7 @@ struct kvm_swap {
|
||||
__BEGIN_DECLS
|
||||
int kvm_close(kvm_t *);
|
||||
char **kvm_getargv(kvm_t *, const struct kinfo_proc *, int);
|
||||
int kvm_getcptime(kvm_t *, long *);
|
||||
char **kvm_getenvv(kvm_t *, const struct kinfo_proc *, int);
|
||||
char *kvm_geterr(kvm_t *);
|
||||
char *kvm_getfiles(kvm_t *, int, int, int *);
|
||||
|
132
lib/libkvm/kvm_cptime.c
Normal file
132
lib/libkvm/kvm_cptime.c
Normal file
@ -0,0 +1,132 @@
|
||||
/*-
|
||||
* Copyright (c) 2008 Yahoo!, Inc.
|
||||
* All rights reserved.
|
||||
* Written by: John Baldwin <jhb@FreeBSD.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/pcpu.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <errno.h>
|
||||
#include <kvm.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "kvm_private.h"
|
||||
|
||||
static struct nlist kvm_cp_time_nl[] = {
|
||||
{ "_cp_time" }, /* (deprecated) */
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
#define NL_CP_TIME 0
|
||||
|
||||
static int kvm_cp_time_cached;
|
||||
|
||||
static int
|
||||
_kvm_cp_time_init(kvm_t *kd)
|
||||
{
|
||||
|
||||
if (kvm_nlist(kd, kvm_cp_time_nl) < 0)
|
||||
return (-1);
|
||||
kvm_cp_time_cached = 1;
|
||||
}
|
||||
|
||||
static int
|
||||
getsysctl(kvm_t *kd, const char *name, void *buf, size_t len)
|
||||
{
|
||||
size_t nlen;
|
||||
|
||||
nlen = len;
|
||||
if (sysctlbyname(name, buf, &nlen, NULL, 0) < 0) {
|
||||
_kvm_err(kd, kd->program, "cannot read sysctl %s:%s", name,
|
||||
strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
if (nlen != len) {
|
||||
_kvm_err(kd, kd->program, "sysctl %s has unexpected size",
|
||||
name);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
kvm_getcptime(kvm_t *kd, long *cp_time)
|
||||
{
|
||||
struct pcpu *pc;
|
||||
int i, j, maxcpu;
|
||||
|
||||
if (kd == NULL) {
|
||||
kvm_cp_time_cached = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (ISALIVE(kd))
|
||||
return (getsysctl(kd, "kern.cp_time", cp_time, sizeof(long) *
|
||||
CPUSTATES));
|
||||
|
||||
if (kvm_cp_time_cached == 0) {
|
||||
if (_kvm_cp_time_init(kd) < 0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* If this kernel has a "cp_time[]" symbol, then just read that. */
|
||||
if (kvm_cp_time_nl[NL_CP_TIME].n_value != 0) {
|
||||
if (kvm_read(kd, kvm_cp_time_nl[NL_CP_TIME].n_value, cp_time,
|
||||
sizeof(long) * CPUSTATES) != sizeof(long) * CPUSTATES) {
|
||||
_kvm_err(kd, kd->program, "cannot read cp_time array");
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we don't have that symbol, then we have to simulate
|
||||
* "cp_time[]" by adding up the individual times for each CPU.
|
||||
*/
|
||||
maxcpu = kvm_getmaxcpu(kd);
|
||||
if (maxcpu < 0)
|
||||
return (-1);
|
||||
for (i = 0; i < CPUSTATES; i++)
|
||||
cp_time[i] = 0;
|
||||
for (i = 0; i < maxcpu; i++) {
|
||||
pc = kvm_getpcpu(kd, i);
|
||||
if (pc == NULL)
|
||||
continue;
|
||||
if (pc == (void *)-1)
|
||||
return (-1);
|
||||
for (j = 0; j < CPUSTATES; j++)
|
||||
cp_time[j] += pc->pc_cp_time[j];
|
||||
free(pc);
|
||||
}
|
||||
return (0);
|
||||
}
|
77
lib/libkvm/kvm_getcptime.3
Normal file
77
lib/libkvm/kvm_getcptime.3
Normal file
@ -0,0 +1,77 @@
|
||||
.\" Copyright (c) 2008 Yahoo!, Inc.
|
||||
.\" All rights reserved.
|
||||
.\" Written by: John Baldwin <jhb@FreeBSD.org>
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the author nor the names of any co-contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 19, 2008
|
||||
.Dt KVM_GETCPTIME 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm kvm_getcptime
|
||||
.Nd fetch global CPU time statistics
|
||||
.Sh LIBRARY
|
||||
.Lb libkvm
|
||||
.Sh SYNOPSIS
|
||||
.In sys/param.h
|
||||
.In sys/resource.h
|
||||
.In sys/sysctl.h
|
||||
.In kvm.h
|
||||
.Ft int
|
||||
.Fn kvm_getcptime "kvm_t *kd" "long *cp_time"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn kvm_getcptime
|
||||
function stores the global CPU time statistics from the kernel
|
||||
.Fa kd
|
||||
in the array of counters pointed to by
|
||||
.Fa cp_time .
|
||||
Note that
|
||||
.Fa cp_time
|
||||
should point to an array of
|
||||
.Dv CPUSTATES
|
||||
long integers.
|
||||
The format of the counters is identical to that output by the
|
||||
.Va kern.cp_time
|
||||
sysctl.
|
||||
.Sh CACHING
|
||||
This function caches the nlist values for various kernel variables which it
|
||||
reuses in successive calls.
|
||||
You may call the function with
|
||||
.Fa kd
|
||||
set to
|
||||
.Dv NULL
|
||||
to clear this cache.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Nm kvm_getcptime
|
||||
function returns 0 on success and -1 on failure.
|
||||
If an error occurs,
|
||||
then an error message may be retrieved via
|
||||
.Xr kvm_geterr 3 .
|
||||
.Sh SEE ALSO
|
||||
.Xr kvm 3
|
Loading…
Reference in New Issue
Block a user