svn commit: r249344 - head/lib/libkvm

Gleb Smirnoff glebius at FreeBSD.org
Wed Apr 10 20:26:55 UTC 2013


Author: glebius
Date: Wed Apr 10 20:26:53 2013
New Revision: 249344
URL: http://svnweb.freebsd.org/changeset/base/249344

Log:
  o Provide function kvm_read_zpcpu() to access UMA_ZONE_PCPU allocations.
  o Provide function kvm_counter_u64_fetch() to fetch valut of a counter(9).
  
  Sponsored by:	Nginx, Inc.

Modified:
  head/lib/libkvm/Makefile
  head/lib/libkvm/kvm.h
  head/lib/libkvm/kvm_getpcpu.3
  head/lib/libkvm/kvm_pcpu.c

Modified: head/lib/libkvm/Makefile
==============================================================================
--- head/lib/libkvm/Makefile	Wed Apr 10 18:59:20 2013	(r249343)
+++ head/lib/libkvm/Makefile	Wed Apr 10 20:26:53 2013	(r249344)
@@ -25,8 +25,10 @@ MAN=	kvm.3 kvm_getcptime.3 kvm_geterr.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_getpcpu.3 kvm_dpcpu_setcpu.3
+MLINKS+=kvm_getpcpu.3 kvm_getmaxcpu.3 \
+	kvm_getpcpu.3 kvm_dpcpu_setcpu.3 \
+	kvm_getpcpu.3 kvm_read_zpcpu.3 \
+	kvm_getpcpu.3 kvm_counter_u64_fetch
 MLINKS+=kvm_getprocs.3 kvm_getargv.3 kvm_getprocs.3 kvm_getenvv.3
 MLINKS+=kvm_open.3 kvm_close.3 kvm_open.3 kvm_openfiles.3
 MLINKS+=kvm_read.3 kvm_write.3

Modified: head/lib/libkvm/kvm.h
==============================================================================
--- head/lib/libkvm/kvm.h	Wed Apr 10 18:59:20 2013	(r249343)
+++ head/lib/libkvm/kvm.h	Wed Apr 10 20:26:53 2013	(r249344)
@@ -78,6 +78,7 @@ char	 *kvm_getfiles(kvm_t *, int, int, i
 int	  kvm_getloadavg(kvm_t *, double [], int);
 int	  kvm_getmaxcpu(kvm_t *);
 void	 *kvm_getpcpu(kvm_t *, int);
+uint64_t  kvm_counter_u64_fetch(kvm_t *, u_long);
 struct kinfo_proc *
 	  kvm_getprocs(kvm_t *, int, int, int *);
 int	  kvm_getswapinfo(kvm_t *, struct kvm_swap *, int, int);
@@ -87,6 +88,7 @@ kvm_t	 *kvm_open
 kvm_t	 *kvm_openfiles
 	    (const char *, const char *, const char *, int, char *);
 ssize_t	  kvm_read(kvm_t *, unsigned long, void *, size_t);
+ssize_t	  kvm_read_zpcpu(kvm_t *, void *, u_long, size_t, int);
 ssize_t	  kvm_uread
 	    (kvm_t *, const struct kinfo_proc *, unsigned long, char *, size_t);
 ssize_t	  kvm_write(kvm_t *, unsigned long, const void *, size_t);

Modified: head/lib/libkvm/kvm_getpcpu.3
==============================================================================
--- head/lib/libkvm/kvm_getpcpu.3	Wed Apr 10 18:59:20 2013	(r249343)
+++ head/lib/libkvm/kvm_getpcpu.3	Wed Apr 10 20:26:53 2013	(r249344)
@@ -28,7 +28,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 28, 2010
+.Dd April 11, 2013
 .Dt KVM_GETPCPU 3
 .Os
 .Sh NAME
@@ -49,6 +49,10 @@
 .Fn kvm_getmaxcpu "kvm_t *kd"
 .Ft void *
 .Fn kvm_getpcpu "kvm_t *kd" "int cpu"
+.Ft ssize_t
+.Fn kvm_read_zpcpu "kvm_t *kd" "void *buf" "u_long base" "size_t size" "int cpu"
+.Ft uint64_t
+.Fn kvm_counter_u64_fetch "kvm_t *kd" "u_long base"
 .Sh DESCRIPTION
 The
 .Fn kvm_dpcpu_setcpu ,
@@ -83,6 +87,28 @@ is not active, then
 .Dv NULL
 is returned instead.
 .Pp
+The
+.Fn kvm_read_zpcpu
+function is used to obtain private per-CPU copy from a
+.Dv UMA_ZONE_PCPU
+.Xr zone 9 .
+It takes
+.Fa base
+argument as base address of an allocation and copyies 
+.Fa size
+bytes into
+.Fa buf
+from the part of allocation that is private to
+.Fa cpu .
+.Pp
+The
+.Fn kvm_counter_u64_fetch
+function fetches value of a
+.Xr counter 9
+pointed by
+.Fa base
+address.
+.Pp
 Symbols for dynamic per-CPU data are accessed via
 .Xr kvm_nlist 3
 as with other symbols.
@@ -122,9 +148,16 @@ On success, the
 .Fn kvm_dpcpu_setcpu
 call returns 0; if an error occurs, it returns -1 instead.
 .Pp
+On success, the
+.Fn kvm_read_zpcpu
+function returns number of bytes copied.
+If an error occurs, it returns -1 instead.
+.Pp
 If any function encounters an error,
 then an error message may be retrieved via
 .Xr kvm_geterr 3 .
 .Sh SEE ALSO
 .Xr free 3 ,
-.Xr kvm 3
+.Xr kvm 3 ,
+.Xr counter 9 ,
+.Xr zone 9

Modified: head/lib/libkvm/kvm_pcpu.c
==============================================================================
--- head/lib/libkvm/kvm_pcpu.c	Wed Apr 10 18:59:20 2013	(r249343)
+++ head/lib/libkvm/kvm_pcpu.c	Wed Apr 10 20:26:53 2013	(r249344)
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2013 Gleb Smirnoff <glebius at FreeBSD.org>
  * Copyright (c) 2010 Juniper Networks, Inc.
  * Copyright (c) 2009 Robert N. M. Watson
  * Copyright (c) 2009 Bjoern A. Zeeb <bz at FreeBSD.org>
@@ -50,8 +51,12 @@ __FBSDID("$FreeBSD$");
 static struct nlist kvm_pcpu_nl[] = {
 	{ .n_name = "_cpuid_to_pcpu" },
 	{ .n_name = "_mp_maxcpus" },
+	{ .n_name = "_mp_ncpus" },
 	{ .n_name = NULL },
 };
+#define	NL_CPUID_TO_PCPU	0
+#define	NL_MP_MAXCPUS		1
+#define	NL_MP_NCPUS		2
 
 /*
  * Kernel per-CPU data state.  We cache this stuff on the first
@@ -63,9 +68,7 @@ static struct nlist kvm_pcpu_nl[] = {
  */
 static void **pcpu_data;
 static int maxcpu;
-
-#define	NL_CPUID_TO_PCPU	0
-#define	NL_MP_MAXCPUS		1
+static int mp_ncpus;
 
 static int
 _kvm_pcpu_init(kvm_t *kd)
@@ -89,6 +92,15 @@ _kvm_pcpu_init(kvm_t *kd)
 		_kvm_err(kd, kd->program, "cannot read mp_maxcpus");
 		return (-1);
 	}
+	if (kvm_pcpu_nl[NL_MP_NCPUS].n_value == 0) {
+		_kvm_err(kd, kd->program, "unable to find mp_ncpus");
+		return (-1);
+	}
+	if (kvm_read(kd, kvm_pcpu_nl[NL_MP_NCPUS].n_value, &mp_ncpus,
+	    sizeof(mp_ncpus)) != sizeof(mp_ncpus)) {
+		_kvm_err(kd, kd->program, "cannot read mp_ncpus");
+		return (-1);
+	}
 	len = max * sizeof(void *);
 	data = malloc(len);
 	if (data == NULL) {
@@ -289,3 +301,36 @@ kvm_dpcpu_setcpu(kvm_t *kd, u_int cpu)
 
 	return (_kvm_dpcpu_setcpu(kd, cpu, 1));
 }
+
+/*
+ * Obtain a per-CPU copy for given cpu from UMA_ZONE_PCPU allocation.
+ */
+ssize_t
+kvm_read_zpcpu(kvm_t *kd, void *buf, u_long base, size_t size, int cpu)
+{
+
+	return (kvm_read(kd, (uintptr_t)(base + sizeof(struct pcpu) * cpu),
+	    buf, size));
+}
+
+/*
+ * Fetch value of a counter(9).
+ */
+uint64_t
+kvm_counter_u64_fetch(kvm_t *kd, u_long base)
+{
+	uint64_t r, c;
+
+	if (mp_ncpus == 0)
+		if (_kvm_pcpu_init(kd) < 0)
+			return (0);
+
+	r = 0;
+	for (int i = 0; i < mp_ncpus; i++) {
+		if (kvm_read_zpcpu(kd, &c, base, sizeof(c), i) != sizeof(c))
+			return (0);
+		r += c;
+	}
+
+	return (r);
+}


More information about the svn-src-head mailing list