diff options
Diffstat (limited to 'usr/src/cmd/mdb/common/modules/genunix/thread.c')
-rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/thread.c | 235 |
1 files changed, 118 insertions, 117 deletions
diff --git a/usr/src/cmd/mdb/common/modules/genunix/thread.c b/usr/src/cmd/mdb/common/modules/genunix/thread.c index 410f9973d8..811f29ec66 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/thread.c +++ b/usr/src/cmd/mdb/common/modules/genunix/thread.c @@ -24,7 +24,7 @@ */ /* * Copyright 2013 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2018, Joyent, Inc. + * Copyright (c) 2017, Joyent, Inc. */ @@ -564,89 +564,6 @@ 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 @@ -657,6 +574,8 @@ 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; @@ -702,32 +621,55 @@ threadlist(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (t.t_state == TS_FREE) return (DCMD_OK); - if (!verbose) { - char desc[128]; + 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 (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 { + char name[THREAD_NAME_MAX]; - mdb_printf("\n"); + mdb_printf(" %s/%u", p.p_user.u_comm, t.t_tid); + if (thread_getname(addr, name, sizeof (name))) + mdb_printf(" [%s]", name); + mdb_printf("\n"); + } + } return (DCMD_OK); } @@ -782,6 +724,7 @@ 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 */ @@ -795,7 +738,6 @@ 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, @@ -841,7 +783,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 LWP"); + mdb_printf("%<u>%s%</u>", " SIZE MAX CMD/LWPID or STARTPC"); mdb_printf("\n"); usize = KMEM_STKINFO_LOG_SIZE * sizeof (kmem_stkinfo_t); log = (kmem_stkinfo_t *)mdb_alloc(usize, UM_SLEEP); @@ -864,15 +806,18 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) if (log[i].kthread == NULL) { continue; } - - (void) thread_getdesc((uintptr_t)log[i].kthread, - B_TRUE, tdesc, sizeof (tdesc)); - - mdb_printf("%0?p %0?p %6x %3d%% %s\n", + mdb_printf("%0?p %0?p %6x %3d%%", log[i].kthread, log[i].start, (uint_t)log[i].stksz, - (int)log[i].percent, tdesc); + (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); + } } mdb_free((void *)log, usize); return (DCMD_OK); @@ -887,7 +832,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 LWP"); + mdb_printf("%<u>%s%</u>", " SIZE CUR MAX CMD/LWPID"); mdb_printf("\n"); } @@ -901,6 +846,12 @@ 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). @@ -935,10 +886,14 @@ 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 %s\n", tdesc); + 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"); return (DCMD_OK); } @@ -1011,9 +966,12 @@ stackinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } else { mdb_printf(" n/a"); } - - mdb_printf(" %s\n", tdesc); - + 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_free((void *)ustack, usize + 8); return (DCMD_OK); } @@ -1028,7 +986,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 LWP\n"); + " THREAD STACK SIZE CUR MAX CMD/LWPID\n"); mdb_printf( "ffffff014f5f2c20 ffffff0004153000 4f00 4%% 43%% init/1\n"); mdb_printf( @@ -1055,3 +1013,46 @@ stackinfo_help(void) "\nSee illumos Modular Debugger Guide for detailed usage.\n"); mdb_flush(); } + +/* If the field is not present in the target, return an empty (0 length) name */ +boolean_t +thread_getname(uintptr_t addr, char *namep, size_t namelen) +{ + mdb_ctf_id_t id; + ulong_t offset; + uintptr_t nameaddr; + + bzero(namep, namelen); + + if (mdb_ctf_lookup_by_name("kthread_t", &id) == -1) + return (B_FALSE); + + if (mdb_ctf_offsetof(id, "t_name", &offset) == -1) + return (B_FALSE); + + if (offset % 8 != 0) { + mdb_warn("kthread_t.t_name is not on a byte boundary"); + return (B_FALSE); + } + offset /= 8; + + if (mdb_vread(&nameaddr, sizeof (nameaddr), addr + offset) != + sizeof (nameaddr)) { + mdb_warn("could not read address of thread name buffer"); + return (B_FALSE); + } + + if (nameaddr != 0 && mdb_readstr(namep, namelen, addr + offset) == -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 explicity + * NUL terminate to be safe. + */ + namep[namelen - 1] = '\0'; + } + + return (strlen(namep) > 0 ? B_TRUE : B_FALSE); +} |