diff options
author | jhb <jhb@FreeBSD.org> | 2008-08-19 21:30:36 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2008-08-19 21:30:36 +0000 |
commit | 67b02c52de29cfb44eea11a7c46f7bf5de57bf36 (patch) | |
tree | 46a6b9c4299efa74349c2c72fe125414690cb591 /lib | |
parent | 10e058a3a20b6ed4f8c0fe21dbadb75ad69ff6b7 (diff) | |
download | FreeBSD-src-67b02c52de29cfb44eea11a7c46f7bf5de57bf36.zip FreeBSD-src-67b02c52de29cfb44eea11a7c46f7bf5de57bf36.tar.gz |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libkvm/Makefile | 7 | ||||
-rw-r--r-- | lib/libkvm/kvm.h | 1 | ||||
-rw-r--r-- | lib/libkvm/kvm_cptime.c | 132 | ||||
-rw-r--r-- | lib/libkvm/kvm_getcptime.3 | 77 |
4 files changed, 214 insertions, 3 deletions
diff --git a/lib/libkvm/Makefile b/lib/libkvm/Makefile index 1204217..3ca8427 100644 --- a/lib/libkvm/Makefile +++ b/lib/libkvm/Makefile @@ -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 diff --git a/lib/libkvm/kvm.h b/lib/libkvm/kvm.h index c60d211..0427bd1 100644 --- a/lib/libkvm/kvm.h +++ b/lib/libkvm/kvm.h @@ -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 *); diff --git a/lib/libkvm/kvm_cptime.c b/lib/libkvm/kvm_cptime.c new file mode 100644 index 0000000..53dcdf3 --- /dev/null +++ b/lib/libkvm/kvm_cptime.c @@ -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); +} diff --git a/lib/libkvm/kvm_getcptime.3 b/lib/libkvm/kvm_getcptime.3 new file mode 100644 index 0000000..2ddc272 --- /dev/null +++ b/lib/libkvm/kvm_getcptime.3 @@ -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 |