summaryrefslogtreecommitdiff
path: root/usr/src/cmd/mdb/common/modules/genunix/thread.c
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2018-10-08 15:34:11 +0100
committerDan McDonald <danmcd@joyent.com>2018-10-19 16:40:54 -0400
commitab618543cc6fc4bc273c077ef5d247961cdb29d4 (patch)
tree24c80e35e958a4c5fef77d444eacb1b4f45798a2 /usr/src/cmd/mdb/common/modules/genunix/thread.c
parent62f63298eba531d48f87aa8c2089298cb7821962 (diff)
downloadillumos-gate-ab618543cc6fc4bc273c077ef5d247961cdb29d4.tar.gz
8158 Want named threads API
9857 proc manpages should have LIBRARY section Reviewed by: Andy Fiddaman <andy@omniosce.org> Reviewed by: Gordon Ross <gwr@nexenta.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/cmd/mdb/common/modules/genunix/thread.c')
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/thread.c192
1 files changed, 121 insertions, 71 deletions
diff --git a/usr/src/cmd/mdb/common/modules/genunix/thread.c b/usr/src/cmd/mdb/common/modules/genunix/thread.c
index 652e5af2d6..410f9973d8 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/thread.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/thread.c
@@ -24,11 +24,13 @@
*/
/*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc.
*/
#include <mdb/mdb_modapi.h>
#include <mdb/mdb_ks.h>
+#include <mdb/mdb_ctf.h>
#include <sys/types.h>
#include <sys/thread.h>
#include <sys/lwp.h>
@@ -38,6 +40,7 @@
#include <sys/disp.h>
#include <sys/taskq_impl.h>
#include <sys/stack.h>
+#include "thread.h"
#ifndef STACK_BIAS
#define STACK_BIAS 0
@@ -561,6 +564,89 @@ thread_help(void)
}
/*
+ * Return a string description of the thread, including the ID and the thread
+ * name.
+ *
+ * If ->t_name is NULL, and we're a system thread, we'll do a little more
+ * spelunking to find a useful string to return.
+ */
+int
+thread_getdesc(uintptr_t addr, boolean_t include_comm,
+ char *buf, size_t bufsize)
+{
+ char name[THREAD_NAME_MAX] = "";
+ kthread_t t;
+ proc_t p;
+
+ bzero(buf, bufsize);
+
+ if (mdb_vread(&t, sizeof (kthread_t), addr) == -1) {
+ mdb_warn("failed to read kthread_t at %p", addr);
+ return (-1);
+ }
+
+ if (t.t_tid == 0) {
+ taskq_t tq;
+
+ if (mdb_vread(&tq, sizeof (taskq_t),
+ (uintptr_t)t.t_taskq) == -1)
+ tq.tq_name[0] = '\0';
+
+ if (t.t_name != NULL) {
+ if (mdb_readstr(buf, bufsize,
+ (uintptr_t)t.t_name) == -1) {
+ mdb_warn("error reading thread name");
+ }
+ } else if (tq.tq_name[0] != '\0') {
+ (void) mdb_snprintf(buf, bufsize, "tq:%s", tq.tq_name);
+ } else {
+ mdb_snprintf(buf, bufsize, "%a()", t.t_startpc);
+ }
+
+ return (buf[0] == '\0' ? -1 : 0);
+ }
+
+ if (include_comm && mdb_vread(&p, sizeof (proc_t),
+ (uintptr_t)t.t_procp) == -1) {
+ mdb_warn("failed to read proc at %p", t.t_procp);
+ return (-1);
+ }
+
+ if (t.t_name != NULL) {
+ if (mdb_readstr(name, sizeof (name), (uintptr_t)t.t_name) == -1)
+ mdb_warn("error reading thread name");
+
+ /*
+ * Just to be safe -- if mdb_readstr() succeeds, it always NUL
+ * terminates the output, but is unclear what it does on
+ * failure. In that case we attempt to show any partial content
+ * w/ the warning in case it's useful, but explicitly
+ * NUL-terminate to be safe.
+ */
+ buf[bufsize - 1] = '\0';
+ }
+
+ if (name[0] != '\0') {
+ if (include_comm) {
+ (void) mdb_snprintf(buf, bufsize, "%s/%u [%s]",
+ p.p_user.u_comm, t.t_tid, name);
+ } else {
+ (void) mdb_snprintf(buf, bufsize, "%u [%s]",
+ t.t_tid, name);
+ }
+ } else {
+ if (include_comm) {
+ (void) mdb_snprintf(buf, bufsize, "%s/%u",
+ p.p_user.u_comm, t.t_tid);
+ } else {
+ (void) mdb_snprintf(buf, bufsize, "%u", t.t_tid);
+ }
+ }
+
+ return (buf[0] == '\0' ? -1 : 0);
+}
+
+/*
* List a combination of kthread_t and proc_t. Add stack traces in verbose mode.
*/
int
@@ -571,8 +657,6 @@ threadlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
uint_t verbose = FALSE;
uint_t notaskq = FALSE;
kthread_t t;
- taskq_t tq;
- proc_t p;
char cmd[80];
mdb_arg_t cmdarg;
@@ -618,50 +702,32 @@ threadlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if (t.t_state == TS_FREE)
return (DCMD_OK);
- if (mdb_vread(&p, sizeof (proc_t), (uintptr_t)t.t_procp) == -1) {
- mdb_warn("failed to read proc at %p", t.t_procp);
- return (DCMD_ERR);
- }
+ if (!verbose) {
+ char desc[128];
+
+ if (thread_getdesc(addr, B_TRUE, desc, sizeof (desc)) == -1)
+ return (DCMD_ERR);
- if (mdb_vread(&tq, sizeof (taskq_t), (uintptr_t)t.t_taskq) == -1)
- tq.tq_name[0] = '\0';
+ mdb_printf("%0?p %?p %?p %s\n", addr, t.t_procp, t.t_lwp, desc);
+ return (DCMD_OK);
+ }
- if (verbose) {
- mdb_printf("%0?p %?p %?p %3u %3d %?p\n",
- addr, t.t_procp, t.t_lwp, t.t_cid, t.t_pri, t.t_wchan);
+ mdb_printf("%0?p %?p %?p %3u %3d %?p\n",
+ addr, t.t_procp, t.t_lwp, t.t_cid, t.t_pri, t.t_wchan);
- mdb_inc_indent(2);
+ mdb_inc_indent(2);
- mdb_printf("PC: %a", t.t_pc);
- if (t.t_tid == 0) {
- if (tq.tq_name[0] != '\0')
- mdb_printf(" TASKQ: %s\n", tq.tq_name);
- else
- mdb_printf(" THREAD: %a()\n", t.t_startpc);
- } else {
- mdb_printf(" CMD: %s\n", p.p_user.u_psargs);
- }
+ mdb_printf("PC: %a\n", t.t_pc);
- mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", count);
- cmdarg.a_type = MDB_TYPE_STRING;
- cmdarg.a_un.a_str = cmd;
+ mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", count);
+ cmdarg.a_type = MDB_TYPE_STRING;
+ cmdarg.a_un.a_str = cmd;
- (void) mdb_call_dcmd("findstack", addr, flags, 1, &cmdarg);
+ (void) mdb_call_dcmd("findstack", addr, flags, 1, &cmdarg);
- mdb_dec_indent(2);
+ mdb_dec_indent(2);
- mdb_printf("\n");
- } else {
- mdb_printf("%0?p %?p %?p", addr, t.t_procp, t.t_lwp);
- if (t.t_tid == 0) {
- if (tq.tq_name[0] != '\0')
- mdb_printf(" tq:%s\n", tq.tq_name);
- else
- mdb_printf(" %a()\n", t.t_startpc);
- } else {
- mdb_printf(" %s/%u\n", p.p_user.u_comm, t.t_tid);
- }
- }
+ mdb_printf("\n");
return (DCMD_OK);
}
@@ -716,7 +782,6 @@ int
stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
kthread_t t;
- proc_t p;
uint64_t *ptr; /* pattern pointer */
caddr_t start; /* kernel stack start */
caddr_t end; /* kernel stack end */
@@ -730,6 +795,7 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
int i = 0;
unsigned int ukmem_stackinfo;
uintptr_t allthreads;
+ char tdesc[128] = "";
/* handle options */
if (mdb_getopts(argc, argv,
@@ -775,7 +841,7 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_printf("%<u>%?s%</u>", "THREAD");
mdb_printf(" %<u>%?s%</u>", "STACK");
- mdb_printf("%<u>%s%</u>", " SIZE MAX CMD/LWPID or STARTPC");
+ mdb_printf("%<u>%s%</u>", " SIZE MAX LWP");
mdb_printf("\n");
usize = KMEM_STKINFO_LOG_SIZE * sizeof (kmem_stkinfo_t);
log = (kmem_stkinfo_t *)mdb_alloc(usize, UM_SLEEP);
@@ -798,18 +864,15 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if (log[i].kthread == NULL) {
continue;
}
- mdb_printf("%0?p %0?p %6x %3d%%",
+
+ (void) thread_getdesc((uintptr_t)log[i].kthread,
+ B_TRUE, tdesc, sizeof (tdesc));
+
+ mdb_printf("%0?p %0?p %6x %3d%% %s\n",
log[i].kthread,
log[i].start,
(uint_t)log[i].stksz,
- (int)log[i].percent);
- if (log[i].t_tid != 0) {
- mdb_printf(" %s/%u\n",
- log[i].cmd, log[i].t_tid);
- } else {
- mdb_printf(" %p (%a)\n", log[i].t_startpc,
- log[i].t_startpc);
- }
+ (int)log[i].percent, tdesc);
}
mdb_free((void *)log, usize);
return (DCMD_OK);
@@ -824,7 +887,7 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
}
mdb_printf("%<u>%?s%</u>", "THREAD");
mdb_printf(" %<u>%?s%</u>", "STACK");
- mdb_printf("%<u>%s%</u>", " SIZE CUR MAX CMD/LWPID");
+ mdb_printf("%<u>%s%</u>", " SIZE CUR MAX LWP");
mdb_printf("\n");
}
@@ -838,12 +901,6 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_OK);
}
- /* read proc */
- if (mdb_vread(&p, sizeof (proc_t), (uintptr_t)t.t_procp) == -1) {
- mdb_warn("failed to read proc at %p\n", t.t_procp);
- return (DCMD_ERR);
- }
-
/*
* Stack grows up or down, see thread_create(),
* compute stack memory aera start and end (start < end).
@@ -878,14 +935,10 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_printf(" %3d%%", percent);
percent = 0;
+ (void) thread_getdesc(addr, B_TRUE, tdesc, sizeof (tdesc));
+
if (ukmem_stackinfo == 0) {
- mdb_printf(" n/a");
- if (t.t_tid == 0) {
- mdb_printf(" %a()", t.t_startpc);
- } else {
- mdb_printf(" %s/%u", p.p_user.u_comm, t.t_tid);
- }
- mdb_printf("\n");
+ mdb_printf(" n/a %s\n", tdesc);
return (DCMD_OK);
}
@@ -958,12 +1011,9 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
} else {
mdb_printf(" n/a");
}
- if (t.t_tid == 0) {
- mdb_printf(" %a()", t.t_startpc);
- } else {
- mdb_printf(" %s/%u", p.p_user.u_comm, t.t_tid);
- }
- mdb_printf("\n");
+
+ mdb_printf(" %s\n", tdesc);
+
mdb_free((void *)ustack, usize + 8);
return (DCMD_OK);
}
@@ -978,7 +1028,7 @@ stackinfo_help(void)
"(an unsigned integer) is non zero at kthread creation time. ");
mdb_printf("For example:\n");
mdb_printf(
- " THREAD STACK SIZE CUR MAX CMD/LWPID\n");
+ " THREAD STACK SIZE CUR MAX LWP\n");
mdb_printf(
"ffffff014f5f2c20 ffffff0004153000 4f00 4%% 43%% init/1\n");
mdb_printf(
@@ -1002,6 +1052,6 @@ stackinfo_help(void)
"-h shows history, dead kthreads that used their "
"kernel stack the most\n");
mdb_printf(
- "\nSee Solaris Modular Debugger Guide for detailed usage.\n");
+ "\nSee illumos Modular Debugger Guide for detailed usage.\n");
mdb_flush();
}