aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2015-09-30 05:46:56 +0000
committerMark Johnston <markj@FreeBSD.org>2015-09-30 05:46:56 +0000
commit3142b37664aacab88dc8df5420ed4527807e8b60 (patch)
tree729bcc4069ad5e5c942c0b90142c5fec64dadc29
parentb22ef02080104899c98f4219095f06c5c5378b0f (diff)
downloadsrc-3142b37664aacab88dc8df5420ed4527807e8b60.tar.gz
src-3142b37664aacab88dc8df5420ed4527807e8b60.zip
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
Notes
Notes: svn path=/head/; revision=288417
-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 1aa73cc114ea..552496840d3b 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 b59bee74f294..38bf681325e6 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))