summaryrefslogtreecommitdiffstats
path: root/cddl
diff options
context:
space:
mode:
authormarkj <markj@FreeBSD.org>2015-09-30 05:46:56 +0000
committermarkj <markj@FreeBSD.org>2015-09-30 05:46:56 +0000
commita6fac84fcf38d1a17650296ab2f345d62e855db1 (patch)
tree729bcc4069ad5e5c942c0b90142c5fec64dadc29 /cddl
parent5f05617bfc4be8dddb44c324b5036b2a08f969a5 (diff)
downloadFreeBSD-src-a6fac84fcf38d1a17650296ab2f345d62e855db1.zip
FreeBSD-src-a6fac84fcf38d1a17650296ab2f345d62e855db1.tar.gz
Have lockstat(1) trace locks by name rather than by address.
Previously, lockstat(1) would use a lock's address as its identifier when consuming data describing lock contention and hold events. After collecting the requested data, it would use ksyms(4) to resolve lock addresses to names. Of course, this doesn't work too well for locks contained in dynamically-allocated memory. This change modifies lockstat(1) to trace the lock names obtained from the base struct lock_object instead, leading to output that is generally much more useful. This change also removes the -c option, which is used to coalesce data for locks in an array. It's not possible to support this option without also tracing lock addresses, and since lock arrays in which the lock names are distinct are not very common in FreeBSD, it's simpler to just remove the option. Reviewed by: avg (earlier revision) Differential Revision: https://reviews.freebsd.org/D3661
Diffstat (limited to 'cddl')
-rw-r--r--cddl/contrib/opensolaris/cmd/lockstat/lockstat.16
-rw-r--r--cddl/contrib/opensolaris/cmd/lockstat/lockstat.c64
2 files changed, 66 insertions, 4 deletions
diff --git a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1 b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1
index 1aa73cc..5524968 100644
--- a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1
+++ b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1
@@ -21,7 +21,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 24, 2015
+.Dd September 29, 2015
.Dt LOCKSTAT 1
.Os
.Sh NAME
@@ -38,7 +38,7 @@
.Op Fl d Ar duration
.Op Fl f Ar function Oo Ns , Ns Ar size Oc
.Op Fl T
-.Op Fl ckgwWRpP
+.Op Fl kgwWRpP
.Op Fl D Ar count
.Op Fl o filename
.Op Fl x Ar opt Oo Ns = Ns Ar val Oc
@@ -172,8 +172,6 @@ This is off by default.
.El
.Ss Data Reporting
.Bl -tag -width indent
-.It Fl c
-Coalesce lock data for lock arrays.
.It Fl D Ar count
Only display the top
.Ar count
diff --git a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.c b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.c
index b59bee7..38bf681 100644
--- a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.c
+++ b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.c
@@ -65,7 +65,11 @@ typedef uintptr_t pc_t;
typedef struct lsrec {
struct lsrec *ls_next; /* next in hash chain */
+#ifdef illumos
uintptr_t ls_lock; /* lock address */
+#else
+ char *ls_lock; /* lock name */
+#endif
uintptr_t ls_caller; /* caller address */
uint32_t ls_count; /* cumulative event count */
uint32_t ls_event; /* type of event */
@@ -338,7 +342,9 @@ usage(void)
" -d duration only watch events longer than <duration>\n"
" -T trace (rather than sample) events\n"
"\nData reporting options:\n\n"
+#ifdef illumos
" -c coalesce lock data for arrays like pse_mutex[]\n"
+#endif
" -k coalesce PCs within functions\n"
" -g show total events generated by function\n"
" -w wherever: don't distinguish events by caller\n"
@@ -381,12 +387,16 @@ lockcmp(lsrec_t *a, lsrec_t *b)
if (a->ls_caller > b->ls_caller)
return (1);
+#ifdef illumos
if (a->ls_lock < b->ls_lock)
return (-1);
if (a->ls_lock > b->ls_lock)
return (1);
return (0);
+#else
+ return (strcmp(a->ls_lock, b->ls_lock));
+#endif
}
static int
@@ -424,26 +434,40 @@ lockcmp_anywhere(lsrec_t *a, lsrec_t *b)
if (a->ls_event > b->ls_event)
return (1);
+#ifdef illumos
if (a->ls_lock < b->ls_lock)
return (-1);
if (a->ls_lock > b->ls_lock)
return (1);
return (0);
+#else
+ return (strcmp(a->ls_lock, b->ls_lock));
+#endif
}
static int
lock_and_count_cmp_anywhere(lsrec_t *a, lsrec_t *b)
{
+#ifndef illumos
+ int cmp;
+#endif
+
if (a->ls_event < b->ls_event)
return (-1);
if (a->ls_event > b->ls_event)
return (1);
+#ifdef illumos
if (a->ls_lock < b->ls_lock)
return (-1);
if (a->ls_lock > b->ls_lock)
return (1);
+#else
+ cmp = strcmp(a->ls_lock, b->ls_lock);
+ if (cmp != 0)
+ return (cmp);
+#endif
return (b->ls_count - a->ls_count);
}
@@ -698,7 +722,11 @@ dprog_addevent(int event)
caller = "(uintptr_t)arg0";
arg1 = "arg2";
} else {
+#ifdef illumos
arg0 = "(uintptr_t)arg0";
+#else
+ arg0 = "stringof(args[0]->lock_object.lo_name)";
+#endif
caller = "caller";
}
@@ -912,12 +940,17 @@ lsrec_fill(lsrec_t *lsrec, const dtrace_recdesc_t *rec, int nrecs, caddr_t data)
lsrec->ls_event = (uint32_t)*((uint64_t *)(data + rec->dtrd_offset));
rec++;
+#ifdef illumos
if (rec->dtrd_size != sizeof (uintptr_t))
fail(0, "bad lock address size in second record");
/* LINTED - alignment */
lsrec->ls_lock = *((uintptr_t *)(data + rec->dtrd_offset));
rec++;
+#else
+ lsrec->ls_lock = strdup((const char *)(data + rec->dtrd_offset));
+ rec++;
+#endif
if (rec->dtrd_size != sizeof (uintptr_t))
fail(0, "bad caller size in third record");
@@ -1224,9 +1257,11 @@ main(int argc, char **argv)
events_specified = 1;
break;
+#ifdef illumos
case 'c':
g_cflag = 1;
break;
+#endif
case 'k':
g_kflag = 1;
@@ -1539,6 +1574,9 @@ main(int argc, char **argv)
caller_in_stack = 1;
bcopy(oldlsp, lsp, LS_TIME);
lsp->ls_caller = oldlsp->ls_stack[fr];
+#ifndef illumos
+ lsp->ls_lock = strdup(oldlsp->ls_lock);
+#endif
/* LINTED - alignment */
lsp = (lsrec_t *)((char *)lsp + LS_TIME);
}
@@ -1547,6 +1585,9 @@ main(int argc, char **argv)
/* LINTED - alignment */
lsp = (lsrec_t *)((char *)lsp + LS_TIME);
}
+#ifndef illumos
+ free(oldlsp->ls_lock);
+#endif
}
g_nrecs = g_nrecs_used =
((uintptr_t)lsp - (uintptr_t)newlsp) / LS_TIME;
@@ -1604,8 +1645,10 @@ main(int argc, char **argv)
for (i = 0; i < g_nrecs_used; i++) {
int fr;
lsp = sort_buf[i];
+#ifdef illumos
if (g_cflag)
coalesce_symbol(&lsp->ls_lock);
+#endif
if (g_kflag) {
for (fr = 0; fr < g_stkdepth; fr++)
coalesce_symbol(&lsp->ls_stack[fr]);
@@ -1659,6 +1702,15 @@ main(int argc, char **argv)
first = current;
}
+#ifndef illumos
+ /*
+ * Free lock name buffers
+ */
+ for (i = 0, lsp = (lsrec_t *)data_buf; i < g_nrecs_used; i++,
+ lsp = (lsrec_t *)((char *)lsp + g_recsize))
+ free(lsp->ls_lock);
+#endif
+
return (0);
}
@@ -1748,8 +1800,12 @@ report_stats(FILE *out, lsrec_t **sort_buf, size_t nrecs, uint64_t total_count,
(void) fprintf(out, "%u %u",
lsp->ls_event, lsp->ls_count);
+#ifdef illumos
(void) fprintf(out, " %s",
format_symbol(buf, lsp->ls_lock, g_cflag));
+#else
+ (void) fprintf(out, " %s", lsp->ls_lock);
+#endif
(void) fprintf(out, " %s",
format_symbol(buf, lsp->ls_caller, 0));
(void) fprintf(out, " %f",
@@ -1811,8 +1867,12 @@ report_stats(FILE *out, lsrec_t **sort_buf, size_t nrecs, uint64_t total_count,
(void) fprintf(out, "%4.2f %8s ",
(double)lsp->ls_refcnt / lsp->ls_count, buf);
+#ifdef illumos
(void) fprintf(out, "%-22s ",
format_symbol(buf, lsp->ls_lock, g_cflag));
+#else
+ (void) fprintf(out, "%-22s ", lsp->ls_lock);
+#endif
(void) fprintf(out, "%-24s\n",
format_symbol(buf, lsp->ls_caller, 0));
@@ -1908,7 +1968,11 @@ report_trace(FILE *out, lsrec_t **sort_buf)
(void) fprintf(out, "%2d %10llu %11p %-24s %-24s\n",
lsp->ls_event, (unsigned long long)lsp->ls_time,
(void *)lsp->ls_next,
+#ifdef illumos
format_symbol(buf, lsp->ls_lock, 0),
+#else
+ lsp->ls_lock,
+#endif
format_symbol(buf2, lsp->ls_caller, 0));
if (rectype <= LS_STACK(0))
OpenPOWER on IntegriCloud