diff --git a/lib/libkvm/Makefile b/lib/libkvm/Makefile index 12042170b440..3ca8427e199a 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 c60d211e1a7a..0427bd1c027e 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 000000000000..53dcdf34288c --- /dev/null +++ b/lib/libkvm/kvm_cptime.c @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 2008 Yahoo!, Inc. + * All rights reserved. + * Written by: John Baldwin + * + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 000000000000..2ddc272d5ff7 --- /dev/null +++ b/lib/libkvm/kvm_getcptime.3 @@ -0,0 +1,77 @@ +.\" Copyright (c) 2008 Yahoo!, Inc. +.\" All rights reserved. +.\" Written by: John Baldwin +.\" +.\" 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