mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-29 12:03:03 +00:00
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
This commit is contained in:
parent
b22ef02080
commit
3142b37664
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=288417
@ -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
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user