thread.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <mdb/mdb_modapi.h>
typedef struct thread_walk {
int
{
mdb_warn("failed to read 'allthreads'");
return (WALK_ERR);
}
} else {
return (WALK_ERR);
}
}
return (WALK_NEXT);
}
int
{
int status;
return (WALK_DONE); /* Proc has 0 threads or allthreads = 0 */
return (WALK_DONE); /* We've wrapped around */
return (WALK_DONE);
}
wsp->walk_cbdata);
else
return (status);
}
void
{
}
int
{
mdb_warn("couldn't walk 'thread_deathrow'");
return (WALK_ERR);
}
mdb_warn("couldn't walk 'lwp_deathrow'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
kthread_t t;
return (WALK_DONE);
return (WALK_ERR);
}
}
int
{
mdb_warn("couldn't read symbol 'thread_deathrow'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
mdb_warn("couldn't read symbol 'lwp_deathrow'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
typedef struct dispq_walk {
int dw_npri;
} dispq_walk_t;
int
{
mdb_warn("cpu_dispq walk needs a cpu_t address\n");
return (WALK_ERR);
}
return (WALK_ERR);
}
return (WALK_ERR);
}
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
mdb_warn("cpupart_dispq walk needs a cpupart_t address\n");
return (WALK_ERR);
}
return (WALK_ERR);
}
mdb_warn("failed to read dispq_t at %p",
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
kthread_t t;
return (WALK_DONE);
return (WALK_ERR);
}
}
return (WALK_ERR);
}
else
}
void
{
}
#define TF_INTR 0x01
#define TF_PROC 0x02
#define TF_BLOCK 0x04
#define TF_SIG 0x08
#define TF_DISP 0x10
#define TF_MERGE 0x20
/*
* Display a kthread_t.
* This is a little complicated, as there is a lot of information that
* the user could be interested in. The flags "ipbsd" are used to
* indicate which subset of the thread's members are to be displayed
* ('i' is the default). If multiple options are specified, multiple
* sets of data will be displayed in a vaguely readable format. If the
* 'm' option is specified, all the selected sets will be merged onto a
* single line for the benefit of those using wider-than-normal
* terminals. Having a generic mechanism for doing this would be
* really useful, but is a project best left to another day.
*/
int
{
kthread_t t;
int first;
char *state;
char stbuf[20];
/*
* "Gracefully" handle printing a boatload of stuff to the
* screen. If we are not printing our first set of data, and
* we haven't been instructed to merge sets together, output a
* newline and indent such that the thread addresses form a
* column of their own.
*/
#define SPACER() \
if (first) { \
}
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("can't walk threads");
return (DCMD_ERR);
}
return (DCMD_OK);
}
return (DCMD_USAGE);
/*
* If no sets were specified, choose the 'i' set.
*/
#ifdef _LP64
#else
#endif
/*
* Print the relevant headers; note use of SPACER().
*/
if (DCMD_HDRSPEC(flags)) {
mdb_flush();
SPACER();
mdb_printf("%<u> %?s %?s %?s%</u>",
"PROC", "LWP", "CRED");
}
SPACER();
mdb_printf("%<u> %8s %4s %4s %4s %5s %5s %3s %?s%</u>",
"STATE", "FLG", "PFLG",
"SFLG", "PRI", "EPRI", "PIL", "INTR");
}
SPACER();
mdb_printf("%<u> %?s %?s %?s %11s%</u>",
"WCHAN", "TS", "PITS", "SOBJ OPS");
}
SPACER();
mdb_printf("%<u> %?s %16s %16s%</u>",
"SIGQUEUE", "SIG PEND", "SIG HELD");
}
SPACER();
mdb_printf("%<u> %?s %5s %2s%</u>",
"DISPTIME", "BOUND", "PR");
}
mdb_printf("\n");
}
return (DCMD_ERR);
}
return (DCMD_OK);
/* process information */
SPACER();
mdb_printf(" %?p %?p %?p",
}
SPACER();
switch (t.t_state) {
case TS_FREE:
state = "free";
break;
case TS_SLEEP:
state = "sleep";
break;
case TS_RUN:
state = "run";
break;
case TS_ONPROC:
state = "onproc";
break;
case TS_ZOMB:
state = "zomb";
break;
case TS_STOPPED:
state = "stopped";
break;
default:
}
mdb_printf(" %-8s %4x %4x %4x %5d %5d %3d %?s",
} else {
mdb_printf(" %-8s %4x %4x %4x %5d %5d %3d %?p",
}
}
/* blocking information */
SPACER();
mdb_printf(" %?p %?p %?p %11s",
}
/* signal information */
SPACER();
mdb_printf(" %?p %016llx %016llx",
}
/* dispatcher stuff */
SPACER();
mdb_printf(" %?lx %5d %2d",
}
mdb_printf("\n");
return (DCMD_OK);
}
void
thread_help(void)
{
"The flags -ipbsd control which information is displayed. When\n"
"combined, the fields are displayed on separate lines unless the\n"
"-m option is given.\n"
"\n"
"\t-b\tprint blocked thread state\n"
"\t-d\tprint dispatcher state\n"
"\t-f\tignore freed threads\n"
"\t-i\tprint basic thread state (default)\n"
"\t-m\tdisplay results on a single line\n"
"\t-p\tprint process and lwp state\n"
"\t-s\tprint signal state\n");
}
/*
* List a combination of kthread_t and proc_t. Add stack traces in verbose mode.
*/
int
{
int i;
kthread_t t;
proc_t p;
char cmd[80];
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("can't walk threads");
return (DCMD_ERR);
}
return (DCMD_OK);
}
if (i != argc) {
return (DCMD_USAGE);
else
}
if (DCMD_HDRSPEC(flags)) {
if (verbose)
mdb_printf("%<u>%?s %?s %?s %3s %3s %?s%</u>\n",
"ADDR", "PROC", "LWP", "CLS", "PRI", "WCHAN");
else
mdb_printf("%<u>%?s %?s %?s %s/%s%</u>\n",
"ADDR", "PROC", "LWP", "CMD", "LWPID");
}
return (DCMD_ERR);
}
return (DCMD_OK);
return (DCMD_ERR);
}
if (verbose) {
mdb_printf("%0?p %?p %?p %3u %3d %?p\n",
mdb_inc_indent(2);
if (t.t_tid == 0)
else
mdb_dec_indent(2);
mdb_printf("\n");
} else {
if (t.t_tid == 0)
else
}
return (DCMD_OK);
}
void
threadlist_help(void)
{
" -v print verbose output including C stack trace\n"
" count print no more than count arguments (default 0)\n");
}