Module Name: src
Committed By: mrg
Date: Tue May 17 04:18:07 UTC 2011
Modified Files:
src/sys/arch/sparc64/conf: GENERIC
src/sys/conf: files
src/sys/ddb: db_command.c
src/sys/dev/ic: sl811hs.c
src/sys/uvm: uvm.h uvm_ddb.h uvm_map.c uvm_stat.c uvm_stat.h
src/usr.bin/vmstat: vmstat.c
Added Files:
src/sys/kern: kern_history.c
src/sys/sys: kernhist.h
Log Message:
move and rename the uvm history code out of uvm_stat to "kernhist".
rename "UVMHIST" option to enable the uvm histories.
TODO:
- make UVMHIST properly depend upon KERNHIST
- enable dynamic registration of histories. this is mostly just
allocating something in a bitmap, and is only for viewing multiple
histories in a merged form.
tested on amd64 and sparc64.
To generate a diff of this commit:
cvs rdiff -u -r1.137 -r1.138 src/sys/arch/sparc64/conf/GENERIC
cvs rdiff -u -r1.1011 -r1.1012 src/sys/conf/files
cvs rdiff -u -r1.135 -r1.136 src/sys/ddb/db_command.c
cvs rdiff -u -r1.27 -r1.28 src/sys/dev/ic/sl811hs.c
cvs rdiff -u -r0 -r1.1 src/sys/kern/kern_history.c
cvs rdiff -u -r0 -r1.1 src/sys/sys/kernhist.h
cvs rdiff -u -r1.61 -r1.62 src/sys/uvm/uvm.h
cvs rdiff -u -r1.14 -r1.15 src/sys/uvm/uvm_ddb.h
cvs rdiff -u -r1.296 -r1.297 src/sys/uvm/uvm_map.c
cvs rdiff -u -r1.36 -r1.37 src/sys/uvm/uvm_stat.c
cvs rdiff -u -r1.49 -r1.50 src/sys/uvm/uvm_stat.h
cvs rdiff -u -r1.180 -r1.181 src/usr.bin/vmstat/vmstat.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/sparc64/conf/GENERIC
diff -u src/sys/arch/sparc64/conf/GENERIC:1.137 src/sys/arch/sparc64/conf/GENERIC:1.138
--- src/sys/arch/sparc64/conf/GENERIC:1.137 Thu May 12 07:06:00 2011
+++ src/sys/arch/sparc64/conf/GENERIC Tue May 17 04:18:05 2011
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.137 2011/05/12 07:06:00 mrg Exp $
+# $NetBSD: GENERIC,v 1.138 2011/05/17 04:18:05 mrg Exp $
#
# GENERIC machine description file
#
@@ -22,7 +22,7 @@
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "GENERIC-$Revision: 1.137 $"
+#ident "GENERIC-$Revision: 1.138 $"
maxusers 64
@@ -99,7 +99,7 @@
## Compile the kernel with debugging symbols (`netbsd.gdb' is the debug file),
## such that gdb(1) can be used on a kernel coredump.
-#makeoptions DEBUG="-g"
+makeoptions DEBUG="-g"
## Adds code to the kernel that does internal consistency checks, and will
Index: src/sys/conf/files
diff -u src/sys/conf/files:1.1011 src/sys/conf/files:1.1012
--- src/sys/conf/files:1.1011 Thu May 5 17:38:35 2011
+++ src/sys/conf/files Tue May 17 04:18:06 2011
@@ -1,4 +1,4 @@
-# $NetBSD: files,v 1.1011 2011/05/05 17:38:35 drochner Exp $
+# $NetBSD: files,v 1.1012 2011/05/17 04:18:06 mrg Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
version 20100430
@@ -1384,6 +1384,13 @@
include "uvm/files.uvm"
#
+# Kernel history/tracing. Old UVMHIST depends upon this.
+# XXXMRG can't make UVMHIST depend properly on KERNHIST?
+#
+defflag opt_kernhist.h KERNHIST KERNHIST_PRINT
+file kern/kern_history.c kernhist
+
+#
# Security models
#
include "secmodel/files.secmodel"
Index: src/sys/ddb/db_command.c
diff -u src/sys/ddb/db_command.c:1.135 src/sys/ddb/db_command.c:1.136
--- src/sys/ddb/db_command.c:1.135 Sun Apr 10 20:59:22 2011
+++ src/sys/ddb/db_command.c Tue May 17 04:18:06 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: db_command.c,v 1.135 2011/04/10 20:59:22 christos Exp $ */
+/* $NetBSD: db_command.c,v 1.136 2011/05/17 04:18:06 mrg Exp $ */
/*
* Copyright (c) 1996, 1997, 1998, 1999, 2002, 2009 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.135 2011/04/10 20:59:22 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.136 2011/05/17 04:18:06 mrg Exp $");
#ifdef _KERNEL_OPT
#include "opt_aio.h"
@@ -68,7 +68,7 @@
#include "opt_kgdb.h"
#include "opt_mqueue.h"
#include "opt_inet.h"
-#include "opt_uvmhist.h"
+#include "opt_kernhist.h"
#include "opt_ddbparam.h"
#include "opt_multiprocessor.h"
#include "arp.h"
@@ -90,6 +90,7 @@
#include <sys/cpu.h>
#include <sys/buf.h>
#include <sys/module.h>
+#include <sys/kernhist.h>
/*include queue macros*/
#include <sys/queue.h>
@@ -205,8 +206,8 @@
static void db_sync_cmd(db_expr_t, bool, db_expr_t, const char *);
static void db_whatis_cmd(db_expr_t, bool, db_expr_t, const char *);
static void db_uvmexp_print_cmd(db_expr_t, bool, db_expr_t, const char *);
-#ifdef UVMHIST
-static void db_uvmhist_print_cmd(db_expr_t, bool, db_expr_t, const char *);
+#ifdef KERNHIST
+static void db_kernhist_print_cmd(db_expr_t, bool, db_expr_t, const char *);
#endif
static void db_vnode_print_cmd(db_expr_t, bool, db_expr_t, const char *);
static void db_vmem_print_cmd(db_expr_t, bool, db_expr_t, const char *);
@@ -276,8 +277,8 @@
{ DDB_ADD_CMD("uvmexp", db_uvmexp_print_cmd, 0,
"Print a selection of UVM counters and statistics.",
NULL,NULL) },
-#ifdef UVMHIST
- { DDB_ADD_CMD("uvmhist", db_uvmhist_print_cmd, 0,
+#ifdef KERNHIST
+ { DDB_ADD_CMD("kernhist", db_kernhist_print_cmd, 0,
"Print the UVM history logs.",
NULL,NULL) },
#endif
@@ -1197,14 +1198,14 @@
#endif
}
-#ifdef UVMHIST
+#ifdef KERNHIST
/*ARGSUSED*/
static void
-db_uvmhist_print_cmd(db_expr_t addr, bool have_addr,
+db_kernhist_print_cmd(db_expr_t addr, bool have_addr,
db_expr_t count, const char *modif)
{
- uvmhist_print(db_printf);
+ kernhist_print(db_printf);
}
#endif
Index: src/sys/dev/ic/sl811hs.c
diff -u src/sys/dev/ic/sl811hs.c:1.27 src/sys/dev/ic/sl811hs.c:1.28
--- src/sys/dev/ic/sl811hs.c:1.27 Sun Mar 13 05:26:14 2011
+++ src/sys/dev/ic/sl811hs.c Tue May 17 04:18:06 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: sl811hs.c,v 1.27 2011/03/13 05:26:14 kiyohara Exp $ */
+/* $NetBSD: sl811hs.c,v 1.28 2011/05/17 04:18:06 mrg Exp $ */
/*
* Not (c) 2007 Matthew Orgass
@@ -84,7 +84,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.27 2011/03/13 05:26:14 kiyohara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.28 2011/05/17 04:18:06 mrg Exp $");
#include "opt_slhci.h"
@@ -561,35 +561,42 @@
int slhci_usbdebug = -1; /* value to set usbdebug on attach, -1 = leave alone */
#endif
-/* Add UVMHIST history for debugging:
+/*
+ * XXXMRG the SLHCI UVMHIST code has been converted to KERNHIST, but it has
+ * not been tested. the extra instructions to enable it can probably be
+ * commited to the kernhist code, and these instructions reduced to simply
+ * enabling SLHCI_DEBUG.
+ */
+
+/* Add KERNHIST history for debugging:
*
- * Before uvm_hist in sys/uvm/uvm_stat.c add:
- * UVMHIST_DECL(slhcihist);
+ * Before kern_hist in sys/kern/subr_kernhist.c add:
+ * KERNHIST_DECL(slhcihist);
*
- * In uvm_hist add:
- * if ((bitmask & UVMHIST_SLHCI))
+ * In kern_hist add:
+ * if ((bitmask & KERNHIST_SLHCI))
* hists[i++] = &slhcihist;
*
- * In sys/uvm/uvm_stat.h add UVMHIST_SLHCI define.
+ * In sys/sys/kernhist.h add KERNHIST_SLHCI define.
*/
-#include <uvm/uvm_stat.h>
-UVMHIST_DECL(slhcihist);
+#include <sys/kernhist.h>
+KERNHIST_DECL(slhcihist);
-#if !defined(UVMHIST) || !defined(UVMHIST_SLHCI)
-#error "SLHCI_DEBUG requires UVMHIST (with modifications, see sys/dev/ic/sl81hs.c)"
+#if !defined(KERNHIST) || !defined(KERNHIST_SLHCI)
+#error "SLHCI_DEBUG requires KERNHIST (with modifications, see sys/dev/ic/sl81hs.c)"
#endif
#ifndef SLHCI_NHIST
#define SLHCI_NHIST 409600
#endif
-const unsigned int SLHCI_HISTMASK = UVMHIST_SLHCI;
-struct uvm_history_ent slhci_he[SLHCI_NHIST];
+const unsigned int SLHCI_HISTMASK = KERNHIST_SLHCI;
+struct kern_history_ent slhci_he[SLHCI_NHIST];
#define SLHCI_DEXEC(x, y) do { if ((slhci_debug & SLHCI_ ## x)) { y; } \
} while (/*CONSTCOND*/ 0)
-#define DDOLOG(f, a, b, c, d) do { const char *_uvmhist_name = __func__; \
- u_long _uvmhist_call = 0; UVMHIST_LOG(slhcihist, f, a, b, c, d); \
+#define DDOLOG(f, a, b, c, d) do { const char *_kernhist_name = __func__; \
+ u_long _kernhist_call = 0; KERNHIST_LOG(slhcihist, f, a, b, c, d); \
} while (/*CONSTCOND*/0)
#define DLOG(x, f, a, b, c, d) SLHCI_DEXEC(x, DDOLOG(f, a, b, c, d))
/* DLOGFLAG8 is a macro not a function so that flag name expressions are not
@@ -597,10 +604,10 @@
* x is debug mask, y is flag identifier, z is flag variable,
* a-h are flag names (must evaluate to string constants, msb first). */
#define DDOLOGFLAG8(y, z, a, b, c, d, e, f, g, h) do { uint8_t _DLF8 = (z); \
- const char *_uvmhist_name = __func__; u_long _uvmhist_call = 0; \
- if (_DLF8 & 0xf0) UVMHIST_LOG(slhcihist, y " %s %s %s %s", _DLF8 & 0x80 ? \
+ const char *_kernhist_name = __func__; u_long _kernhist_call = 0; \
+ if (_DLF8 & 0xf0) KERNHIST_LOG(slhcihist, y " %s %s %s %s", _DLF8 & 0x80 ? \
(a) : "", _DLF8 & 0x40 ? (b) : "", _DLF8 & 0x20 ? (c) : "", _DLF8 & 0x10 ? \
- (d) : ""); if (_DLF8 & 0x0f) UVMHIST_LOG(slhcihist, y " %s %s %s %s", \
+ (d) : ""); if (_DLF8 & 0x0f) KERNHIST_LOG(slhcihist, y " %s %s %s %s", \
_DLF8 & 0x08 ? (e) : "", _DLF8 & 0x04 ? (f) : "", _DLF8 & 0x02 ? (g) : "", \
_DLF8 & 0x01 ? (h) : ""); \
} while (/*CONSTCOND*/ 0)
@@ -1143,7 +1150,7 @@
t = &sc->sc_transfers;
#ifdef SLHCI_DEBUG
- UVMHIST_INIT_STATIC(slhcihist, slhci_he);
+ KERNHIST_INIT_STATIC(slhcihist, slhci_he);
#endif
simple_lock_init(&sc->sc_lock);
#ifdef SLHCI_WAITLOCK
Index: src/sys/uvm/uvm.h
diff -u src/sys/uvm/uvm.h:1.61 src/sys/uvm/uvm.h:1.62
--- src/sys/uvm/uvm.h:1.61 Wed Feb 2 17:53:42 2011
+++ src/sys/uvm/uvm.h Tue May 17 04:18:07 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm.h,v 1.61 2011/02/02 17:53:42 chuck Exp $ */
+/* $NetBSD: uvm.h,v 1.62 2011/05/17 04:18:07 mrg Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -39,7 +39,9 @@
#include <uvm/uvm_extern.h>
+#ifdef _KERNEL
#include <uvm/uvm_stat.h>
+#endif
/*
* pull in prototypes
Index: src/sys/uvm/uvm_ddb.h
diff -u src/sys/uvm/uvm_ddb.h:1.14 src/sys/uvm/uvm_ddb.h:1.15
--- src/sys/uvm/uvm_ddb.h:1.14 Wed Feb 2 15:13:34 2011
+++ src/sys/uvm/uvm_ddb.h Tue May 17 04:18:07 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_ddb.h,v 1.14 2011/02/02 15:13:34 chuck Exp $ */
+/* $NetBSD: uvm_ddb.h,v 1.15 2011/05/17 04:18:07 mrg Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -41,7 +41,6 @@
void (*)(const char *, ...));
void uvm_page_printall(void (*)(const char *, ...));
void uvmexp_print(void (*)(const char *, ...));
-void uvmhist_print(void (*)(const char *, ...));
#endif /* DDB || DEBUGPRINT */
#endif /* _KERNEL */
Index: src/sys/uvm/uvm_map.c
diff -u src/sys/uvm/uvm_map.c:1.296 src/sys/uvm/uvm_map.c:1.297
--- src/sys/uvm/uvm_map.c:1.296 Fri Apr 8 10:38:36 2011
+++ src/sys/uvm/uvm_map.c Tue May 17 04:18:07 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_map.c,v 1.296 2011/04/08 10:38:36 yamt Exp $ */
+/* $NetBSD: uvm_map.c,v 1.297 2011/05/17 04:18:07 mrg Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.296 2011/04/08 10:38:36 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.297 2011/05/17 04:18:07 mrg Exp $");
#include "opt_ddb.h"
#include "opt_uvmhist.h"
@@ -1013,8 +1013,8 @@
uvm_map_init(void)
{
#if defined(UVMHIST)
- static struct uvm_history_ent maphistbuf[100];
- static struct uvm_history_ent pdhistbuf[100];
+ static struct kern_history_ent maphistbuf[100];
+ static struct kern_history_ent pdhistbuf[100];
#endif
/*
Index: src/sys/uvm/uvm_stat.c
diff -u src/sys/uvm/uvm_stat.c:1.36 src/sys/uvm/uvm_stat.c:1.37
--- src/sys/uvm/uvm_stat.c:1.36 Wed Feb 2 15:13:34 2011
+++ src/sys/uvm/uvm_stat.c Tue May 17 04:18:07 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_stat.c,v 1.36 2011/02/02 15:13:34 chuck Exp $ */
+/* $NetBSD: uvm_stat.c,v 1.37 2011/05/17 04:18:07 mrg Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -32,9 +32,8 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_stat.c,v 1.36 2011/02/02 15:13:34 chuck Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_stat.c,v 1.37 2011/05/17 04:18:07 mrg Exp $");
-#include "opt_uvmhist.h"
#include "opt_readahead.h"
#include "opt_ddb.h"
@@ -45,157 +44,9 @@
#include <uvm/uvm.h>
#include <uvm/uvm_ddb.h>
-/*
- * globals
- */
-
-#ifdef UVMHIST
-struct uvm_history_head uvm_histories;
-#endif
-
-#ifdef UVMHIST_PRINT
-int uvmhist_print_enabled = 1;
-#endif
-
#ifdef DDB
/*
- * prototypes
- */
-
-#ifdef UVMHIST
-void uvmhist_dump(struct uvm_history *);
-void uvm_hist(u_int32_t);
-static void uvmhist_dump_histories(struct uvm_history *[]);
-#endif
-void uvmcnt_dump(void);
-
-
-#ifdef UVMHIST
-/* call this from ddb */
-void
-uvmhist_dump(struct uvm_history *l)
-{
- int lcv, s;
-
- s = splhigh();
- lcv = l->f;
- do {
- if (l->e[lcv].fmt)
- uvmhist_entry_print(&l->e[lcv]);
- lcv = (lcv + 1) % l->n;
- } while (lcv != l->f);
- splx(s);
-}
-
-/*
- * print a merged list of uvm_history structures
- */
-static void
-uvmhist_dump_histories(struct uvm_history *hists[])
-{
- struct timeval tv;
- int cur[MAXHISTS];
- int s, lcv, hi;
-
- /* so we don't get corrupted lists! */
- s = splhigh();
-
- /* find the first of each list */
- for (lcv = 0; hists[lcv]; lcv++)
- cur[lcv] = hists[lcv]->f;
-
- /*
- * here we loop "forever", finding the next earliest
- * history entry and printing it. cur[X] is the current
- * entry to test for the history in hists[X]. if it is
- * -1, then this history is finished.
- */
- for (;;) {
- hi = -1;
- tv.tv_sec = tv.tv_usec = 0;
-
- /* loop over each history */
- for (lcv = 0; hists[lcv]; lcv++) {
-restart:
- if (cur[lcv] == -1)
- continue;
-
- /*
- * if the format is empty, go to the next entry
- * and retry.
- */
- if (hists[lcv]->e[cur[lcv]].fmt == NULL) {
- cur[lcv] = (cur[lcv] + 1) % (hists[lcv]->n);
- if (cur[lcv] == hists[lcv]->f)
- cur[lcv] = -1;
- goto restart;
- }
-
- /*
- * if the time hasn't been set yet, or this entry is
- * earlier than the current tv, set the time and history
- * index.
- */
- if (tv.tv_sec == 0 ||
- timercmp(&hists[lcv]->e[cur[lcv]].tv, &tv, <)) {
- tv = hists[lcv]->e[cur[lcv]].tv;
- hi = lcv;
- }
- }
-
- /* if we didn't find any entries, we must be done */
- if (hi == -1)
- break;
-
- /* print and move to the next entry */
- uvmhist_entry_print(&hists[hi]->e[cur[hi]]);
- cur[hi] = (cur[hi] + 1) % (hists[hi]->n);
- if (cur[hi] == hists[hi]->f)
- cur[hi] = -1;
- }
- splx(s);
-}
-
-/*
- * call this from ddb. `bitmask' is from <uvm/uvm_stat.h>. it
- * merges the named histories.
- */
-void
-uvm_hist(u_int32_t bitmask) /* XXX only support 32 hists */
-{
- struct uvm_history *hists[MAXHISTS + 1];
- int i = 0;
-
- if ((bitmask & UVMHIST_MAPHIST) || bitmask == 0)
- hists[i++] = &maphist;
-
- if ((bitmask & UVMHIST_PDHIST) || bitmask == 0)
- hists[i++] = &pdhist;
-
- if ((bitmask & UVMHIST_UBCHIST) || bitmask == 0)
- hists[i++] = &ubchist;
-
- if ((bitmask & UVMHIST_LOANHIST) || bitmask == 0)
- hists[i++] = &loanhist;
-
- hists[i] = NULL;
-
- uvmhist_dump_histories(hists);
-}
-
-/*
- * uvmhist_print: ddb hook to print uvm history
- */
-void
-uvmhist_print(void (*pr)(const char *, ...))
-{
- uvmhist_dump(LIST_FIRST(&uvm_histories));
-}
-
-#endif /* UVMHIST */
-
-/*
* uvmexp_print: ddb hook to print interesting uvm counters
*/
void
Index: src/sys/uvm/uvm_stat.h
diff -u src/sys/uvm/uvm_stat.h:1.49 src/sys/uvm/uvm_stat.h:1.50
--- src/sys/uvm/uvm_stat.h:1.49 Sat Apr 23 18:14:13 2011
+++ src/sys/uvm/uvm_stat.h Tue May 17 04:18:07 2011
@@ -1,7 +1,7 @@
-/* $NetBSD: uvm_stat.h,v 1.49 2011/04/23 18:14:13 rmind Exp $ */
+/* $NetBSD: uvm_stat.h,v 1.50 2011/05/17 04:18:07 mrg Exp $ */
/*
- * Copyright (c) 1997 Charles D. Cranor and Washington University.
+ * Copyright (c) 2011 Matthew R. Green
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -12,19 +12,24 @@
* 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
- *
- * from: Id: uvm_stat.h,v 1.1.2.4 1998/02/07 01:16:56 chs Exp
+ * 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.
+ */
+
+/*
+ * Backwards compat for UVMHIST, in the new KERNHIST form.
*/
#ifndef _UVM_UVM_STAT_H_
@@ -32,162 +37,36 @@
#if defined(_KERNEL_OPT)
#include "opt_uvmhist.h"
+#include "opt_kernhist.h"
#endif
-#include <sys/queue.h>
-#ifdef UVMHIST
-#include <sys/cpu.h>
-#endif
-
-/*
- * uvm_stat: monitor what is going on with uvm (or whatever)
- */
-
/*
- * history/tracing
+ * Make UVMHIST_PRINT force on KERNHIST_PRINT for at least UVMHIST_* usage.
*/
+#if defined(UVMHIST_PRINT) && !defined(KERNHIST_PRINT)
+#define KERNHIST_PRINT 1
+#endif
-struct uvm_history_ent {
- struct timeval tv; /* time stamp */
- int cpunum;
- const char *fmt; /* printf format */
- size_t fmtlen; /* length of printf format */
- const char *fn; /* function name */
- size_t fnlen; /* length of function name */
- u_long call; /* function call number */
- u_long v[4]; /* values */
-};
-
-struct uvm_history {
- const char *name; /* name of this history */
- size_t namelen; /* length of name, not including null */
- LIST_ENTRY(uvm_history) list; /* link on list of all histories */
- unsigned int n; /* number of entries */
- unsigned int f; /* next free one */
- struct uvm_history_ent *e; /* the allocated entries */
-};
-
-LIST_HEAD(uvm_history_head, uvm_history);
-
-/*
- * grovelling lists all at once. we currently do not allow more than
- * 32 histories to exist, as the way to dump a number of them at once
- * is by calling uvm_hist() with a bitmask.
- */
+#include <sys/kernhist.h>
-/* this is used to set the size of some arrays */
-#define MAXHISTS 32 /* do not change this! */
+#ifdef UVMHIST
-/* and these are the bit values of each history */
-#define UVMHIST_MAPHIST 0x00000001 /* maphist */
-#define UVMHIST_PDHIST 0x00000002 /* pdhist */
-#define UVMHIST_UBCHIST 0x00000004 /* ubchist */
-#define UVMHIST_LOANHIST 0x00000008 /* loanhist */
+#define UVMHIST_DECL(NAME) KERNHIST_DECL(NAME)
+#define UVMHIST_INIT(NAME,N) KERNHIST_INIT(NAME,N)
+#define UVMHIST_INIT_STATIC(NAME,BUF) KERNHIST_INIT_STATIC(NAME,BUF)
+#define UVMHIST_LOG(NAME,FMT,A,B,C,D) KERNHIST_LOG(NAME,FMT,A,B,C,D)
+#define UVMHIST_CALLED(NAME) KERNHIST_CALLED(NAME)
+#define UVMHIST_FUNC(FNAME) KERNHIST_FUNC(FNAME)
-#ifdef _KERNEL
+#else
-/*
- * macros to use the history/tracing code. note that UVMHIST_LOG
- * must take 4 arguments (even if they are ignored by the format).
- */
-#ifndef UVMHIST
#define UVMHIST_DECL(NAME)
#define UVMHIST_INIT(NAME,N)
#define UVMHIST_INIT_STATIC(NAME,BUF)
#define UVMHIST_LOG(NAME,FMT,A,B,C,D)
#define UVMHIST_CALLED(NAME)
#define UVMHIST_FUNC(FNAME)
-#define uvmhist_dump(NAME)
-#else
-#include <sys/kernel.h> /* for "cold" variable */
-#include <sys/atomic.h>
-#include <sys/kmem.h>
-
-extern struct uvm_history_head uvm_histories;
-
-#define UVMHIST_DECL(NAME) struct uvm_history NAME
-
-#define UVMHIST_INIT(NAME,N) \
-do { \
- (NAME).name = __STRING(NAME); \
- (NAME).namelen = strlen(__STRING(NAME)); \
- (NAME).n = (N); \
- (NAME).f = 0; \
- (NAME).e = (struct uvm_history_ent *) \
- kmem_zalloc(sizeof(struct uvm_history_ent) * (N), KM_SLEEP); \
- LIST_INSERT_HEAD(&uvm_histories, &(NAME), list); \
-} while (/*CONSTCOND*/ 0)
-
-#define UVMHIST_INIT_STATIC(NAME,BUF) \
-do { \
- (NAME).name = __STRING(NAME); \
- (NAME).namelen = strlen(__STRING(NAME)); \
- (NAME).n = sizeof(BUF) / sizeof(struct uvm_history_ent); \
- (NAME).f = 0; \
- (NAME).e = (struct uvm_history_ent *) (BUF); \
- memset((NAME).e, 0, sizeof(struct uvm_history_ent) * (NAME).n); \
- LIST_INSERT_HEAD(&uvm_histories, &(NAME), list); \
-} while (/*CONSTCOND*/ 0)
-
-#if defined(UVMHIST_PRINT)
-extern int uvmhist_print_enabled;
-#define UVMHIST_PRINTNOW(E) \
-do { \
- if (uvmhist_print_enabled) { \
- uvmhist_entry_print(E); \
- DELAY(100000); \
- } \
-} while (/*CONSTCOND*/ 0)
-#else
-#define UVMHIST_PRINTNOW(E) /* nothing */
-#endif
-
-#define UVMHIST_LOG(NAME,FMT,A,B,C,D) \
-do { \
- unsigned int _i_, _j_; \
- do { \
- _i_ = (NAME).f; \
- _j_ = (_i_ + 1 < (NAME).n) ? _i_ + 1 : 0; \
- } while (atomic_cas_uint(&(NAME).f, _i_, _j_) != _i_); \
- if (!cold) \
- microtime(&(NAME).e[_i_].tv); \
- (NAME).e[_i_].cpunum = cpu_number(); \
- (NAME).e[_i_].fmt = (FMT); \
- (NAME).e[_i_].fmtlen = strlen(FMT); \
- (NAME).e[_i_].fn = _uvmhist_name; \
- (NAME).e[_i_].fnlen = strlen(_uvmhist_name); \
- (NAME).e[_i_].call = _uvmhist_call; \
- (NAME).e[_i_].v[0] = (u_long)(A); \
- (NAME).e[_i_].v[1] = (u_long)(B); \
- (NAME).e[_i_].v[2] = (u_long)(C); \
- (NAME).e[_i_].v[3] = (u_long)(D); \
- UVMHIST_PRINTNOW(&((NAME).e[_i_])); \
-} while (/*CONSTCOND*/ 0)
-
-#define UVMHIST_CALLED(NAME) \
-do { \
- _uvmhist_call = atomic_inc_uint_nv(&_uvmhist_cnt); \
- UVMHIST_LOG(NAME,"called!", 0, 0, 0, 0); \
-} while (/*CONSTCOND*/ 0)
-
-#define UVMHIST_FUNC(FNAME) \
- static unsigned int _uvmhist_cnt = 0; \
- static const char *const _uvmhist_name = FNAME; \
- int _uvmhist_call;
-
-static inline void uvmhist_entry_print(struct uvm_history_ent *);
-
-static inline void
-uvmhist_entry_print(e)
- struct uvm_history_ent *e;
-{
- printf("%06" PRIu64 ".%06d ", e->tv.tv_sec, e->tv.tv_usec);
- printf("%s#%ld@%d: ", e->fn, e->call, e->cpunum);
- printf(e->fmt, e->v[0], e->v[1], e->v[2], e->v[3]);
- printf("\n");
-}
-#endif /* UVMHIST */
-#endif /* _KERNEL */
+#endif
#endif /* _UVM_UVM_STAT_H_ */
Index: src/usr.bin/vmstat/vmstat.c
diff -u src/usr.bin/vmstat/vmstat.c:1.180 src/usr.bin/vmstat/vmstat.c:1.181
--- src/usr.bin/vmstat/vmstat.c:1.180 Wed Feb 16 12:58:38 2011
+++ src/usr.bin/vmstat/vmstat.c Tue May 17 04:18:07 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: vmstat.c,v 1.180 2011/02/16 12:58:38 nakayama Exp $ */
+/* $NetBSD: vmstat.c,v 1.181 2011/05/17 04:18:07 mrg Exp $ */
/*-
* Copyright (c) 1998, 2000, 2001, 2007 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
#if 0
static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95";
#else
-__RCSID("$NetBSD: vmstat.c,v 1.180 2011/02/16 12:58:38 nakayama Exp $");
+__RCSID("$NetBSD: vmstat.c,v 1.181 2011/05/17 04:18:07 mrg Exp $");
#endif
#endif /* not lint */
@@ -95,6 +95,7 @@
#include <sys/time.h>
#include <sys/user.h>
#include <sys/queue.h>
+#include <sys/kernhist.h>
#include <uvm/uvm_extern.h>
#include <uvm/uvm_stat.h>
@@ -236,12 +237,12 @@
};
/*
- * Namelist for UVM histories
+ * Namelist for kernel histories
*/
struct nlist histnl[] =
{
- { .n_name = "_uvm_histories" },
-#define X_UVM_HISTORIES 0
+ { .n_name = "_kern_histories" },
+#define X_KERN_HISTORIES 0
{ .n_name = NULL },
};
@@ -319,7 +320,7 @@
void doforkst(void);
void hist_traverse(int, const char *);
-void hist_dodump(struct uvm_history *);
+void hist_dodump(struct kern_history *);
int main(int, char **);
char **choosedrives(char **);
@@ -1752,34 +1753,34 @@
}
/*
- * Traverse the UVM history buffers, performing the requested action.
+ * Traverse the kernel history buffers, performing the requested action.
*
* Note, we assume that if we're not listing, we're dumping.
*/
void
hist_traverse(int todo, const char *histname)
{
- struct uvm_history_head histhead;
- struct uvm_history hist, *histkva;
+ struct kern_history_head histhead;
+ struct kern_history hist, *histkva;
char *name = NULL;
size_t namelen = 0;
getnlist(todo);
if (histnl[0].n_value == 0) {
- warnx("UVM history is not compiled into the kernel.");
+ warnx("kernel history is not compiled into the kernel.");
return;
}
- deref_kptr((void *)histnl[X_UVM_HISTORIES].n_value, &histhead,
- sizeof(histhead), histnl[X_UVM_HISTORIES].n_name);
+ deref_kptr((void *)histnl[X_KERN_HISTORIES].n_value, &histhead,
+ sizeof(histhead), histnl[X_KERN_HISTORIES].n_name);
if (histhead.lh_first == NULL) {
- warnx("No active UVM history logs.");
+ warnx("No active kernel history logs.");
return;
}
if (todo & HISTLIST)
- (void)printf("Active UVM histories:");
+ (void)printf("Active kernel histories:");
for (histkva = LIST_FIRST(&histhead); histkva != NULL;
histkva = LIST_NEXT(&hist, list)) {
@@ -1804,7 +1805,7 @@
if (histname == NULL || strcmp(histname, name) == 0) {
if (histname == NULL)
(void)printf(
- "\nUVM history `%s':\n", name);
+ "\nkernel history `%s':\n", name);
hist_dodump(&hist);
}
}
@@ -1821,15 +1822,15 @@
* Actually dump the history buffer at the specified KVA.
*/
void
-hist_dodump(struct uvm_history *histp)
+hist_dodump(struct kern_history *histp)
{
- struct uvm_history_ent *histents, *e;
+ struct kern_history_ent *histents, *e;
size_t histsize;
char *fmt = NULL, *fn = NULL;
size_t fmtlen = 0, fnlen = 0;
unsigned i;
- histsize = sizeof(struct uvm_history_ent) * histp->n;
+ histsize = sizeof(struct kern_history_ent) * histp->n;
if ((histents = malloc(histsize)) == NULL)
err(1, "malloc history entries");
Added files:
Index: src/sys/kern/kern_history.c
diff -u /dev/null src/sys/kern/kern_history.c:1.1
--- /dev/null Tue May 17 04:18:07 2011
+++ src/sys/kern/kern_history.c Tue May 17 04:18:06 2011
@@ -0,0 +1,191 @@
+/* $NetBSD: kern_history.c,v 1.1 2011/05/17 04:18:06 mrg Exp $ */
+
+/*
+ * Copyright (c) 1997 Charles D. Cranor and Washington University.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ * from: NetBSD: uvm_stat.c,v 1.36 2011/02/02 15:13:34 chuck Exp
+ * from: Id: uvm_stat.c,v 1.1.2.3 1997/12/19 15:01:00 mrg Exp
+ */
+
+/*
+ * subr_kernhist.c
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: kern_history.c,v 1.1 2011/05/17 04:18:06 mrg Exp $");
+
+#include "opt_kernhist.h"
+#include "opt_uvmhist.h"
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/cpu.h>
+#include <sys/kernhist.h>
+
+#include <uvm/uvm.h>
+
+/*
+ * globals
+ */
+
+struct kern_history_head kern_histories;
+
+int kernhist_print_enabled = 1;
+
+#ifdef DDB
+
+/*
+ * prototypes
+ */
+
+void kernhist_dump(struct kern_history *);
+void kernhist_dumpmask(u_int32_t);
+static void kernhist_dump_histories(struct kern_history *[]);
+
+
+/*
+ * call this from ddb
+ *
+ * expects the system to be quiesced, no locking
+ */
+void
+kernhist_dump(struct kern_history *l)
+{
+ int lcv;
+
+ lcv = l->f;
+ do {
+ if (l->e[lcv].fmt)
+ kernhist_entry_print(&l->e[lcv]);
+ lcv = (lcv + 1) % l->n;
+ } while (lcv != l->f);
+}
+
+/*
+ * print a merged list of kern_history structures
+ */
+static void
+kernhist_dump_histories(struct kern_history *hists[])
+{
+ struct timeval tv;
+ int cur[MAXHISTS];
+ int lcv, hi;
+
+ /* find the first of each list */
+ for (lcv = 0; hists[lcv]; lcv++)
+ cur[lcv] = hists[lcv]->f;
+
+ /*
+ * here we loop "forever", finding the next earliest
+ * history entry and printing it. cur[X] is the current
+ * entry to test for the history in hists[X]. if it is
+ * -1, then this history is finished.
+ */
+ for (;;) {
+ hi = -1;
+ tv.tv_sec = tv.tv_usec = 0;
+
+ /* loop over each history */
+ for (lcv = 0; hists[lcv]; lcv++) {
+restart:
+ if (cur[lcv] == -1)
+ continue;
+
+ /*
+ * if the format is empty, go to the next entry
+ * and retry.
+ */
+ if (hists[lcv]->e[cur[lcv]].fmt == NULL) {
+ cur[lcv] = (cur[lcv] + 1) % (hists[lcv]->n);
+ if (cur[lcv] == hists[lcv]->f)
+ cur[lcv] = -1;
+ goto restart;
+ }
+
+ /*
+ * if the time hasn't been set yet, or this entry is
+ * earlier than the current tv, set the time and history
+ * index.
+ */
+ if (tv.tv_sec == 0 ||
+ timercmp(&hists[lcv]->e[cur[lcv]].tv, &tv, <)) {
+ tv = hists[lcv]->e[cur[lcv]].tv;
+ hi = lcv;
+ }
+ }
+
+ /* if we didn't find any entries, we must be done */
+ if (hi == -1)
+ break;
+
+ /* print and move to the next entry */
+ kernhist_entry_print(&hists[hi]->e[cur[hi]]);
+ cur[hi] = (cur[hi] + 1) % (hists[hi]->n);
+ if (cur[hi] == hists[hi]->f)
+ cur[hi] = -1;
+ }
+}
+
+/*
+ * call this from ddb. `bitmask' is from <sys/kernhist.h>. it
+ * merges the named histories.
+ *
+ * expects the system to be quiesced, no locking
+ */
+void
+kernhist_dumpmask(u_int32_t bitmask) /* XXX only support 32 hists */
+{
+ struct kern_history *hists[MAXHISTS + 1];
+ int i = 0;
+
+#ifdef UVMHIST
+ if ((bitmask & KERNHIST_UVMMAPHIST) || bitmask == 0)
+ hists[i++] = &maphist;
+
+ if ((bitmask & KERNHIST_UVMPDHIST) || bitmask == 0)
+ hists[i++] = &pdhist;
+
+ if ((bitmask & KERNHIST_UVMUBCHIST) || bitmask == 0)
+ hists[i++] = &ubchist;
+
+ if ((bitmask & KERNHIST_UVMLOANHIST) || bitmask == 0)
+ hists[i++] = &loanhist;
+#endif
+
+ hists[i] = NULL;
+
+ kernhist_dump_histories(hists);
+}
+
+/*
+ * kernhist_print: ddb hook to print kern history
+ */
+void
+kernhist_print(void (*pr)(const char *, ...))
+{
+ kernhist_dump(LIST_FIRST(&kern_histories));
+}
+
+#endif
Index: src/sys/sys/kernhist.h
diff -u /dev/null src/sys/sys/kernhist.h:1.1
--- /dev/null Tue May 17 04:18:07 2011
+++ src/sys/sys/kernhist.h Tue May 17 04:18:07 2011
@@ -0,0 +1,199 @@
+/* $NetBSD: kernhist.h,v 1.1 2011/05/17 04:18:07 mrg Exp $ */
+
+/*
+ * Copyright (c) 1997 Charles D. Cranor and Washington University.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
+ *
+ * from: NetBSD: uvm_stat.h,v 1.49 2011/04/23 18:14:13 rmind Exp
+ * from: Id: uvm_stat.h,v 1.1.2.4 1998/02/07 01:16:56 chs Exp
+ */
+
+#ifndef _SYS_KERNHIST_H_
+#define _SYS_KERNHIST_H_
+
+#if defined(_KERNEL_OPT)
+#include "opt_kernhist.h"
+#endif
+
+#include <sys/queue.h>
+#ifdef KERNHIST
+#include <sys/cpu.h>
+#endif
+
+/*
+ * kernel history/tracing, was uvm_stat
+ */
+
+struct kern_history_ent {
+ struct timeval tv; /* time stamp */
+ int cpunum;
+ const char *fmt; /* printf format */
+ size_t fmtlen; /* length of printf format */
+ const char *fn; /* function name */
+ size_t fnlen; /* length of function name */
+ u_long call; /* function call number */
+ u_long v[4]; /* values */
+};
+
+struct kern_history {
+ const char *name; /* name of this history */
+ size_t namelen; /* length of name, not including null */
+ LIST_ENTRY(kern_history) list; /* link on list of all histories */
+ unsigned int n; /* number of entries */
+ unsigned int f; /* next free one */
+ struct kern_history_ent *e; /* the allocated entries */
+};
+
+LIST_HEAD(kern_history_head, kern_history);
+
+/*
+ * grovelling lists all at once. we currently do not allow more than
+ * 32 histories to exist, as the way to dump a number of them at once
+ * is by calling kern_hist() with a bitmask.
+ *
+ * XXX extend this to have a registration function? however, there
+ * needs to be static ones as UVM requires this before almost anything
+ * else is setup.
+ */
+
+/* this is used to set the size of some arrays */
+#define MAXHISTS 32
+
+/* and these are the bit values of each history */
+#define KERNHIST_UVMMAPHIST 0x00000001 /* maphist */
+#define KERNHIST_UVMPDHIST 0x00000002 /* pdhist */
+#define KERNHIST_UVMUBCHIST 0x00000004 /* ubchist */
+#define KERNHIST_UVMLOANHIST 0x00000008 /* loanhist */
+
+#ifdef _KERNEL
+
+/*
+ * macros to use the history/tracing code. note that KERNHIST_LOG
+ * must take 4 arguments (even if they are ignored by the format).
+ */
+#ifndef KERNHIST
+#define KERNHIST_DECL(NAME)
+#define KERNHIST_INIT(NAME,N)
+#define KERNHIST_INIT_STATIC(NAME,BUF)
+#define KERNHIST_LOG(NAME,FMT,A,B,C,D)
+#define KERNHIST_CALLED(NAME)
+#define KERNHIST_FUNC(FNAME)
+#define kernhist_dump(NAME)
+#else
+#include <sys/kernel.h> /* for "cold" variable */
+#include <sys/atomic.h>
+#include <sys/kmem.h>
+
+extern struct kern_history_head kern_histories;
+
+#define KERNHIST_DECL(NAME) struct kern_history NAME
+
+#define KERNHIST_INIT(NAME,N) \
+do { \
+ (NAME).name = __STRING(NAME); \
+ (NAME).namelen = strlen(__STRING(NAME)); \
+ (NAME).n = (N); \
+ (NAME).f = 0; \
+ (NAME).e = (struct kern_history_ent *) \
+ kmem_zalloc(sizeof(struct kern_history_ent) * (N), KM_SLEEP); \
+ LIST_INSERT_HEAD(&kern_histories, &(NAME), list); \
+} while (/*CONSTCOND*/ 0)
+
+#define KERNHIST_INIT_STATIC(NAME,BUF) \
+do { \
+ (NAME).name = __STRING(NAME); \
+ (NAME).namelen = strlen(__STRING(NAME)); \
+ (NAME).n = sizeof(BUF) / sizeof(struct kern_history_ent); \
+ (NAME).f = 0; \
+ (NAME).e = (struct kern_history_ent *) (BUF); \
+ memset((NAME).e, 0, sizeof(struct kern_history_ent) * (NAME).n); \
+ LIST_INSERT_HEAD(&kern_histories, &(NAME), list); \
+} while (/*CONSTCOND*/ 0)
+
+#if defined(KERNHIST_PRINT)
+extern int kernhist_print_enabled;
+#define KERNHIST_PRINTNOW(E) \
+do { \
+ if (kernhist_print_enabled) { \
+ kernhist_entry_print(E); \
+ DELAY(100000); \
+ } \
+} while (/*CONSTCOND*/ 0)
+#else
+#define KERNHIST_PRINTNOW(E) /* nothing */
+#endif
+
+#define KERNHIST_LOG(NAME,FMT,A,B,C,D) \
+do { \
+ unsigned int _i_, _j_; \
+ do { \
+ _i_ = (NAME).f; \
+ _j_ = (_i_ + 1 < (NAME).n) ? _i_ + 1 : 0; \
+ } while (atomic_cas_uint(&(NAME).f, _i_, _j_) != _i_); \
+ if (!cold) \
+ microtime(&(NAME).e[_i_].tv); \
+ (NAME).e[_i_].cpunum = cpu_number(); \
+ (NAME).e[_i_].fmt = (FMT); \
+ (NAME).e[_i_].fmtlen = strlen(FMT); \
+ (NAME).e[_i_].fn = _kernhist_name; \
+ (NAME).e[_i_].fnlen = strlen(_kernhist_name); \
+ (NAME).e[_i_].call = _kernhist_call; \
+ (NAME).e[_i_].v[0] = (u_long)(A); \
+ (NAME).e[_i_].v[1] = (u_long)(B); \
+ (NAME).e[_i_].v[2] = (u_long)(C); \
+ (NAME).e[_i_].v[3] = (u_long)(D); \
+ KERNHIST_PRINTNOW(&((NAME).e[_i_])); \
+} while (/*CONSTCOND*/ 0)
+
+#define KERNHIST_CALLED(NAME) \
+do { \
+ _kernhist_call = atomic_inc_uint_nv(&_kernhist_cnt); \
+ KERNHIST_LOG(NAME,"called!", 0, 0, 0, 0); \
+} while (/*CONSTCOND*/ 0)
+
+#define KERNHIST_FUNC(FNAME) \
+ static unsigned int _kernhist_cnt = 0; \
+ static const char *const _kernhist_name = FNAME; \
+ int _kernhist_call = 0;
+
+static inline void kernhist_entry_print(struct kern_history_ent *);
+
+static inline void
+kernhist_entry_print(e)
+ struct kern_history_ent *e;
+{
+ printf("%06" PRIu64 ".%06d ", e->tv.tv_sec, e->tv.tv_usec);
+ printf("%s#%ld@%d: ", e->fn, e->call, e->cpunum);
+ printf(e->fmt, e->v[0], e->v[1], e->v[2], e->v[3]);
+ printf("\n");
+}
+
+#if defined(DDB)
+void kernhist_print(void (*)(const char *, ...));
+#endif /* DDB */
+
+#endif /* KERNHIST */
+
+#endif /* _KERNEL */
+
+#endif /* _SYS_KERNHIST_H_ */