- Increase default number of trace buffers to 10000.
- New options: -f Trace only by calling functions. -m Merge call sites within unique functions. -M Merge lock addresses within unique objects.
This commit is contained in:
parent
8f6e6386cb
commit
5c2240bb95
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: lockstat.c,v 1.9 2007/06/15 20:17:07 ad Exp $ */
|
||||
/* $NetBSD: lockstat.c,v 1.10 2007/07/14 13:30:44 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
|
||||
|
@ -44,7 +44,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lockstat.c,v 1.9 2007/06/15 20:17:07 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lockstat.c,v 1.10 2007/07/14 13:30:44 ad Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -69,9 +69,9 @@ __KERNEL_RCSID(0, "$NetBSD: lockstat.c,v 1.9 2007/06/15 20:17:07 ad Exp $");
|
|||
#define LOCKSTAT_HASH_SHIFT 2
|
||||
#endif
|
||||
|
||||
#define LOCKSTAT_MINBUFS 100
|
||||
#define LOCKSTAT_DEFBUFS 1000
|
||||
#define LOCKSTAT_MAXBUFS 10000
|
||||
#define LOCKSTAT_MINBUFS 1000
|
||||
#define LOCKSTAT_DEFBUFS 10000
|
||||
#define LOCKSTAT_MAXBUFS 50000
|
||||
|
||||
#define LOCKSTAT_HASH_SIZE 64
|
||||
#define LOCKSTAT_HASH_MASK (LOCKSTAT_HASH_SIZE - 1)
|
||||
|
@ -103,6 +103,7 @@ volatile u_int lockstat_enabled;
|
|||
uintptr_t lockstat_csstart;
|
||||
uintptr_t lockstat_csend;
|
||||
uintptr_t lockstat_csmask;
|
||||
uintptr_t lockstat_lamask;
|
||||
uintptr_t lockstat_lockstart;
|
||||
uintptr_t lockstat_lockend;
|
||||
|
||||
|
@ -236,6 +237,11 @@ lockstat_start(lsenable_t *le)
|
|||
else
|
||||
lockstat_csmask = 0;
|
||||
|
||||
if ((le->le_flags & LE_LOCK) != 0)
|
||||
lockstat_lamask = (uintptr_t)-1LL;
|
||||
else
|
||||
lockstat_lamask = 0;
|
||||
|
||||
lockstat_csstart = le->le_csstart;
|
||||
lockstat_csend = le->le_csend;
|
||||
lockstat_lockstart = le->le_lockstart;
|
||||
|
@ -373,6 +379,7 @@ lockstat_event(uintptr_t lock, uintptr_t callsite, u_int flags, u_int count,
|
|||
return;
|
||||
|
||||
callsite &= lockstat_csmask;
|
||||
lock &= lockstat_lamask;
|
||||
|
||||
/*
|
||||
* Find the table for this lock+callsite pair, and try to locate a
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: lockstat.h,v 1.4 2007/02/09 21:55:26 ad Exp $ */
|
||||
/* $NetBSD: lockstat.h,v 1.5 2007/07/14 13:30:44 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
|
@ -59,7 +59,7 @@
|
|||
|
||||
#define IOC_LOCKSTAT_GVERSION _IOR('L', 0, int)
|
||||
|
||||
#define LS_VERSION 3
|
||||
#define LS_VERSION 4
|
||||
|
||||
/*
|
||||
* Enable request. We can limit tracing by the call site and by
|
||||
|
@ -72,6 +72,7 @@
|
|||
#define LE_CALLSITE 0x01 /* track call sites */
|
||||
#define LE_ONE_CALLSITE 0x02 /* specific call site */
|
||||
#define LE_ONE_LOCK 0x04 /* specific lock */
|
||||
#define LE_LOCK 0x08 /* track locks */
|
||||
|
||||
typedef struct lsenable {
|
||||
uintptr_t le_csstart; /* callsite start */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: elf32.c,v 1.5 2006/12/25 11:57:40 ad Exp $ */
|
||||
/* $NetBSD: elf32.c,v 1.6 2007/07/14 13:30:43 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
|
@ -72,7 +72,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: elf32.c,v 1.5 2006/12/25 11:57:40 ad Exp $");
|
||||
__RCSID("$NetBSD: elf32.c,v 1.6 2007/07/14 13:30:43 ad Exp $");
|
||||
#endif
|
||||
|
||||
#ifndef ELFSIZE
|
||||
|
@ -217,6 +217,11 @@ NAME(findsym)(findsym_t find, char *name, uintptr_t *start, uintptr_t *end)
|
|||
if (*start < sa || *start > ea)
|
||||
break;
|
||||
off = (int)(*start - sa);
|
||||
*start = sa;
|
||||
if (end != NULL)
|
||||
*end = ea;
|
||||
if (name == NULL)
|
||||
goto found;
|
||||
if (off == 0)
|
||||
strlcpy(name, &strp[symp[i].st_name],
|
||||
NAME_SIZE);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" $NetBSD: lockstat.8,v 1.5 2006/12/15 20:25:55 ad Exp $
|
||||
.\" $NetBSD: lockstat.8,v 1.6 2007/07/14 13:30:43 ad Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
.\" Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -34,7 +34,7 @@
|
|||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd September 1, 2006
|
||||
.Dd July 14, 2007
|
||||
.Dt LOCKSTAT 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -42,7 +42,7 @@
|
|||
.Nd display kernel locking statistics
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl celpst
|
||||
.Op Fl ceflMmpst
|
||||
.Op Fl b Ar nbuf
|
||||
.Op Fl E Ar event
|
||||
.Op Fl F Ar func
|
||||
|
@ -86,6 +86,8 @@ option to list valid events.
|
|||
List valid event types for the
|
||||
.Fl E
|
||||
option and exit.
|
||||
.It Fl f
|
||||
Trace only by calling functions; do not report on individual locks.
|
||||
.It Fl F Ar func
|
||||
Limit tracing to locking operations performed within the specified function.
|
||||
.Ar func
|
||||
|
@ -97,6 +99,10 @@ may either be the name of a lock object in the kernel, or a kernel virtual
|
|||
address.
|
||||
.It Fl l
|
||||
Trace only by lock; do not report on calling functions.
|
||||
.It Fl m
|
||||
Merge call sites within unique functions.
|
||||
.It Fl M
|
||||
Merge lock addresses within unique objects.
|
||||
.It Fl N Ar nlist
|
||||
Extract symbol information from the
|
||||
.Ar nlist
|
||||
|
@ -137,16 +143,27 @@ namelist
|
|||
.El
|
||||
.Sh EXAMPLES
|
||||
.Bd -literal
|
||||
# lockstat sleep 10
|
||||
Elapsed time: 10.02s
|
||||
# lockstat -T kernel_lock sleep 10
|
||||
Elapsed time: 10.01 seconds.
|
||||
|
||||
-- Spin mutex spin
|
||||
-- Kernel lock spin
|
||||
|
||||
Total% Count Time/ms Lock Caller
|
||||
------ ------- --------- -------------- -------------------------------
|
||||
100.00 1576 44.27 kernel_mutex \*[Lt]all\*[Gt]
|
||||
95.71 1493 42.46 kernel_mutex _kernel_lock+0xd1
|
||||
4.29 82 1.80 kernel_mutex _kernel_lock_acquire_count+0xb0
|
||||
Total% Count Time/ms Lock Caller
|
||||
------ ------- --------- ---------------------- ------------------------------
|
||||
100.00 74941 1545.54 kernel_lock <all>
|
||||
43.54 28467 673.00 kernel_lock trap+71e
|
||||
42.87 34466 662.51 kernel_lock syscall_plain+111
|
||||
7.38 7565 114.14 kernel_lock uiomove+17a
|
||||
1.92 1221 29.61 kernel_lock sleepq_block+20b
|
||||
1.84 1759 28.40 kernel_lock trap+706
|
||||
0.81 124 12.54 kernel_lock x86_softintlock+1a
|
||||
0.64 587 9.87 kernel_lock pmap_load+2a6
|
||||
0.52 214 8.10 kernel_lock intr_biglock_wrapper+1e
|
||||
0.20 219 3.09 kernel_lock pmap_load+323
|
||||
0.14 175 2.12 kernel_lock do_sys_wait+2d0
|
||||
0.09 85 1.43 kernel_lock lwp_startup+66
|
||||
0.04 49 0.64 kernel_lock sleepq_block+18c
|
||||
0.01 10 0.12 kernel_lock lwp_userret+3c
|
||||
.Ed
|
||||
.Sh DIAGNOSTICS
|
||||
.Bl -diag
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: main.c,v 1.8 2007/01/20 20:01:03 ad Exp $ */
|
||||
/* $NetBSD: main.c,v 1.9 2007/07/14 13:30:44 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -49,7 +49,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: main.c,v 1.8 2007/01/20 20:01:03 ad Exp $");
|
||||
__RCSID("$NetBSD: main.c,v 1.9 2007/07/14 13:30:44 ad Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
@ -73,6 +73,7 @@ __RCSID("$NetBSD: main.c,v 1.8 2007/01/20 20:01:03 ad Exp $");
|
|||
#include <util.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
|
@ -138,9 +139,10 @@ locklist_t sortlist;
|
|||
|
||||
lsbuf_t *bufs;
|
||||
lsdisable_t ld;
|
||||
int lflag;
|
||||
bool lflag;
|
||||
bool fflag;
|
||||
int nbufs;
|
||||
int cflag;
|
||||
bool cflag;
|
||||
int lsfd;
|
||||
int displayed;
|
||||
int bin64;
|
||||
|
@ -149,11 +151,12 @@ double cscale;
|
|||
double cpuscale[sizeof(ld.ld_freq) / sizeof(ld.ld_freq[0])];
|
||||
FILE *outfp;
|
||||
|
||||
void findsym(findsym_t, char *, uintptr_t *, uintptr_t *);
|
||||
void findsym(findsym_t, char *, uintptr_t *, uintptr_t *, bool);
|
||||
void spawn(int, char **);
|
||||
void display(int, const char *name);
|
||||
void listnames(const name_t *);
|
||||
int matchname(const name_t *, const char *);
|
||||
void collapse(bool, bool);
|
||||
int matchname(const name_t *, char *);
|
||||
void makelists(int, int);
|
||||
void nullsig(int);
|
||||
void usage(void);
|
||||
|
@ -163,7 +166,8 @@ lock_t *morelocks(void);
|
|||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int eventtype, locktype, ch, nlfd, sflag, fd, i, pflag;
|
||||
int eventtype, locktype, ch, nlfd, fd, i;
|
||||
bool sflag, pflag, mflag, Mflag;
|
||||
const char *nlistf, *outf;
|
||||
char *lockname, *funcname;
|
||||
const name_t *name;
|
||||
|
@ -178,10 +182,12 @@ main(int argc, char **argv)
|
|||
eventtype = -1;
|
||||
locktype = -1;
|
||||
nbufs = 0;
|
||||
sflag = 0;
|
||||
pflag = 0;
|
||||
sflag = false;
|
||||
pflag = false;
|
||||
mflag = false;
|
||||
Mflag = false;
|
||||
|
||||
while ((ch = getopt(argc, argv, "E:F:L:M:N:T:b:ceflo:pst")) != -1)
|
||||
while ((ch = getopt(argc, argv, "E:F:L:MN:T:b:ceflmo:pst")) != -1)
|
||||
switch (ch) {
|
||||
case 'E':
|
||||
eventtype = matchname(eventnames, optarg);
|
||||
|
@ -204,22 +210,31 @@ main(int argc, char **argv)
|
|||
usage();
|
||||
break;
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
cflag = true;
|
||||
break;
|
||||
case 'e':
|
||||
listnames(eventnames);
|
||||
break;
|
||||
case 'f':
|
||||
fflag = true;
|
||||
break;
|
||||
case 'l':
|
||||
lflag = 1;
|
||||
lflag = true;
|
||||
break;
|
||||
case 'm':
|
||||
mflag = true;
|
||||
break;
|
||||
case 'M':
|
||||
Mflag = true;
|
||||
break;
|
||||
case 'o':
|
||||
outf = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
pflag = true;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
sflag = true;
|
||||
break;
|
||||
case 't':
|
||||
listnames(locknames);
|
||||
|
@ -270,15 +285,17 @@ main(int argc, char **argv)
|
|||
*/
|
||||
if (lockname != NULL) {
|
||||
findsym(LOCK_BYNAME, lockname, &le.le_lockstart,
|
||||
&le.le_lockend);
|
||||
&le.le_lockend, true);
|
||||
le.le_flags |= LE_ONE_LOCK;
|
||||
}
|
||||
if (!lflag)
|
||||
le.le_flags |= LE_CALLSITE;
|
||||
if (!fflag)
|
||||
le.le_flags |= LE_LOCK;
|
||||
if (funcname != NULL) {
|
||||
if (lflag)
|
||||
usage();
|
||||
findsym(FUNC_BYNAME, funcname, &le.le_csstart, &le.le_csend);
|
||||
findsym(FUNC_BYNAME, funcname, &le.le_csstart, &le.le_csend, true);
|
||||
le.le_flags |= LE_ONE_CALLSITE;
|
||||
}
|
||||
le.le_mask = (eventtype & LB_EVENT_MASK) | (locktype & LB_LOCK_MASK);
|
||||
|
@ -340,6 +357,9 @@ main(int argc, char **argv)
|
|||
TAILQ_INIT(&sortlist);
|
||||
TAILQ_INIT(&freelist);
|
||||
|
||||
if ((mflag | Mflag) != 0)
|
||||
collapse(mflag, Mflag);
|
||||
|
||||
/*
|
||||
* Display the results.
|
||||
*/
|
||||
|
@ -381,9 +401,12 @@ usage(void)
|
|||
"-c\t\treport percentage of total events by count, not time\n"
|
||||
"-E evt\t\tdisplay only one type of event\n"
|
||||
"-e\t\tlist event types\n"
|
||||
"-f\t\ttrace only by function\n"
|
||||
"-F func\t\tlimit trace to one function\n"
|
||||
"-L lock\t\tlimit trace to one lock (name, or address)\n"
|
||||
"-l\t\ttrace only by lock\n"
|
||||
"-m\t\tmerge call sites within unique functions\n"
|
||||
"-M\t\tmerge lock addresses within unique objects\n"
|
||||
"-N nlist\tspecify name list file\n"
|
||||
"-o file\t\tsend output to named file, not stdout\n"
|
||||
"-p\t\tshow average count/time per CPU, not total\n"
|
||||
|
@ -413,16 +436,33 @@ listnames(const name_t *name)
|
|||
}
|
||||
|
||||
int
|
||||
matchname(const name_t *name, const char *string)
|
||||
matchname(const name_t *name, char *string)
|
||||
{
|
||||
int empty, mask;
|
||||
char *sp;
|
||||
|
||||
for (; name->name != NULL; name++)
|
||||
if (strcasecmp(name->name, string) == 0)
|
||||
return name->mask;
|
||||
empty = 1;
|
||||
mask = 0;
|
||||
|
||||
warnx("unknown type `%s'", string);
|
||||
usage();
|
||||
return 0;
|
||||
while ((sp = strsep(&string, ",")) != NULL) {
|
||||
if (*sp == '\0')
|
||||
usage();
|
||||
|
||||
for (; name->name != NULL; name++) {
|
||||
if (strcasecmp(name->name, sp) == 0) {
|
||||
mask |= name->mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name->name == NULL)
|
||||
errx(EXIT_FAILURE, "unknown identifier `%s'", sp);
|
||||
empty = 0;
|
||||
}
|
||||
|
||||
if (empty)
|
||||
usage();
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -447,12 +487,18 @@ ncpu(void)
|
|||
* Call into the ELF parser and look up a symbol by name or by address.
|
||||
*/
|
||||
void
|
||||
findsym(findsym_t find, char *name, uintptr_t *start, uintptr_t *end)
|
||||
findsym(findsym_t find, char *name, uintptr_t *start, uintptr_t *end, bool chg)
|
||||
{
|
||||
uintptr_t tend;
|
||||
uintptr_t tend, sa, ea;
|
||||
char *p;
|
||||
int rv;
|
||||
|
||||
if (!chg) {
|
||||
sa = *start;
|
||||
start = &sa;
|
||||
end = &ea;
|
||||
}
|
||||
|
||||
if (end == NULL)
|
||||
end = &tend;
|
||||
|
||||
|
@ -523,6 +569,26 @@ morelocks(void)
|
|||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Collapse addresses from unique objects.
|
||||
*/
|
||||
void
|
||||
collapse(bool func, bool lock)
|
||||
{
|
||||
lsbuf_t *lb, *max;
|
||||
|
||||
for (lb = bufs, max = bufs + nbufs; lb < max; lb++) {
|
||||
if (func && lb->lb_callsite != 0) {
|
||||
findsym(FUNC_BYADDR, NULL, &lb->lb_callsite, NULL,
|
||||
true);
|
||||
}
|
||||
if (lock && lb->lb_lock != 0) {
|
||||
findsym(LOCK_BYADDR, NULL, &lb->lb_lock, NULL,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* From the kernel supplied data, construct two dimensional lists of locks
|
||||
* and event buffers, indexed by lock type and sorted by event type.
|
||||
|
@ -698,7 +764,7 @@ display(int mask, const char *name)
|
|||
metric *= pcscale;
|
||||
|
||||
if (l->name[0] == '\0')
|
||||
findsym(LOCK_BYADDR, l->name, &l->lock, NULL);
|
||||
findsym(LOCK_BYADDR, l->name, &l->lock, NULL, false);
|
||||
|
||||
if (lflag || l->nbufs > 1)
|
||||
fprintf(outfp, "%6.2f %7d %9.2f %-22s <all>\n",
|
||||
|
@ -715,7 +781,8 @@ display(int mask, const char *name)
|
|||
metric = lb->lb_times[event];
|
||||
metric *= pcscale;
|
||||
|
||||
findsym(FUNC_BYADDR, fname, &lb->lb_callsite, NULL);
|
||||
findsym(FUNC_BYADDR, fname, &lb->lb_callsite, NULL,
|
||||
false);
|
||||
fprintf(outfp, "%6.2f %7d %9.2f %-22s %s\n",
|
||||
metric, (int)(lb->lb_counts[event] * cscale),
|
||||
lb->lb_times[event] * tscale, l->name, fname);
|
||||
|
|
Loading…
Reference in New Issue