- 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.
|
* Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#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/types.h>
|
||||||
#include <sys/param.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
|
#define LOCKSTAT_HASH_SHIFT 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LOCKSTAT_MINBUFS 100
|
#define LOCKSTAT_MINBUFS 1000
|
||||||
#define LOCKSTAT_DEFBUFS 1000
|
#define LOCKSTAT_DEFBUFS 10000
|
||||||
#define LOCKSTAT_MAXBUFS 10000
|
#define LOCKSTAT_MAXBUFS 50000
|
||||||
|
|
||||||
#define LOCKSTAT_HASH_SIZE 64
|
#define LOCKSTAT_HASH_SIZE 64
|
||||||
#define LOCKSTAT_HASH_MASK (LOCKSTAT_HASH_SIZE - 1)
|
#define LOCKSTAT_HASH_MASK (LOCKSTAT_HASH_SIZE - 1)
|
||||||
|
@ -103,6 +103,7 @@ volatile u_int lockstat_enabled;
|
||||||
uintptr_t lockstat_csstart;
|
uintptr_t lockstat_csstart;
|
||||||
uintptr_t lockstat_csend;
|
uintptr_t lockstat_csend;
|
||||||
uintptr_t lockstat_csmask;
|
uintptr_t lockstat_csmask;
|
||||||
|
uintptr_t lockstat_lamask;
|
||||||
uintptr_t lockstat_lockstart;
|
uintptr_t lockstat_lockstart;
|
||||||
uintptr_t lockstat_lockend;
|
uintptr_t lockstat_lockend;
|
||||||
|
|
||||||
|
@ -236,6 +237,11 @@ lockstat_start(lsenable_t *le)
|
||||||
else
|
else
|
||||||
lockstat_csmask = 0;
|
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_csstart = le->le_csstart;
|
||||||
lockstat_csend = le->le_csend;
|
lockstat_csend = le->le_csend;
|
||||||
lockstat_lockstart = le->le_lockstart;
|
lockstat_lockstart = le->le_lockstart;
|
||||||
|
@ -373,6 +379,7 @@ lockstat_event(uintptr_t lock, uintptr_t callsite, u_int flags, u_int count,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
callsite &= lockstat_csmask;
|
callsite &= lockstat_csmask;
|
||||||
|
lock &= lockstat_lamask;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the table for this lock+callsite pair, and try to locate a
|
* 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.
|
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
|
|
||||||
#define IOC_LOCKSTAT_GVERSION _IOR('L', 0, int)
|
#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
|
* 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_CALLSITE 0x01 /* track call sites */
|
||||||
#define LE_ONE_CALLSITE 0x02 /* specific call site */
|
#define LE_ONE_CALLSITE 0x02 /* specific call site */
|
||||||
#define LE_ONE_LOCK 0x04 /* specific lock */
|
#define LE_ONE_LOCK 0x04 /* specific lock */
|
||||||
|
#define LE_LOCK 0x08 /* track locks */
|
||||||
|
|
||||||
typedef struct lsenable {
|
typedef struct lsenable {
|
||||||
uintptr_t le_csstart; /* callsite start */
|
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.
|
* Copyright (c) 2006 The NetBSD Foundation, Inc.
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#if !defined(lint)
|
#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
|
#endif
|
||||||
|
|
||||||
#ifndef ELFSIZE
|
#ifndef ELFSIZE
|
||||||
|
@ -217,6 +217,11 @@ NAME(findsym)(findsym_t find, char *name, uintptr_t *start, uintptr_t *end)
|
||||||
if (*start < sa || *start > ea)
|
if (*start < sa || *start > ea)
|
||||||
break;
|
break;
|
||||||
off = (int)(*start - sa);
|
off = (int)(*start - sa);
|
||||||
|
*start = sa;
|
||||||
|
if (end != NULL)
|
||||||
|
*end = ea;
|
||||||
|
if (name == NULL)
|
||||||
|
goto found;
|
||||||
if (off == 0)
|
if (off == 0)
|
||||||
strlcpy(name, &strp[symp[i].st_name],
|
strlcpy(name, &strp[symp[i].st_name],
|
||||||
NAME_SIZE);
|
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.
|
.\" All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
.\" 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
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd September 1, 2006
|
.Dd July 14, 2007
|
||||||
.Dt LOCKSTAT 8
|
.Dt LOCKSTAT 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
.Nd display kernel locking statistics
|
.Nd display kernel locking statistics
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl celpst
|
.Op Fl ceflMmpst
|
||||||
.Op Fl b Ar nbuf
|
.Op Fl b Ar nbuf
|
||||||
.Op Fl E Ar event
|
.Op Fl E Ar event
|
||||||
.Op Fl F Ar func
|
.Op Fl F Ar func
|
||||||
|
@ -86,6 +86,8 @@ option to list valid events.
|
||||||
List valid event types for the
|
List valid event types for the
|
||||||
.Fl E
|
.Fl E
|
||||||
option and exit.
|
option and exit.
|
||||||
|
.It Fl f
|
||||||
|
Trace only by calling functions; do not report on individual locks.
|
||||||
.It Fl F Ar func
|
.It Fl F Ar func
|
||||||
Limit tracing to locking operations performed within the specified function.
|
Limit tracing to locking operations performed within the specified function.
|
||||||
.Ar func
|
.Ar func
|
||||||
|
@ -97,6 +99,10 @@ may either be the name of a lock object in the kernel, or a kernel virtual
|
||||||
address.
|
address.
|
||||||
.It Fl l
|
.It Fl l
|
||||||
Trace only by lock; do not report on calling functions.
|
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
|
.It Fl N Ar nlist
|
||||||
Extract symbol information from the
|
Extract symbol information from the
|
||||||
.Ar nlist
|
.Ar nlist
|
||||||
|
@ -137,16 +143,27 @@ namelist
|
||||||
.El
|
.El
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
# lockstat sleep 10
|
# lockstat -T kernel_lock sleep 10
|
||||||
Elapsed time: 10.02s
|
Elapsed time: 10.01 seconds.
|
||||||
|
|
||||||
-- Spin mutex spin
|
-- Kernel lock spin
|
||||||
|
|
||||||
Total% Count Time/ms Lock Caller
|
Total% Count Time/ms Lock Caller
|
||||||
------ ------- --------- -------------- -------------------------------
|
------ ------- --------- ---------------------- ------------------------------
|
||||||
100.00 1576 44.27 kernel_mutex \*[Lt]all\*[Gt]
|
100.00 74941 1545.54 kernel_lock <all>
|
||||||
95.71 1493 42.46 kernel_mutex _kernel_lock+0xd1
|
43.54 28467 673.00 kernel_lock trap+71e
|
||||||
4.29 82 1.80 kernel_mutex _kernel_lock_acquire_count+0xb0
|
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
|
.Ed
|
||||||
.Sh DIAGNOSTICS
|
.Sh DIAGNOSTICS
|
||||||
.Bl -diag
|
.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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This code is derived from software contributed to The NetBSD Foundation
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#ifndef lint
|
#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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#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 <util.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
|
|
||||||
|
@ -138,9 +139,10 @@ locklist_t sortlist;
|
||||||
|
|
||||||
lsbuf_t *bufs;
|
lsbuf_t *bufs;
|
||||||
lsdisable_t ld;
|
lsdisable_t ld;
|
||||||
int lflag;
|
bool lflag;
|
||||||
|
bool fflag;
|
||||||
int nbufs;
|
int nbufs;
|
||||||
int cflag;
|
bool cflag;
|
||||||
int lsfd;
|
int lsfd;
|
||||||
int displayed;
|
int displayed;
|
||||||
int bin64;
|
int bin64;
|
||||||
|
@ -149,11 +151,12 @@ double cscale;
|
||||||
double cpuscale[sizeof(ld.ld_freq) / sizeof(ld.ld_freq[0])];
|
double cpuscale[sizeof(ld.ld_freq) / sizeof(ld.ld_freq[0])];
|
||||||
FILE *outfp;
|
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 spawn(int, char **);
|
||||||
void display(int, const char *name);
|
void display(int, const char *name);
|
||||||
void listnames(const name_t *);
|
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 makelists(int, int);
|
||||||
void nullsig(int);
|
void nullsig(int);
|
||||||
void usage(void);
|
void usage(void);
|
||||||
|
@ -163,7 +166,8 @@ lock_t *morelocks(void);
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
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;
|
const char *nlistf, *outf;
|
||||||
char *lockname, *funcname;
|
char *lockname, *funcname;
|
||||||
const name_t *name;
|
const name_t *name;
|
||||||
|
@ -178,10 +182,12 @@ main(int argc, char **argv)
|
||||||
eventtype = -1;
|
eventtype = -1;
|
||||||
locktype = -1;
|
locktype = -1;
|
||||||
nbufs = 0;
|
nbufs = 0;
|
||||||
sflag = 0;
|
sflag = false;
|
||||||
pflag = 0;
|
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) {
|
switch (ch) {
|
||||||
case 'E':
|
case 'E':
|
||||||
eventtype = matchname(eventnames, optarg);
|
eventtype = matchname(eventnames, optarg);
|
||||||
|
@ -204,22 +210,31 @@ main(int argc, char **argv)
|
||||||
usage();
|
usage();
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
cflag = 1;
|
cflag = true;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
listnames(eventnames);
|
listnames(eventnames);
|
||||||
break;
|
break;
|
||||||
|
case 'f':
|
||||||
|
fflag = true;
|
||||||
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
lflag = 1;
|
lflag = true;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
mflag = true;
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
Mflag = true;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
outf = optarg;
|
outf = optarg;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
pflag = 1;
|
pflag = true;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
sflag = 1;
|
sflag = true;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
listnames(locknames);
|
listnames(locknames);
|
||||||
|
@ -270,15 +285,17 @@ main(int argc, char **argv)
|
||||||
*/
|
*/
|
||||||
if (lockname != NULL) {
|
if (lockname != NULL) {
|
||||||
findsym(LOCK_BYNAME, lockname, &le.le_lockstart,
|
findsym(LOCK_BYNAME, lockname, &le.le_lockstart,
|
||||||
&le.le_lockend);
|
&le.le_lockend, true);
|
||||||
le.le_flags |= LE_ONE_LOCK;
|
le.le_flags |= LE_ONE_LOCK;
|
||||||
}
|
}
|
||||||
if (!lflag)
|
if (!lflag)
|
||||||
le.le_flags |= LE_CALLSITE;
|
le.le_flags |= LE_CALLSITE;
|
||||||
|
if (!fflag)
|
||||||
|
le.le_flags |= LE_LOCK;
|
||||||
if (funcname != NULL) {
|
if (funcname != NULL) {
|
||||||
if (lflag)
|
if (lflag)
|
||||||
usage();
|
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_flags |= LE_ONE_CALLSITE;
|
||||||
}
|
}
|
||||||
le.le_mask = (eventtype & LB_EVENT_MASK) | (locktype & LB_LOCK_MASK);
|
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(&sortlist);
|
||||||
TAILQ_INIT(&freelist);
|
TAILQ_INIT(&freelist);
|
||||||
|
|
||||||
|
if ((mflag | Mflag) != 0)
|
||||||
|
collapse(mflag, Mflag);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Display the results.
|
* Display the results.
|
||||||
*/
|
*/
|
||||||
|
@ -381,9 +401,12 @@ usage(void)
|
||||||
"-c\t\treport percentage of total events by count, not time\n"
|
"-c\t\treport percentage of total events by count, not time\n"
|
||||||
"-E evt\t\tdisplay only one type of event\n"
|
"-E evt\t\tdisplay only one type of event\n"
|
||||||
"-e\t\tlist event types\n"
|
"-e\t\tlist event types\n"
|
||||||
|
"-f\t\ttrace only by function\n"
|
||||||
"-F func\t\tlimit trace to one function\n"
|
"-F func\t\tlimit trace to one function\n"
|
||||||
"-L lock\t\tlimit trace to one lock (name, or address)\n"
|
"-L lock\t\tlimit trace to one lock (name, or address)\n"
|
||||||
"-l\t\ttrace only by lock\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"
|
"-N nlist\tspecify name list file\n"
|
||||||
"-o file\t\tsend output to named file, not stdout\n"
|
"-o file\t\tsend output to named file, not stdout\n"
|
||||||
"-p\t\tshow average count/time per CPU, not total\n"
|
"-p\t\tshow average count/time per CPU, not total\n"
|
||||||
|
@ -413,16 +436,33 @@ listnames(const name_t *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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++)
|
empty = 1;
|
||||||
if (strcasecmp(name->name, string) == 0)
|
mask = 0;
|
||||||
return name->mask;
|
|
||||||
|
|
||||||
warnx("unknown type `%s'", string);
|
while ((sp = strsep(&string, ",")) != NULL) {
|
||||||
usage();
|
if (*sp == '\0')
|
||||||
return 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.
|
* Call into the ELF parser and look up a symbol by name or by address.
|
||||||
*/
|
*/
|
||||||
void
|
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;
|
char *p;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
if (!chg) {
|
||||||
|
sa = *start;
|
||||||
|
start = &sa;
|
||||||
|
end = &ea;
|
||||||
|
}
|
||||||
|
|
||||||
if (end == NULL)
|
if (end == NULL)
|
||||||
end = &tend;
|
end = &tend;
|
||||||
|
|
||||||
|
@ -523,6 +569,26 @@ morelocks(void)
|
||||||
return l;
|
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
|
* From the kernel supplied data, construct two dimensional lists of locks
|
||||||
* and event buffers, indexed by lock type and sorted by event type.
|
* and event buffers, indexed by lock type and sorted by event type.
|
||||||
|
@ -698,7 +764,7 @@ display(int mask, const char *name)
|
||||||
metric *= pcscale;
|
metric *= pcscale;
|
||||||
|
|
||||||
if (l->name[0] == '\0')
|
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)
|
if (lflag || l->nbufs > 1)
|
||||||
fprintf(outfp, "%6.2f %7d %9.2f %-22s <all>\n",
|
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 = lb->lb_times[event];
|
||||||
metric *= pcscale;
|
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",
|
fprintf(outfp, "%6.2f %7d %9.2f %-22s %s\n",
|
||||||
metric, (int)(lb->lb_counts[event] * cscale),
|
metric, (int)(lb->lb_counts[event] * cscale),
|
||||||
lb->lb_times[event] * tscale, l->name, fname);
|
lb->lb_times[event] * tscale, l->name, fname);
|
||||||
|
|
Loading…
Reference in New Issue