17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
5154eb83jwadams * Common Development and Distribution License (the "License").
6154eb83jwadams * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
220605fe7Gordon Ross * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
23d7025c8Jonathan Adams * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24c3377eeJohn Levon * Copyright 2019 Joyent, Inc.
252a12f85Jeremy Jones * Copyright (c) 2013 by Delphix. All rights reserved.
267c478bdstevel@tonic-gate */
277c478bdstevel@tonic-gate
287c478bdstevel@tonic-gate#include <mdb/mdb_param.h>
297c478bdstevel@tonic-gate#include <mdb/mdb_modapi.h>
307c478bdstevel@tonic-gate#include <mdb/mdb_ks.h>
317c478bdstevel@tonic-gate#include <mdb/mdb_ctf.h>
327c478bdstevel@tonic-gate
337c478bdstevel@tonic-gate#include <sys/types.h>
347c478bdstevel@tonic-gate#include <sys/thread.h>
357c478bdstevel@tonic-gate#include <sys/session.h>
367c478bdstevel@tonic-gate#include <sys/user.h>
377c478bdstevel@tonic-gate#include <sys/proc.h>
387c478bdstevel@tonic-gate#include <sys/var.h>
397c478bdstevel@tonic-gate#include <sys/t_lock.h>
407c478bdstevel@tonic-gate#include <sys/callo.h>
417c478bdstevel@tonic-gate#include <sys/priocntl.h>
427c478bdstevel@tonic-gate#include <sys/class.h>
437c478bdstevel@tonic-gate#include <sys/regset.h>
447c478bdstevel@tonic-gate#include <sys/stack.h>
457c478bdstevel@tonic-gate#include <sys/cpuvar.h>
467c478bdstevel@tonic-gate#include <sys/vnode.h>
477c478bdstevel@tonic-gate#include <sys/vfs.h>
487c478bdstevel@tonic-gate#include <sys/flock_impl.h>
497c478bdstevel@tonic-gate#include <sys/kmem_impl.h>
507c478bdstevel@tonic-gate#include <sys/vmem_impl.h>
517c478bdstevel@tonic-gate#include <sys/kstat.h>
527c478bdstevel@tonic-gate#include <sys/dditypes.h>
537c478bdstevel@tonic-gate#include <sys/ddi_impldefs.h>
547c478bdstevel@tonic-gate#include <sys/sysmacros.h>
557c478bdstevel@tonic-gate#include <sys/sysconf.h>
567c478bdstevel@tonic-gate#include <sys/task.h>
577c478bdstevel@tonic-gate#include <sys/project.h>
587c478bdstevel@tonic-gate#include <sys/errorq_impl.h>
597c478bdstevel@tonic-gate#include <sys/cred_impl.h>
607c478bdstevel@tonic-gate#include <sys/zone.h>
617c478bdstevel@tonic-gate#include <sys/panic.h>
627c478bdstevel@tonic-gate#include <regex.h>
637c478bdstevel@tonic-gate#include <sys/port_impl.h>
6471a582fJohn Levon#include <sys/contract/process_impl.h>
657c478bdstevel@tonic-gate
66fa9e406ahrens#include "avl.h"
674c06356dh#include "bio.h"
684c06356dh#include "bitset.h"
69b5fca8ftomee#include "combined.h"
707c478bdstevel@tonic-gate#include "contract.h"
717c478bdstevel@tonic-gate#include "cpupart_mdb.h"
720605fe7Gordon Ross#include "cred.h"
734c06356dh#include "ctxop.h"
744c06356dh#include "cyclic.h"
754c06356dh#include "damap.h"
76a288e5aJoshua M. Clulow#include "ddi_periodic.h"
777c478bdstevel@tonic-gate#include "devinfo.h"
7839f030bPatrick Mooney#include "dnlc.h"
794c06356dh#include "findstack.h"
804c06356dh#include "fm.h"
812a12f85Jeremy Jones#include "gcore.h"
824c06356dh#include "group.h"
835febcb4Scott Carter, SD IOSW#include "irm.h"
844c06356dh#include "kgrep.h"
854c06356dh#include "kmem.h"
864c06356dh#include "ldi.h"
877c478bdstevel@tonic-gate#include "leaky.h"
887c478bdstevel@tonic-gate#include "lgrp.h"
897c478bdstevel@tonic-gate#include "list.h"
907c478bdstevel@tonic-gate#include "log.h"
914c06356dh#include "mdi.h"
924c06356dh#include "memory.h"
937c478bdstevel@tonic-gate#include "mmd.h"
944c06356dh#include "modhash.h"
954c06356dh#include "ndievents.h"
967c478bdstevel@tonic-gate#include "net.h"
97f4b3ec6dh#include "netstack.h"
987c478bdstevel@tonic-gate#include "nvpair.h"
99e386d4dRobert Mustacchi#include "pci.h"
1004c06356dh#include "pg.h"
1014c06356dh#include "rctl.h"
1027c478bdstevel@tonic-gate#include "sobj.h"
1034c06356dh#include "streams.h"
1047c478bdstevel@tonic-gate#include "sysevent.h"
105e0ad97eJonathan Adams#include "taskq.h"
1064c06356dh#include "thread.h"
1074c06356dh#include "tsd.h"
10845916cdjpk#include "tsol.h"
1097c478bdstevel@tonic-gate#include "typegraph.h"
1107c478bdstevel@tonic-gate#include "vfs.h"
1117c478bdstevel@tonic-gate#include "zone.h"
1122694730Evan Yan#include "hotplug.h"
1137c478bdstevel@tonic-gate
1147c478bdstevel@tonic-gate/*
1157c478bdstevel@tonic-gate * Surely this is defined somewhere...
1167c478bdstevel@tonic-gate */
1177c478bdstevel@tonic-gate#define	NINTR		16
1187c478bdstevel@tonic-gate
119bb8b513ek#define	KILOS		10
120bb8b513ek#define	MEGS		20
121bb8b513ek#define	GIGS		30
122bb8b513ek
1237c478bdstevel@tonic-gate#ifndef STACK_BIAS
1247c478bdstevel@tonic-gate#define	STACK_BIAS	0
1257c478bdstevel@tonic-gate#endif
1267c478bdstevel@tonic-gate
1277c478bdstevel@tonic-gatestatic char
1287c478bdstevel@tonic-gatepstat2ch(uchar_t state)
1297c478bdstevel@tonic-gate{
1307c478bdstevel@tonic-gate	switch (state) {
1317c478bdstevel@tonic-gate		case SSLEEP: return ('S');
1327c478bdstevel@tonic-gate		case SRUN: return ('R');
1337c478bdstevel@tonic-gate		case SZOMB: return ('Z');
1347c478bdstevel@tonic-gate		case SIDL: return ('I');
1357c478bdstevel@tonic-gate		case SONPROC: return ('O');
1367c478bdstevel@tonic-gate		case SSTOP: return ('T');
137c97ad5cakolb		case SWAIT: return ('W');
1387c478bdstevel@tonic-gate		default: return ('?');
1397c478bdstevel@tonic-gate	}
1407c478bdstevel@tonic-gate}
1417c478bdstevel@tonic-gate
1427c478bdstevel@tonic-gate#define	PS_PRTTHREADS	0x1
1437c478bdstevel@tonic-gate#define	PS_PRTLWPS	0x2
1447c478bdstevel@tonic-gate#define	PS_PSARGS	0x4
1457c478bdstevel@tonic-gate#define	PS_TASKS	0x8
1467c478bdstevel@tonic-gate#define	PS_PROJECTS	0x10
1477c478bdstevel@tonic-gate#define	PS_ZONES	0x20
14871a582fJohn Levon#define	PS_SERVICES	0x40
1497c478bdstevel@tonic-gate
1507c478bdstevel@tonic-gatestatic int
1517c478bdstevel@tonic-gateps_threadprint(uintptr_t addr, const void *data, void *private)
1527c478bdstevel@tonic-gate{
1537c478bdstevel@tonic-gate	const kthread_t *t = (const kthread_t *)data;
1547c478bdstevel@tonic-gate	uint_t prt_flags = *((uint_t *)private);
1557c478bdstevel@tonic-gate
1567c478bdstevel@tonic-gate	static const mdb_bitmask_t t_state_bits[] = {
1577c478bdstevel@tonic-gate		{ "TS_FREE",	UINT_MAX,	TS_FREE		},
1587c478bdstevel@tonic-gate		{ "TS_SLEEP",	TS_SLEEP,	TS_SLEEP	},
1597c478bdstevel@tonic-gate		{ "TS_RUN",	TS_RUN,		TS_RUN		},
1607c478bdstevel@tonic-gate		{ "TS_ONPROC",	TS_ONPROC,	TS_ONPROC	},
1617c478bdstevel@tonic-gate		{ "TS_ZOMB",	TS_ZOMB,	TS_ZOMB		},
1627c478bdstevel@tonic-gate		{ "TS_STOPPED",	TS_STOPPED,	TS_STOPPED	},
163c97ad5cakolb		{ "TS_WAIT",	TS_WAIT,	TS_WAIT		},
1647c478bdstevel@tonic-gate		{ NULL,		0,		0		}
1657c478bdstevel@tonic-gate	};
1667c478bdstevel@tonic-gate
1677c478bdstevel@tonic-gate	if (prt_flags & PS_PRTTHREADS)
1687c478bdstevel@tonic-gate		mdb_printf("\tT  %?a <%b>\n", addr, t->t_state, t_state_bits);
1697c478bdstevel@tonic-gate
170ab61854John Levon	if (prt_flags & PS_PRTLWPS) {
171ab61854John Levon		char desc[128] = "";
172ab61854John Levon
173ab61854John Levon		(void) thread_getdesc(addr, B_FALSE, desc, sizeof (desc));
174ab61854John Levon
175ab61854John Levon		mdb_printf("\tL  %?a ID: %s\n", t->t_lwp, desc);
176ab61854John Levon	}
1777c478bdstevel@tonic-gate
1787c478bdstevel@tonic-gate	return (WALK_NEXT);
1797c478bdstevel@tonic-gate}
1807c478bdstevel@tonic-gate
18175cebddRyan Zezeskitypedef struct mdb_pflags_proc {
182ab61854John Levon	struct pid	*p_pidp;
18375cebddRyan Zezeski	ushort_t	p_pidflag;
18475cebddRyan Zezeski	uint_t		p_proc_flag;
18575cebddRyan Zezeski	uint_t		p_flag;
18675cebddRyan Zezeski} mdb_pflags_proc_t;
18775cebddRyan Zezeski
1885b91507Joshua M. Clulowstatic int
1895b91507Joshua M. Clulowpflags(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1905b91507Joshua M. Clulow{
19175cebddRyan Zezeski	mdb_pflags_proc_t pr;
1925b91507Joshua M. Clulow	struct pid pid;
1935b91507Joshua M. Clulow
1945b91507Joshua M. Clulow	static const mdb_bitmask_t p_flag_bits[] = {
1955b91507Joshua M. Clulow		{ "SSYS",		SSYS,		SSYS		},
1965b91507Joshua M. Clulow		{ "SEXITING",		SEXITING,	SEXITING	},
1975b91507Joshua M. Clulow		{ "SITBUSY",		SITBUSY,	SITBUSY		},
1985b91507Joshua M. Clulow		{ "SFORKING",		SFORKING,	SFORKING	},
1995b91507Joshua M. Clulow		{ "SWATCHOK",		SWATCHOK,	SWATCHOK	},
2005b91507Joshua M. Clulow		{ "SKILLED",		SKILLED,	SKILLED		},
2015b91507Joshua M. Clulow		{ "SSCONT",		SSCONT,		SSCONT		},
2025b91507Joshua M. Clulow		{ "SZONETOP",		SZONETOP,	SZONETOP	},
2035b91507Joshua M. Clulow		{ "SEXTKILLED",		SEXTKILLED,	SEXTKILLED	},
2045b91507Joshua M. Clulow		{ "SUGID",		SUGID,		SUGID		},
2055b91507Joshua M. Clulow		{ "SEXECED",		SEXECED,	SEXECED		},
2065b91507Joshua M. Clulow		{ "SJCTL",		SJCTL,		SJCTL		},
2075b91507Joshua M. Clulow		{ "SNOWAIT",		SNOWAIT,	SNOWAIT		},
2085b91507Joshua M. Clulow		{ "SVFORK",		SVFORK,		SVFORK		},
2095b91507Joshua M. Clulow		{ "SVFWAIT",		SVFWAIT,	SVFWAIT		},
2105b91507Joshua M. Clulow		{ "SEXITLWPS",		SEXITLWPS,	SEXITLWPS	},
2115b91507Joshua M. Clulow		{ "SHOLDFORK",		SHOLDFORK,	SHOLDFORK	},
2125b91507Joshua M. Clulow		{ "SHOLDFORK1",		SHOLDFORK1,	SHOLDFORK1	},
2135b91507Joshua M. Clulow		{ "SCOREDUMP",		SCOREDUMP,	SCOREDUMP	},
2145b91507Joshua M. Clulow		{ "SMSACCT",		SMSACCT,	SMSACCT		},
2155b91507Joshua M. Clulow		{ "SLWPWRAP",		SLWPWRAP,	SLWPWRAP	},
2165b91507Joshua M. Clulow		{ "SAUTOLPG",		SAUTOLPG,	SAUTOLPG	},
2175b91507Joshua M. Clulow		{ "SNOCD",		SNOCD,		SNOCD		},
2185b91507Joshua M. Clulow		{ "SHOLDWATCH",		SHOLDWATCH,	SHOLDWATCH	},
2195b91507Joshua M. Clulow		{ "SMSFORK",		SMSFORK,	SMSFORK		},
2205b91507Joshua M. Clulow		{ "SDOCORE",		SDOCORE,	SDOCORE		},
2215b91507Joshua M. Clulow		{ NULL,			0,		0		}
2225b91507Joshua M. Clulow	};
2235b91507Joshua M. Clulow
2245b91507Joshua M. Clulow	static const mdb_bitmask_t p_pidflag_bits[] = {
2255b91507Joshua M. Clulow		{ "CLDPEND",		CLDPEND,	CLDPEND		},
2265b91507Joshua M. Clulow		{ "CLDCONT",		CLDCONT,	CLDCONT		},
2275b91507Joshua M. Clulow		{ "CLDNOSIGCHLD",	CLDNOSIGCHLD,	CLDNOSIGCHLD	},
2285b91507Joshua M. Clulow		{ "CLDWAITPID",		CLDWAITPID,	CLDWAITPID	},
2295b91507Joshua M. Clulow		{ NULL,			0,		0		}
2305b91507Joshua M. Clulow	};
2315b91507Joshua M. Clulow
2325b91507Joshua M. Clulow	static const mdb_bitmask_t p_proc_flag_bits[] = {
2335b91507Joshua M. Clulow		{ "P_PR_TRACE",		P_PR_TRACE,	P_PR_TRACE	},
2345b91507Joshua M. Clulow		{ "P_PR_PTRACE",	P_PR_PTRACE,	P_PR_PTRACE	},
2355b91507Joshua M. Clulow		{ "P_PR_FORK",		P_PR_FORK,	P_PR_FORK	},
2365b91507Joshua M. Clulow		{ "P_PR_LOCK",		P_PR_LOCK,	P_PR_LOCK	},
2375b91507Joshua M. Clulow		{ "P_PR_ASYNC",		P_PR_ASYNC,	P_PR_ASYNC	},
2385b91507Joshua M. Clulow		{ "P_PR_EXEC",		P_PR_EXEC,	P_PR_EXEC	},
2395b91507Joshua M. Clulow		{ "P_PR_BPTADJ",	P_PR_BPTADJ,	P_PR_BPTADJ	},
2405b91507Joshua M. Clulow		{ "P_PR_RUNLCL",	P_PR_RUNLCL,	P_PR_RUNLCL	},
2415b91507Joshua M. Clulow		{ "P_PR_KILLCL",	P_PR_KILLCL,	P_PR_KILLCL	},
2425b91507Joshua M. Clulow		{ NULL,			0,		0		}
2435b91507Joshua M. Clulow	};
2445b91507Joshua M. Clulow
2455b91507Joshua M. Clulow	if (!(flags & DCMD_ADDRSPEC)) {
2465b91507Joshua M. Clulow		if (mdb_walk_dcmd("proc", "pflags", argc, argv) == -1) {
2475b91507Joshua M. Clulow			mdb_warn("can't walk 'proc'");
2485b91507Joshua M. Clulow			return (DCMD_ERR);
2495b91507Joshua M. Clulow		}
2505b91507Joshua M. Clulow		return (DCMD_OK);
2515b91507Joshua M. Clulow	}
2525b91507Joshua M. Clulow
25375cebddRyan Zezeski	if (mdb_ctf_vread(&pr, "proc_t", "mdb_pflags_proc_t", addr, 0) == -1 ||
2545b91507Joshua M. Clulow	    mdb_vread(&pid, sizeof (pid), (uintptr_t)pr.p_pidp) == -1) {
2555b91507Joshua M. Clulow		mdb_warn("cannot read proc_t or pid");
2565b91507Joshua M. Clulow		return (DCMD_ERR);
2575b91507Joshua M. Clulow	}
2585b91507Joshua M. Clulow
2595b91507Joshua M. Clulow	mdb_printf("%p [pid %d]:\n", addr, pid.pid_id);
2605b91507Joshua M. Clulow	mdb_printf("\tp_flag:      %08x <%b>\n", pr.p_flag, pr.p_flag,
2615b91507Joshua M. Clulow	    p_flag_bits);
2625b91507Joshua M. Clulow	mdb_printf("\tp_pidflag:   %08x <%b>\n", pr.p_pidflag, pr.p_pidflag,
2635b91507Joshua M. Clulow	    p_pidflag_bits);
2645b91507Joshua M. Clulow	mdb_printf("\tp_proc_flag: %08x <%b>\n", pr.p_proc_flag, pr.p_proc_flag,
2655b91507Joshua M. Clulow	    p_proc_flag_bits);
2665b91507Joshua M. Clulow
2675b91507Joshua M. Clulow	return (DCMD_OK);
2685b91507Joshua M. Clulow}
2695b91507Joshua M. Clulow
27075cebddRyan Zezeskitypedef struct mdb_ps_proc {
27175cebddRyan Zezeski	char		p_stat;
272ab61854John Levon	struct pid	*p_pidp;
273ab61854John Levon	struct pid	*p_pgidp;
27475cebddRyan Zezeski	struct cred	*p_cred;
27575cebddRyan Zezeski	struct sess	*p_sessp;
27675cebddRyan Zezeski	struct task	*p_task;
27775cebddRyan Zezeski	struct zone	*p_zone;
27871a582fJohn Levon	struct cont_process *p_ct_process;
27975cebddRyan Zezeski	pid_t		p_ppid;
28075cebddRyan Zezeski	uint_t		p_flag;
28175cebddRyan Zezeski	struct {
28275cebddRyan Zezeski		char		u_comm[MAXCOMLEN + 1];
28375cebddRyan Zezeski		char		u_psargs[PSARGSZ];
28475cebddRyan Zezeski	} p_user;
28575cebddRyan Zezeski} mdb_ps_proc_t;
28675cebddRyan Zezeski
28771a582fJohn Levon/*
28871a582fJohn Levon * A reasonable enough limit. Note that we purposefully let this column over-run
28971a582fJohn Levon * if needed.
29071a582fJohn Levon */
29171a582fJohn Levon#define	FMRI_LEN (128)
29271a582fJohn Levon
2937c478bdstevel@tonic-gateint
2947c478bdstevel@tonic-gateps(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2957c478bdstevel@tonic-gate{
2967c478bdstevel@tonic-gate	uint_t prt_flags = 0;
29775cebddRyan Zezeski	mdb_ps_proc_t pr;
2987c478bdstevel@tonic-gate	struct pid pid, pgid, sid;
2997c478bdstevel@tonic-gate	sess_t session;
3007c478bdstevel@tonic-gate	cred_t cred;
3017c478bdstevel@tonic-gate	task_t tk;
3027c478bdstevel@tonic-gate	kproject_t pj;
3037c478bdstevel@tonic-gate	zone_t zn;
30471a582fJohn Levon	struct cont_process cp;
30571a582fJohn Levon	char fmri[FMRI_LEN] = "";
3067c478bdstevel@tonic-gate
3077c478bdstevel@tonic-gate	if (!(flags & DCMD_ADDRSPEC)) {
3087c478bdstevel@tonic-gate		if (mdb_walk_dcmd("proc", "ps", argc, argv) == -1) {
3097c478bdstevel@tonic-gate			mdb_warn("can't walk 'proc'");
3107c478bdstevel@tonic-gate			return (DCMD_ERR);
3117c478bdstevel@tonic-gate		}
3127c478bdstevel@tonic-gate		return (DCMD_OK);
3137c478bdstevel@tonic-gate	}
3147c478bdstevel@tonic-gate
3157c478bdstevel@tonic-gate	if (mdb_getopts(argc, argv,
3167c478bdstevel@tonic-gate	    'f', MDB_OPT_SETBITS, PS_PSARGS, &prt_flags,
3177c478bdstevel@tonic-gate	    'l', MDB_OPT_SETBITS, PS_PRTLWPS, &prt_flags,
31871a582fJohn Levon	    's', MDB_OPT_SETBITS, PS_SERVICES, &prt_flags,
3197c478bdstevel@tonic-gate	    'T', MDB_OPT_SETBITS, PS_TASKS, &prt_flags,
3207c478bdstevel@tonic-gate	    'P', MDB_OPT_SETBITS, PS_PROJECTS, &prt_flags,
3217c478bdstevel@tonic-gate	    'z', MDB_OPT_SETBITS, PS_ZONES, &prt_flags,
3227c478bdstevel@tonic-gate	    't', MDB_OPT_SETBITS, PS_PRTTHREADS, &prt_flags, NULL) != argc)
3237c478bdstevel@tonic-gate		return (DCMD_USAGE);
3247c478bdstevel@tonic-gate
3257c478bdstevel@tonic-gate	if (DCMD_HDRSPEC(flags)) {
32671a582fJohn Levon		mdb_printf("%<u>%-1s %-6s %-6s %-6s %-6s ",
3277c478bdstevel@tonic-gate		    "S", "PID", "PPID", "PGID", "SID");
3287c478bdstevel@tonic-gate		if (prt_flags & PS_TASKS)
32971a582fJohn Levon			mdb_printf("%-5s ", "TASK");
3307c478bdstevel@tonic-gate		if (prt_flags & PS_PROJECTS)
33171a582fJohn Levon			mdb_printf("%-5s ", "PROJ");
3327c478bdstevel@tonic-gate		if (prt_flags & PS_ZONES)
33371a582fJohn Levon			mdb_printf("%-5s ", "ZONE");
33471a582fJohn Levon		if (prt_flags & PS_SERVICES)
33571a582fJohn Levon			mdb_printf("%-40s ", "SERVICE");
33671a582fJohn Levon		mdb_printf("%-6s %-10s %-?s %-s%</u>\n",
3377c478bdstevel@tonic-gate		    "UID", "FLAGS", "ADDR", "NAME");
3387c478bdstevel@tonic-gate	}
3397c478bdstevel@tonic-gate
34075cebddRyan Zezeski	if (mdb_ctf_vread(&pr, "proc_t", "mdb_ps_proc_t", addr, 0) == -1)
34175cebddRyan Zezeski		return (DCMD_ERR);
34275cebddRyan Zezeski
3437c478bdstevel@tonic-gate	mdb_vread(&pid, sizeof (pid), (uintptr_t)pr.p_pidp);
3447c478bdstevel@tonic-gate	mdb_vread(&pgid, sizeof (pgid), (uintptr_t)pr.p_pgidp);
3457c478bdstevel@tonic-gate	mdb_vread(&cred, sizeof (cred), (uintptr_t)pr.p_cred);
3467c478bdstevel@tonic-gate	mdb_vread(&session, sizeof (session), (uintptr_t)pr.p_sessp);
3477c478bdstevel@tonic-gate	mdb_vread(&sid, sizeof (sid), (uintptr_t)session.s_sidp);
3487c478bdstevel@tonic-gate	if (prt_flags & (PS_TASKS | PS_PROJECTS))
3497c478bdstevel@tonic-gate		mdb_vread(&tk, sizeof (tk), (uintptr_t)pr.p_task);
3507c478bdstevel@tonic-gate	if (prt_flags & PS_PROJECTS)
3517c478bdstevel@tonic-gate		mdb_vread(&pj, sizeof (pj), (uintptr_t)tk.tk_proj);
3527c478bdstevel@tonic-gate	if (prt_flags & PS_ZONES)
35375cebddRyan Zezeski		mdb_vread(&zn, sizeof (zn), (uintptr_t)pr.p_zone);
35471a582fJohn Levon	if ((prt_flags & PS_SERVICES) && pr.p_ct_process != NULL) {
35571a582fJohn Levon		mdb_vread(&cp, sizeof (cp), (uintptr_t)pr.p_ct_process);
35671a582fJohn Levon
35771a582fJohn Levon		if (mdb_read_refstr((uintptr_t)cp.conp_svc_fmri, fmri,
35871a582fJohn Levon		    sizeof (fmri)) <= 0)
35971a582fJohn Levon			(void) strlcpy(fmri, "?", sizeof (fmri));
36071a582fJohn Levon
36171a582fJohn Levon		/* Strip any standard prefix and suffix. */
36271a582fJohn Levon		if (strncmp(fmri, "svc:/", sizeof ("svc:/") - 1) == 0) {
36371a582fJohn Levon			char *i = fmri;
36471a582fJohn Levon			char *j = fmri + sizeof ("svc:/") - 1;
36571a582fJohn Levon			for (; *j != '\0'; i++, j++) {
36671a582fJohn Levon				if (strcmp(j, ":default") == 0)
36771a582fJohn Levon					break;
36871a582fJohn Levon				*i = *j;
36971a582fJohn Levon			}
37071a582fJohn Levon
37171a582fJohn Levon			*i = '\0';
37271a582fJohn Levon		}
37371a582fJohn Levon	}
3747c478bdstevel@tonic-gate
37571a582fJohn Levon	mdb_printf("%-c %-6d %-6d %-6d %-6d ",
3767c478bdstevel@tonic-gate	    pstat2ch(pr.p_stat), pid.pid_id, pr.p_ppid, pgid.pid_id,
3777c478bdstevel@tonic-gate	    sid.pid_id);
3787c478bdstevel@tonic-gate	if (prt_flags & PS_TASKS)
37971a582fJohn Levon		mdb_printf("%-5d ", tk.tk_tkid);
3807c478bdstevel@tonic-gate	if (prt_flags & PS_PROJECTS)
38171a582fJohn Levon		mdb_printf("%-5d ", pj.kpj_id);
3827c478bdstevel@tonic-gate	if (prt_flags & PS_ZONES)
38371a582fJohn Levon		mdb_printf("%-5d ", zn.zone_id);
38471a582fJohn Levon	if (prt_flags & PS_SERVICES)
38571a582fJohn Levon		mdb_printf("%-40s ", fmri);
38671a582fJohn Levon	mdb_printf("%-6d 0x%08x %0?p %-s\n",
3877c478bdstevel@tonic-gate	    cred.cr_uid, pr.p_flag, addr,
3887c478bdstevel@tonic-gate	    (prt_flags & PS_PSARGS) ? pr.p_user.u_psargs : pr.p_user.u_comm);
3897c478bdstevel@tonic-gate
3907c478bdstevel@tonic-gate	if (prt_flags & ~PS_PSARGS)
3917c478bdstevel@tonic-gate		(void) mdb_pwalk("thread", ps_threadprint, &prt_flags, addr);
3927c478bdstevel@tonic-gate
3937c478bdstevel@tonic-gate	return (DCMD_OK);
3947c478bdstevel@tonic-gate}
3957c478bdstevel@tonic-gate
3965a382e8Jason Kingstatic void
3975a382e8Jason Kingps_help(void)
3985a382e8Jason King{
3995a382e8Jason King	mdb_printf("Display processes.\n\n"
4005a382e8Jason King	    "Options:\n"
4015a382e8Jason King	    "    -f\tDisplay command arguments\n"
4025a382e8Jason King	    "    -l\tDisplay LWPs\n"
4035a382e8Jason King	    "    -T\tDisplay tasks\n"
4045a382e8Jason King	    "    -P\tDisplay projects\n"
40571a582fJohn Levon	    "    -s\tDisplay SMF FMRI\n"
4065a382e8Jason King	    "    -z\tDisplay zones\n"
4075a382e8Jason King	    "    -t\tDisplay threads\n\n");
4085a382e8Jason King
4095a382e8Jason King	mdb_printf("The resulting output is a table of the processes on the "
4105a382e8Jason King	    "system.  The\n"
4115a382e8Jason King	    "columns in the output consist of a combination of the "
4125a382e8Jason King	    "following fields:\n\n");
4135a382e8Jason King	mdb_printf("S\tProcess state.  Possible states are:\n"
4145a382e8Jason King	    "\tS\tSleeping (SSLEEP)\n"
4155a382e8Jason King	    "\tR\tRunnable (SRUN)\n"
4165a382e8Jason King	    "\tZ\tZombie (SZOMB)\n"
4175a382e8Jason King	    "\tI\tIdle (SIDL)\n"
4185a382e8Jason King	    "\tO\tOn Cpu (SONPROC)\n"
4195a382e8Jason King	    "\tT\tStopped (SSTOP)\n"
4205a382e8Jason King	    "\tW\tWaiting (SWAIT)\n");
4215a382e8Jason King
4225a382e8Jason King	mdb_printf("PID\tProcess id.\n");
4235a382e8Jason King	mdb_printf("PPID\tParent process id.\n");
4245a382e8Jason King	mdb_printf("PGID\tProcess group id.\n");
4255a382e8Jason King	mdb_printf("SID\tProcess id of the session leader.\n");
4265a382e8Jason King	mdb_printf("TASK\tThe task id of the process.\n");
4275a382e8Jason King	mdb_printf("PROJ\tThe project id of the process.\n");
4285a382e8Jason King	mdb_printf("ZONE\tThe zone id of the process.\n");
42971a582fJohn Levon	mdb_printf("SERVICE The SMF service FMRI of the process.\n");
4305a382e8Jason King	mdb_printf("UID\tThe user id of the process.\n");
4315a382e8Jason King	mdb_printf("FLAGS\tThe process flags (see ::pflags).\n");
4325a382e8Jason King	mdb_printf("ADDR\tThe kernel address of the proc_t structure of the "
4335a382e8Jason King	    "process\n");
4345a382e8Jason King	mdb_printf("NAME\tThe name (p_user.u_comm field) of the process.  If "
4355a382e8Jason King	    "the -f flag\n"
4365a382e8Jason King	    "\tis specified, the arguments of the process are displayed.\n");
4375a382e8Jason King}
4385a382e8Jason King
4397c478bdstevel@tonic-gate#define	PG_NEWEST	0x0001
4407c478bdstevel@tonic-gate#define	PG_OLDEST	0x0002
4417c478bdstevel@tonic-gate#define	PG_PIPE_OUT	0x0004
442adb664evb#define	PG_EXACT_MATCH	0x0008
4437c478bdstevel@tonic-gate
4447c478bdstevel@tonic-gatetypedef struct pgrep_data {
4457c478bdstevel@tonic-gate	uint_t pg_flags;
4467c478bdstevel@tonic-gate	uint_t pg_psflags;
4477c478bdstevel@tonic-gate	uintptr_t pg_xaddr;
4487c478bdstevel@tonic-gate	hrtime_t pg_xstart;
4497c478bdstevel@tonic-gate	const char *pg_pat;
4507c478bdstevel@tonic-gate#ifndef _KMDB
4517c478bdstevel@tonic-gate	regex_t pg_reg;
4527c478bdstevel@tonic-gate#endif
4537c478bdstevel@tonic-gate} pgrep_data_t;
4547c478bdstevel@tonic-gate
45575cebddRyan Zezeskitypedef struct mdb_pgrep_proc {
45675cebddRyan Zezeski	struct {
45775cebddRyan Zezeski		timestruc_t	u_start;
45875cebddRyan Zezeski		char		u_comm[MAXCOMLEN + 1];
45975cebddRyan Zezeski	} p_user;
46075cebddRyan Zezeski} mdb_pgrep_proc_t;
46175cebddRyan Zezeski
4627c478bdstevel@tonic-gate/*ARGSUSED*/
4637c478bdstevel@tonic-gatestatic int
46475cebddRyan Zezeskipgrep_cb(uintptr_t addr, const void *ignored, void *data)
4657c478bdstevel@tonic-gate{
46675cebddRyan Zezeski	mdb_pgrep_proc_t p;
4677c478bdstevel@tonic-gate	pgrep_data_t *pgp = data;
4687c478bdstevel@tonic-gate#ifndef _KMDB
4697c478bdstevel@tonic-gate	regmatch_t pmatch;
4707c478bdstevel@tonic-gate#endif
4717c478bdstevel@tonic-gate
47275cebddRyan Zezeski	if (mdb_ctf_vread(&p, "proc_t", "mdb_pgrep_proc_t", addr, 0) == -1)
47375cebddRyan Zezeski		return (WALK_ERR);
47475cebddRyan Zezeski
4757c478bdstevel@tonic-gate	/*
4767c478bdstevel@tonic-gate	 * kmdb doesn't have access to the reg* functions, so we fall back
477adb664evb	 * to strstr/strcmp.
4787c478bdstevel@tonic-gate	 */
4797c478bdstevel@tonic-gate#ifdef _KMDB
480adb664evb	if ((pgp->pg_flags & PG_EXACT_MATCH) ?
48175cebddRyan Zezeski	    (strcmp(p.p_user.u_comm, pgp->pg_pat) != 0) :
48275cebddRyan Zezeski	    (strstr(p.p_user.u_comm, pgp->pg_pat) == NULL))
4837c478bdstevel@tonic-gate		return (WALK_NEXT);
4847c478bdstevel@tonic-gate#else
48575cebddRyan Zezeski	if (regexec(&pgp->pg_reg, p.p_user.u_comm, 1, &pmatch, 0) != 0)
4867c478bdstevel@tonic-gate		return (WALK_NEXT);
487adb664evb
488adb664evb	if ((pgp->pg_flags & PG_EXACT_MATCH) &&
48975cebddRyan Zezeski	    (pmatch.rm_so != 0 || p.p_user.u_comm[pmatch.rm_eo] != '\0'))
490adb664evb		return (WALK_NEXT);
4917c478bdstevel@tonic-gate#endif
4927c478bdstevel@tonic-gate
4937c478bdstevel@tonic-gate	if (pgp->pg_flags & (PG_NEWEST | PG_OLDEST)) {
4947c478bdstevel@tonic-gate		hrtime_t start;
4957c478bdstevel@tonic-gate
49675cebddRyan Zezeski		start = (hrtime_t)p.p_user.u_start.tv_sec * NANOSEC +
49775cebddRyan Zezeski		    p.p_user.u_start.tv_nsec;
4987c478bdstevel@tonic-gate
4997c478bdstevel@tonic-gate		if (pgp->pg_flags & PG_NEWEST) {
500892ad16Toomas Soome			if (pgp->pg_xaddr == 0 || start > pgp->pg_xstart) {
5017c478bdstevel@tonic-gate				pgp->pg_xaddr = addr;
5027c478bdstevel@tonic-gate				pgp->pg_xstart = start;
5037c478bdstevel@tonic-gate			}
5047c478bdstevel@tonic-gate		} else {
505892ad16Toomas Soome			if (pgp->pg_xaddr == 0 || start < pgp->pg_xstart) {
5067c478bdstevel@tonic-gate				pgp->pg_xaddr = addr;
5077c478bdstevel@tonic-gate				pgp->pg_xstart = start;
5087c478bdstevel@tonic-gate			}
5097c478bdstevel@tonic-gate		}
5107c478bdstevel@tonic-gate
5117c478bdstevel@tonic-gate	} else if (pgp->pg_flags & PG_PIPE_OUT) {
5127c478bdstevel@tonic-gate		mdb_printf("%p\n", addr);
5137c478bdstevel@tonic-gate
5147c478bdstevel@tonic-gate	} else {
5157c478bdstevel@tonic-gate		if (mdb_call_dcmd("ps", addr, pgp->pg_psflags, 0, NULL) != 0) {
5167c478bdstevel@tonic-gate			mdb_warn("can't invoke 'ps'");
5177c478bdstevel@tonic-gate			return (WALK_DONE);
5187c478bdstevel@tonic-gate		}
5197c478bdstevel@tonic-gate		pgp->pg_psflags &= ~DCMD_LOOPFIRST;
5207c478bdstevel@tonic-gate	}
5217c478bdstevel@tonic-gate
5227c478bdstevel@tonic-gate	return (WALK_NEXT);
5237c478bdstevel@tonic-gate}
5247c478bdstevel@tonic-gate
5257c478bdstevel@tonic-gate/*ARGSUSED*/
5267c478bdstevel@tonic-gateint
5277c478bdstevel@tonic-gatepgrep(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5287c478bdstevel@tonic-gate{
5297c478bdstevel@tonic-gate	pgrep_data_t pg;
5307c478bdstevel@tonic-gate	int i;
5317c478bdstevel@tonic-gate#ifndef _KMDB
5327c478bdstevel@tonic-gate	int err;
5337c478bdstevel@tonic-gate#endif
5347c478bdstevel@tonic-gate
5357c478bdstevel@tonic-gate	if (flags & DCMD_ADDRSPEC)
5367c478bdstevel@tonic-gate		return (DCMD_USAGE);
5377c478bdstevel@tonic-gate
5387c478bdstevel@tonic-gate	pg.pg_flags = 0;
5397c478bdstevel@tonic-gate	pg.pg_xaddr = 0;
5407c478bdstevel@tonic-gate
5417c478bdstevel@tonic-gate	i = mdb_getopts(argc, argv,
5427c478bdstevel@tonic-gate	    'n', MDB_OPT_SETBITS, PG_NEWEST, &pg.pg_flags,
5437c478bdstevel@tonic-gate	    'o', MDB_OPT_SETBITS, PG_OLDEST, &pg.pg_flags,
544adb664evb	    'x', MDB_OPT_SETBITS, PG_EXACT_MATCH, &pg.pg_flags,
5457c478bdstevel@tonic-gate	    NULL);
5467c478bdstevel@tonic-gate
5477c478bdstevel@tonic-gate	argc -= i;
5487c478bdstevel@tonic-gate	argv += i;
5497c478bdstevel@tonic-gate
5507c478bdstevel@tonic-gate	if (argc != 1)
5517c478bdstevel@tonic-gate		return (DCMD_USAGE);
5527c478bdstevel@tonic-gate
5537c478bdstevel@tonic-gate	/*
5547c478bdstevel@tonic-gate	 * -n and -o are mutually exclusive.
5557c478bdstevel@tonic-gate	 */
5567c478bdstevel@tonic-gate	if ((pg.pg_flags & PG_NEWEST) && (pg.pg_flags & PG_OLDEST))
5577c478bdstevel@tonic-gate		return (DCMD_USAGE);
5587c478bdstevel@tonic-gate
5597c478bdstevel@tonic-gate	if (argv->a_type != MDB_TYPE_STRING)
5607c478bdstevel@tonic-gate		return (DCMD_USAGE);
5617c478bdstevel@tonic-gate
5627c478bdstevel@tonic-gate	if (flags & DCMD_PIPE_OUT)
5637c478bdstevel@tonic-gate		pg.pg_flags |= PG_PIPE_OUT;
5647c478bdstevel@tonic-gate
5657c478bdstevel@tonic-gate	pg.pg_pat = argv->a_un.a_str;
5667c478bdstevel@tonic-gate	if (DCMD_HDRSPEC(flags))
5677c478bdstevel@tonic-gate		pg.pg_psflags = DCMD_ADDRSPEC | DCMD_LOOP | DCMD_LOOPFIRST;
5687c478bdstevel@tonic-gate	else
5697c478bdstevel@tonic-gate		pg.pg_psflags = DCMD_ADDRSPEC | DCMD_LOOP;
5707c478bdstevel@tonic-gate
5717c478bdstevel@tonic-gate#ifndef _KMDB
5727c478bdstevel@tonic-gate	if ((err = regcomp(&pg.pg_reg, pg.pg_pat, REG_EXTENDED)) != 0) {
5737c478bdstevel@tonic-gate		size_t nbytes;
5747c478bdstevel@tonic-gate		char *buf;
5757c478bdstevel@tonic-gate
5767c478bdstevel@tonic-gate		nbytes = regerror(err, &pg.pg_reg, NULL, 0);
5777c478bdstevel@tonic-gate		buf = mdb_alloc(nbytes + 1, UM_SLEEP | UM_GC);
5787c478bdstevel@tonic-gate		(void) regerror(err, &pg.pg_reg, buf, nbytes);
5797c478bdstevel@tonic-gate		mdb_warn("%s\n", buf);
5807c478bdstevel@tonic-gate
5817c478bdstevel@tonic-gate		return (DCMD_ERR);
5827c478bdstevel@tonic-gate	}
5837c478bdstevel@tonic-gate#endif
5847c478bdstevel@tonic-gate
5857c478bdstevel@tonic-gate	if (mdb_walk("proc", pgrep_cb, &pg) != 0) {
5867c478bdstevel@tonic-gate		mdb_warn("can't walk 'proc'");
5877c478bdstevel@tonic-gate		return (DCMD_ERR);
5887c478bdstevel@tonic-gate	}
5897c478bdstevel@tonic-gate
5907c478bdstevel@tonic-gate	if (pg.pg_xaddr != 0 && (pg.pg_flags & (PG_NEWEST | PG_OLDEST))) {
5917c478bdstevel@tonic-gate		if (pg.pg_flags & PG_PIPE_OUT) {
5927c478bdstevel@tonic-gate			mdb_printf("%p\n", pg.pg_xaddr);
5937c478bdstevel@tonic-gate		} else {
5947c478bdstevel@tonic-gate			if (mdb_call_dcmd("ps", pg.pg_xaddr, pg.pg_psflags,
5957c478bdstevel@tonic-gate			    0, NULL) != 0) {
5967c478bdstevel@tonic-gate				mdb_warn("can't invoke 'ps'");
5977c478bdstevel@tonic-gate				return (DCMD_ERR);
5987c478bdstevel@tonic-gate			}
5997c478bdstevel@tonic-gate		}
6007c478bdstevel@tonic-gate	}
6017c478bdstevel@tonic-gate
6027c478bdstevel@tonic-gate	return (DCMD_OK);
6037c478bdstevel@tonic-gate}
6047c478bdstevel@tonic-gate
6057c478bdstevel@tonic-gateint
6067c478bdstevel@tonic-gatetask(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
6077c478bdstevel@tonic-gate{
6087c478bdstevel@tonic-gate	task_t tk;
6097c478bdstevel@tonic-gate	kproject_t pj;
6107c478bdstevel@tonic-gate
6117c478bdstevel@tonic-gate	if (!(flags & DCMD_ADDRSPEC)) {
6127c478bdstevel@tonic-gate		if (mdb_walk_dcmd("task_cache", "task", argc, argv) == -1) {
6137c478bdstevel@tonic-gate			mdb_warn("can't walk task_cache");
6147c478bdstevel@tonic-gate			return (DCMD_ERR);
6157c478bdstevel@tonic-gate		}
6167c478bdstevel@tonic-gate		return (DCMD_OK);
6177c478bdstevel@tonic-gate	}
6187c478bdstevel@tonic-gate	if (DCMD_HDRSPEC(flags)) {
6197c478bdstevel@tonic-gate		mdb_printf("%<u>%?s %6s %6s %6s %6s %10s%</u>\n",
6207c478bdstevel@tonic-gate		    "ADDR", "TASKID", "PROJID", "ZONEID", "REFCNT", "FLAGS");
6217c478bdstevel@tonic-gate	}
6227c478bdstevel@tonic-gate	if (mdb_vread(&tk, sizeof (task_t), addr) == -1) {
6237c478bdstevel@tonic-gate		mdb_warn("can't read task_t structure at %p", addr);
6247c478bdstevel@tonic-gate		return (DCMD_ERR);
6257c478bdstevel@tonic-gate	}
6267c478bdstevel@tonic-gate	if (mdb_vread(&pj, sizeof (kproject_t), (uintptr_t)tk.tk_proj) == -1) {
6277c478bdstevel@tonic-gate		mdb_warn("can't read project_t structure at %p", addr);
6287c478bdstevel@tonic-gate		return (DCMD_ERR);
6297c478bdstevel@tonic-gate	}
6307c478bdstevel@tonic-gate	mdb_printf("%0?p %6d %6d %6d %6u 0x%08x\n",
6317c478bdstevel@tonic-gate	    addr, tk.tk_tkid, pj.kpj_id, pj.kpj_zoneid, tk.tk_hold_count,
6327c478bdstevel@tonic-gate	    tk.tk_flags);
6337c478bdstevel@tonic-gate	return (DCMD_OK);
6347c478bdstevel@tonic-gate}
6357c478bdstevel@tonic-gate
6367c478bdstevel@tonic-gateint
6377c478bdstevel@tonic-gateproject(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
6387c478bdstevel@tonic-gate{
6397c478bdstevel@tonic-gate	kproject_t pj;
6407c478bdstevel@tonic-gate
6417c478bdstevel@tonic-gate	if (!(flags & DCMD_ADDRSPEC)) {
6427c478bdstevel@tonic-gate		if (mdb_walk_dcmd("projects", "project", argc, argv) == -1) {
6437c478bdstevel@tonic-gate			mdb_warn("can't walk projects");
6447c478bdstevel@tonic-gate			return (DCMD_ERR);
6457c478bdstevel@tonic-gate		}
6467c478bdstevel@tonic-gate		return (DCMD_OK);
6477c478bdstevel@tonic-gate	}
6487c478bdstevel@tonic-gate	if (DCMD_HDRSPEC(flags)) {
6497c478bdstevel@tonic-gate		mdb_printf("%<u>%?s %6s %6s %6s%</u>\n",
6507c478bdstevel@tonic-gate		    "ADDR", "PROJID", "ZONEID", "REFCNT");
6517c478bdstevel@tonic-gate	}
6527c478bdstevel@tonic-gate	if (mdb_vread(&pj, sizeof (kproject_t), addr) == -1) {
6537c478bdstevel@tonic-gate		mdb_warn("can't read kproject_t structure at %p", addr);
6547c478bdstevel@tonic-gate		return (DCMD_ERR);
6557c478bdstevel@tonic-gate	}
6567c478bdstevel@tonic-gate	mdb_printf("%0?p %6d %6d %6u\n", addr, pj.kpj_id, pj.kpj_zoneid,
6577c478bdstevel@tonic-gate	    pj.kpj_count);
6587c478bdstevel@tonic-gate	return (DCMD_OK);
6597c478bdstevel@tonic-gate}
6607c478bdstevel@tonic-gate
66187a18d3Madhavan Venkataraman/* walk callouts themselves, either by list or id hash. */
6627c478bdstevel@tonic-gateint
66387a18d3Madhavan Venkataramancallout_walk_init(mdb_walk_state_t *wsp)
6647c478bdstevel@tonic-gate{
665892ad16Toomas Soome	if (wsp->walk_addr == 0) {
66687a18d3Madhavan Venkataraman		mdb_warn("callout doesn't support global walk");
66787a18d3Madhavan Venkataraman		return (WALK_ERR);
66887a18d3Madhavan Venkataraman	}
66987a18d3Madhavan Venkataraman	wsp->walk_data = mdb_alloc(sizeof (callout_t), UM_SLEEP);
67087a18d3Madhavan Venkataraman	return (WALK_NEXT);
67187a18d3Madhavan Venkataraman}
6727c478bdstevel@tonic-gate
67387a18d3Madhavan Venkataraman#define	CALLOUT_WALK_BYLIST	0
67487a18d3Madhavan Venkataraman#define	CALLOUT_WALK_BYID	1
67587a18d3Madhavan Venkataraman
67687a18d3Madhavan Venkataraman/* the walker arg switches between walking by list (0) and walking by id (1). */
67787a18d3Madhavan Venkataramanint
67887a18d3Madhavan Venkataramancallout_walk_step(mdb_walk_state_t *wsp)
67987a18d3Madhavan Venkataraman{
68087a18d3Madhavan Venkataraman	int retval;
6817c478bdstevel@tonic-gate
682892ad16Toomas Soome	if (wsp->walk_addr == 0) {
68387a18d3Madhavan Venkataraman		return (WALK_DONE);
68487a18d3Madhavan Venkataraman	}
68587a18d3Madhavan Venkataraman	if (mdb_vread(wsp->walk_data, sizeof (callout_t),
68687a18d3Madhavan Venkataraman	    wsp->walk_addr) == -1) {
68787a18d3Madhavan Venkataraman		mdb_warn("failed to read callout at %p", wsp->walk_addr);
68887a18d3Madhavan Venkataraman		return (WALK_DONE);
68987a18d3Madhavan Venkataraman	}
69087a18d3Madhavan Venkataraman	retval = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
69187a18d3Madhavan Venkataraman	    wsp->walk_cbdata);
69287a18d3Madhavan Venkataraman
69387a18d3Madhavan Venkataraman	if ((ulong_t)wsp->walk_arg == CALLOUT_WALK_BYID) {
69487a18d3Madhavan Venkataraman		wsp->walk_addr =
69587a18d3Madhavan Venkataraman		    (uintptr_t)(((callout_t *)wsp->walk_data)->c_idnext);
696843e198johnlev	} else {
69787a18d3Madhavan Venkataraman		wsp->walk_addr =
69887a18d3Madhavan Venkataraman		    (uintptr_t)(((callout_t *)wsp->walk_data)->c_clnext);
699843e198johnlev	}
7007c478bdstevel@tonic-gate
70187a18d3Madhavan Venkataraman	return (retval);
70287a18d3Madhavan Venkataraman}
70387a18d3Madhavan Venkataraman
70487a18d3Madhavan Venkataramanvoid
70587a18d3Madhavan Venkataramancallout_walk_fini(mdb_walk_state_t *wsp)
70687a18d3Madhavan Venkataraman{
70787a18d3Madhavan Venkataraman	mdb_free(wsp->walk_data, sizeof (callout_t));
70887a18d3Madhavan Venkataraman}
70987a18d3Madhavan Venkataraman
71087a18d3Madhavan Venkataraman/*
71187a18d3Madhavan Venkataraman * walker for callout lists. This is different from hashes and callouts.
71287a18d3Madhavan Venkataraman * Thankfully, it's also simpler.
71387a18d3Madhavan Venkataraman */
71487a18d3Madhavan Venkataramanint
71587a18d3Madhavan Venkataramancallout_list_walk_init(mdb_walk_state_t *wsp)
71687a18d3Madhavan Venkataraman{
717892ad16Toomas Soome	if (wsp->walk_addr == 0) {
71887a18d3Madhavan Venkataraman		mdb_warn("callout list doesn't support global walk");
71987a18d3Madhavan Venkataraman		return (WALK_ERR);
7207c478bdstevel@tonic-gate	}
72187a18d3Madhavan Venkataraman	wsp->walk_data = mdb_alloc(sizeof (callout_list_t), UM_SLEEP);
72287a18d3Madhavan Venkataraman	return (WALK_NEXT);
72387a18d3Madhavan Venkataraman}
7247c478bdstevel@tonic-gate
72587a18d3Madhavan Venkataramanint
72687a18d3Madhavan Venkataramancallout_list_walk_step(mdb_walk_state_t *wsp)
72787a18d3Madhavan Venkataraman{
72887a18d3Madhavan Venkataraman	int retval;
72987a18d3Madhavan Venkataraman
730892ad16Toomas Soome	if (wsp->walk_addr == 0) {
73187a18d3Madhavan Venkataraman		return (WALK_DONE);
7327c478bdstevel@tonic-gate	}
73387a18d3Madhavan Venkataraman	if (mdb_vread(wsp->walk_data, sizeof (callout_list_t),
73487a18d3Madhavan Venkataraman	    wsp->walk_addr) != sizeof (callout_list_t)) {
73587a18d3Madhavan Venkataraman		mdb_warn("failed to read callout_list at %p", wsp->walk_addr);
73687a18d3Madhavan Venkataraman		return (WALK_ERR);
73787a18d3Madhavan Venkataraman	}
73887a18d3Madhavan Venkataraman	retval = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
73987a18d3Madhavan Venkataraman	    wsp->walk_cbdata);
7407c478bdstevel@tonic-gate
74187a18d3Madhavan Venkataraman	wsp->walk_addr = (uintptr_t)
74287a18d3Madhavan Venkataraman	    (((callout_list_t *)wsp->walk_data)->cl_next);
74387a18d3Madhavan Venkataraman
74487a18d3Madhavan Venkataraman	return (retval);
74587a18d3Madhavan Venkataraman}
74687a18d3Madhavan Venkataraman
74787a18d3Madhavan Venkataramanvoid
74887a18d3Madhavan Venkataramancallout_list_walk_fini(mdb_walk_state_t *wsp)
74987a18d3Madhavan Venkataraman{
75087a18d3Madhavan Venkataraman	mdb_free(wsp->walk_data, sizeof (callout_list_t));
75187a18d3Madhavan Venkataraman}
75287a18d3Madhavan Venkataraman
75387a18d3Madhavan Venkataraman/* routines/structs to walk callout table(s) */
75487a18d3Madhavan Venkataramantypedef struct cot_data {
75587a18d3Madhavan Venkataraman	callout_table_t *ct0;
75687a18d3Madhavan Venkataraman	callout_table_t ct;
75787a18d3Madhavan Venkataraman	callout_hash_t cot_idhash[CALLOUT_BUCKETS];
75887a18d3Madhavan Venkataraman	callout_hash_t cot_clhash[CALLOUT_BUCKETS];
75987a18d3Madhavan Venkataraman	kstat_named_t ct_kstat_data[CALLOUT_NUM_STATS];
76087a18d3Madhavan Venkataraman	int cotndx;
76187a18d3Madhavan Venkataraman	int cotsize;
76287a18d3Madhavan Venkataraman} cot_data_t;
76387a18d3Madhavan Venkataraman
76487a18d3Madhavan Venkataramanint
76587a18d3Madhavan Venkataramancallout_table_walk_init(mdb_walk_state_t *wsp)
76687a18d3Madhavan Venkataraman{
76787a18d3Madhavan Venkataraman	int max_ncpus;
76887a18d3Madhavan Venkataraman	cot_data_t *cot_walk_data;
76987a18d3Madhavan Venkataraman
77087a18d3Madhavan Venkataraman	cot_walk_data = mdb_alloc(sizeof (cot_data_t), UM_SLEEP);
77187a18d3Madhavan Venkataraman
772892ad16Toomas Soome	if (wsp->walk_addr == 0) {
77387a18d3Madhavan Venkataraman		if (mdb_readvar(&cot_walk_data->ct0, "callout_table") == -1) {
77487a18d3Madhavan Venkataraman			mdb_warn("failed to read 'callout_table'");
77587a18d3Madhavan Venkataraman			return (WALK_ERR);
77687a18d3Madhavan Venkataraman		}
77787a18d3Madhavan Venkataraman		if (mdb_readvar(&max_ncpus, "max_ncpus") == -1) {
77887a18d3Madhavan Venkataraman			mdb_warn("failed to get callout_table array size");
77987a18d3Madhavan Venkataraman			return (WALK_ERR);
78087a18d3Madhavan Venkataraman		}
78187a18d3Madhavan Venkataraman		cot_walk_data->cotsize = CALLOUT_NTYPES * max_ncpus;
78287a18d3Madhavan Venkataraman		wsp->walk_addr = (uintptr_t)cot_walk_data->ct0;
78387a18d3Madhavan Venkataraman	} else {
78487a18d3Madhavan Venkataraman		/* not a global walk */
78587a18d3Madhavan Venkataraman		cot_walk_data->cotsize = 1;
7867c478bdstevel@tonic-gate	}
7877c478bdstevel@tonic-gate
78887a18d3Madhavan Venkataraman	cot_walk_data->cotndx = 0;
78987a18d3Madhavan Venkataraman	wsp->walk_data = cot_walk_data;
7907c478bdstevel@tonic-gate
79187a18d3Madhavan Venkataraman	return (WALK_NEXT);
79287a18d3Madhavan Venkataraman}
7937c478bdstevel@tonic-gate
79487a18d3Madhavan Venkataramanint
79587a18d3Madhavan Venkataramancallout_table_walk_step(mdb_walk_state_t *wsp)
79687a18d3Madhavan Venkataraman{
79787a18d3Madhavan Venkataraman	int retval;
79887a18d3Madhavan Venkataraman	cot_data_t *cotwd = (cot_data_t *)wsp->walk_data;
79987a18d3Madhavan Venkataraman	size_t size;
8007c478bdstevel@tonic-gate
80187a18d3Madhavan Venkataraman	if (cotwd->cotndx >= cotwd->cotsize) {
80287a18d3Madhavan Venkataraman		return (WALK_DONE);
80387a18d3Madhavan Venkataraman	}
80487a18d3Madhavan Venkataraman	if (mdb_vread(&(cotwd->ct), sizeof (callout_table_t),
80587a18d3Madhavan Venkataraman	    wsp->walk_addr) != sizeof (callout_table_t)) {
80687a18d3Madhavan Venkataraman		mdb_warn("failed to read callout_table at %p", wsp->walk_addr);
80787a18d3Madhavan Venkataraman		return (WALK_ERR);
80887a18d3Madhavan Venkataraman	}
80987a18d3Madhavan Venkataraman
81087a18d3Madhavan Venkataraman	size = sizeof (callout_hash_t) * CALLOUT_BUCKETS;
81187a18d3Madhavan Venkataraman	if (cotwd->ct.ct_idhash != NULL) {
81287a18d3Madhavan Venkataraman		if (mdb_vread(cotwd->cot_idhash, size,
81387a18d3Madhavan Venkataraman		    (uintptr_t)(cotwd->ct.ct_idhash)) != size) {
81487a18d3Madhavan Venkataraman			mdb_warn("failed to read id_hash at %p",
81587a18d3Madhavan Venkataraman			    cotwd->ct.ct_idhash);
81687a18d3Madhavan Venkataraman			return (WALK_ERR);
81787a18d3Madhavan Venkataraman		}
81887a18d3Madhavan Venkataraman	}
81987a18d3Madhavan Venkataraman	if (cotwd->ct.ct_clhash != NULL) {
82087a18d3Madhavan Venkataraman		if (mdb_vread(&(cotwd->cot_clhash), size,
82187a18d3Madhavan Venkataraman		    (uintptr_t)cotwd->ct.ct_clhash) == -1) {
82287a18d3Madhavan Venkataraman			mdb_warn("failed to read cl_hash at %p",
82387a18d3Madhavan Venkataraman			    cotwd->ct.ct_clhash);
82487a18d3Madhavan Venkataraman			return (WALK_ERR);
82587a18d3Madhavan Venkataraman		}
82687a18d3Madhavan Venkataraman	}
82787a18d3Madhavan Venkataraman	size = sizeof (kstat_named_t) * CALLOUT_NUM_STATS;
82887a18d3Madhavan Venkataraman	if (cotwd->ct.ct_kstat_data != NULL) {
82987a18d3Madhavan Venkataraman		if (mdb_vread(&(cotwd->ct_kstat_data), size,
83087a18d3Madhavan Venkataraman		    (uintptr_t)cotwd->ct.ct_kstat_data) == -1) {
83187a18d3Madhavan Venkataraman			mdb_warn("failed to read kstats at %p",
83287a18d3Madhavan Venkataraman			    cotwd->ct.ct_kstat_data);
83387a18d3Madhavan Venkataraman			return (WALK_ERR);
83487a18d3Madhavan Venkataraman		}
83587a18d3Madhavan Venkataraman	}
83687a18d3Madhavan Venkataraman	retval = wsp->walk_callback(wsp->walk_addr, (void *)cotwd,
83787a18d3Madhavan Venkataraman	    wsp->walk_cbdata);
83887a18d3Madhavan Venkataraman
83987a18d3Madhavan Venkataraman	cotwd->cotndx++;
84087a18d3Madhavan Venkataraman	if (cotwd->cotndx >= cotwd->cotsize) {
84187a18d3Madhavan Venkataraman		return (WALK_DONE);
84287a18d3Madhavan Venkataraman	}
84387a18d3Madhavan Venkataraman	wsp->walk_addr = (uintptr_t)((char *)wsp->walk_addr +
84487a18d3Madhavan Venkataraman	    sizeof (callout_table_t));
84587a18d3Madhavan Venkataraman
84687a18d3Madhavan Venkataraman	return (retval);
84787a18d3Madhavan Venkataraman}
84887a18d3Madhavan Venkataraman
84987a18d3Madhavan Venkataramanvoid
85087a18d3Madhavan Venkataramancallout_table_walk_fini(mdb_walk_state_t *wsp)
85187a18d3Madhavan Venkataraman{
85287a18d3Madhavan Venkataraman	mdb_free(wsp->walk_data, sizeof (cot_data_t));
85387a18d3Madhavan Venkataraman}
85487a18d3Madhavan Venkataraman
85587a18d3Madhavan Venkataramanstatic const char *co_typenames[] = { "R", "N" };
85687a18d3Madhavan Venkataraman
8570724764Madhavan Venkataraman#define	CO_PLAIN_ID(xid)	((xid) & CALLOUT_ID_MASK)
85887a18d3Madhavan Venkataraman
85987a18d3Madhavan Venkataraman#define	TABLE_TO_SEQID(x)	((x) >> CALLOUT_TYPE_BITS)
86087a18d3Madhavan Venkataraman
86187a18d3Madhavan Venkataraman/* callout flags, in no particular order */
862060cedfMadhavan Venkataraman#define	COF_REAL	0x00000001
863060cedfMadhavan Venkataraman#define	COF_NORM	0x00000002
864060cedfMadhavan Venkataraman#define	COF_LONG	0x00000004
865060cedfMadhavan Venkataraman#define	COF_SHORT	0x00000008
866060cedfMadhavan Venkataraman#define	COF_EMPTY	0x00000010
867060cedfMadhavan Venkataraman#define	COF_TIME	0x00000020
868060cedfMadhavan Venkataraman#define	COF_BEFORE	0x00000040
869060cedfMadhavan Venkataraman#define	COF_AFTER	0x00000080
870060cedfMadhavan Venkataraman#define	COF_SEQID	0x00000100
871060cedfMadhavan Venkataraman#define	COF_FUNC	0x00000200
872060cedfMadhavan Venkataraman#define	COF_ADDR	0x00000400
873060cedfMadhavan Venkataraman#define	COF_EXEC	0x00000800
874060cedfMadhavan Venkataraman#define	COF_HIRES	0x00001000
875060cedfMadhavan Venkataraman#define	COF_ABS		0x00002000
876060cedfMadhavan Venkataraman#define	COF_TABLE	0x00004000
877060cedfMadhavan Venkataraman#define	COF_BYIDH	0x00008000
878060cedfMadhavan Venkataraman#define	COF_FREE	0x00010000
879060cedfMadhavan Venkataraman#define	COF_LIST	0x00020000
880060cedfMadhavan Venkataraman#define	COF_EXPREL	0x00040000
881060cedfMadhavan Venkataraman#define	COF_HDR		0x00080000
882060cedfMadhavan Venkataraman#define	COF_VERBOSE	0x00100000
883060cedfMadhavan Venkataraman#define	COF_LONGLIST	0x00200000
884060cedfMadhavan Venkataraman#define	COF_THDR	0x00400000
885060cedfMadhavan Venkataraman#define	COF_LHDR	0x00800000
886060cedfMadhavan Venkataraman#define	COF_CHDR	0x01000000
887060cedfMadhavan Venkataraman#define	COF_PARAM	0x02000000
888060cedfMadhavan Venkataraman#define	COF_DECODE	0x04000000
889060cedfMadhavan Venkataraman#define	COF_HEAP	0x08000000
890060cedfMadhavan Venkataraman#define	COF_QUEUE	0x10000000
89187a18d3Madhavan Venkataraman
89287a18d3Madhavan Venkataraman/* show real and normal, short and long, expired and unexpired. */
89387a18d3Madhavan Venkataraman#define	COF_DEFAULT	(COF_REAL | COF_NORM | COF_LONG | COF_SHORT)
89487a18d3Madhavan Venkataraman
89551b32bdMadhavan Venkataraman#define	COF_LIST_FLAGS	\
89651b32bdMadhavan Venkataraman	(CALLOUT_LIST_FLAG_HRESTIME | CALLOUT_LIST_FLAG_ABSOLUTE)
89751b32bdMadhavan Venkataraman
89887a18d3Madhavan Venkataraman/* private callout data for callback functions */
89987a18d3Madhavan Venkataramantypedef struct callout_data {
90087a18d3Madhavan Venkataraman	uint_t flags;		/* COF_* */
90187a18d3Madhavan Venkataraman	cpu_t *cpu;		/* cpu pointer if given */
90287a18d3Madhavan Venkataraman	int seqid;		/* cpu seqid, or -1 */
90387a18d3Madhavan Venkataraman	hrtime_t time;		/* expiration time value */
90487a18d3Madhavan Venkataraman	hrtime_t atime;		/* expiration before value */
90587a18d3Madhavan Venkataraman	hrtime_t btime;		/* expiration after value */
90687a18d3Madhavan Venkataraman	uintptr_t funcaddr;	/* function address or NULL */
90787a18d3Madhavan Venkataraman	uintptr_t param;	/* parameter to function or NULL */
90887a18d3Madhavan Venkataraman	hrtime_t now;		/* current system time */
90987a18d3Madhavan Venkataraman	int nsec_per_tick;	/* for conversions */
91087a18d3Madhavan Venkataraman	ulong_t ctbits;		/* for decoding xid */
91187a18d3Madhavan Venkataraman	callout_table_t *co_table;	/* top of callout table array */
91287a18d3Madhavan Venkataraman	int ndx;		/* table index. */
91387a18d3Madhavan Venkataraman	int bucket;		/* which list/id bucket are we in */
91487a18d3Madhavan Venkataraman	hrtime_t exp;		/* expire time */
9150724764Madhavan Venkataraman	int list_flags;		/* copy of cl_flags */
91687a18d3Madhavan Venkataraman} callout_data_t;
91787a18d3Madhavan Venkataraman
91887a18d3Madhavan Venkataraman/* this callback does the actual callback itself (finally). */
91987a18d3Madhavan Venkataraman/*ARGSUSED*/
92087a18d3Madhavan Venkataramanstatic int
92187a18d3Madhavan Venkataramancallouts_cb(uintptr_t addr, const void *data, void *priv)
92287a18d3Madhavan Venkataraman{
92387a18d3Madhavan Venkataraman	callout_data_t *coargs = (callout_data_t *)priv;
92487a18d3Madhavan Venkataraman	callout_t *co = (callout_t *)data;
92551b32bdMadhavan Venkataraman	int tableid, list_flags;
92687a18d3Madhavan Venkataraman	callout_id_t coid;
92787a18d3Madhavan Venkataraman
92887a18d3Madhavan Venkataraman	if ((coargs == NULL) || (co == NULL)) {
92987a18d3Madhavan Venkataraman		return (WALK_ERR);
93087a18d3Madhavan Venkataraman	}
93187a18d3Madhavan Venkataraman
932060cedfMadhavan Venkataraman	if ((coargs->flags & COF_FREE) && !(co->c_xid & CALLOUT_ID_FREE)) {
93351b32bdMadhavan Venkataraman		/*
93451b32bdMadhavan Venkataraman		 * The callout must have been reallocated. No point in
93551b32bdMadhavan Venkataraman		 * walking any more.
93651b32bdMadhavan Venkataraman		 */
93751b32bdMadhavan Venkataraman		return (WALK_DONE);
93851b32bdMadhavan Venkataraman	}
939060cedfMadhavan Venkataraman	if (!(coargs->flags & COF_FREE) && (co->c_xid & CALLOUT_ID_FREE)) {
94051b32bdMadhavan Venkataraman		/*
94151b32bdMadhavan Venkataraman		 * The callout must have been freed. No point in
94251b32bdMadhavan Venkataraman		 * walking any more.
94351b32bdMadhavan Venkataraman		 */
94451b32bdMadhavan Venkataraman		return (WALK_DONE);
94551b32bdMadhavan Venkataraman	}
94687a18d3Madhavan Venkataraman	if ((coargs->flags & COF_FUNC) &&
94787a18d3Madhavan Venkataraman	    (coargs->funcaddr != (uintptr_t)co->c_func)) {
94887a18d3Madhavan Venkataraman		return (WALK_NEXT);
94987a18d3Madhavan Venkataraman	}
95087a18d3Madhavan Venkataraman	if ((coargs->flags & COF_PARAM) &&
95187a18d3Madhavan Venkataraman	    (coargs->param != (uintptr_t)co->c_arg)) {
95287a18d3Madhavan Venkataraman		return (WALK_NEXT);
95387a18d3Madhavan Venkataraman	}
95487a18d3Madhavan Venkataraman	if (!(coargs->flags & COF_LONG) && (co->c_xid & CALLOUT_LONGTERM)) {
95587a18d3Madhavan Venkataraman		return (WALK_NEXT);
95687a18d3Madhavan Venkataraman	}
95787a18d3Madhavan Venkataraman	if (!(coargs->flags & COF_SHORT) && !(co->c_xid & CALLOUT_LONGTERM)) {
95887a18d3Madhavan Venkataraman		return (WALK_NEXT);
95987a18d3Madhavan Venkataraman	}
96087a18d3Madhavan Venkataraman	if ((coargs->flags & COF_EXEC) && !(co->c_xid & CALLOUT_EXECUTING)) {
96187a18d3Madhavan Venkataraman		return (WALK_NEXT);
96287a18d3Madhavan Venkataraman	}
96351b32bdMadhavan Venkataraman	/* it is possible we don't have the exp time or flags */
96487a18d3Madhavan Venkataraman	if (coargs->flags & COF_BYIDH) {
96587a18d3Madhavan Venkataraman		if (!(coargs->flags & COF_FREE)) {
96687a18d3Madhavan Venkataraman			/* we have to fetch the expire time ourselves. */
96787a18d3Madhavan Venkataraman			if (mdb_vread(&coargs->exp, sizeof (hrtime_t),
96887a18d3Madhavan Venkataraman			    (uintptr_t)co->c_list + offsetof(callout_list_t,
96987a18d3Madhavan Venkataraman			    cl_expiration)) == -1) {
97087a18d3Madhavan Venkataraman				mdb_warn("failed to read expiration "
97187a18d3Madhavan Venkataraman				    "time from %p", co->c_list);
97287a18d3Madhavan Venkataraman				coargs->exp = 0;
9737c478bdstevel@tonic-gate			}
9740724764Madhavan Venkataraman			/* and flags. */
9750724764Madhavan Venkataraman			if (mdb_vread(&coargs->list_flags, sizeof (int),
9760724764Madhavan Venkataraman			    (uintptr_t)co->c_list + offsetof(callout_list_t,
9770724764Madhavan Venkataraman			    cl_flags)) == -1) {
9780724764Madhavan Venkataraman				mdb_warn("failed to read list flags"
9790724764Madhavan Venkataraman				    "from %p", co->c_list);
9800724764Madhavan Venkataraman				coargs->list_flags = 0;
9810724764Madhavan Venkataraman			}
98287a18d3Madhavan Venkataraman		} else {
98387a18d3Madhavan Venkataraman			/* free callouts can't use list pointer. */
98487a18d3Madhavan Venkataraman			coargs->exp = 0;
9850724764Madhavan Venkataraman			coargs->list_flags = 0;
9860724764Madhavan Venkataraman		}
9870724764Madhavan Venkataraman		if (coargs->exp != 0) {
9880724764Madhavan Venkataraman			if ((coargs->flags & COF_TIME) &&
9890724764Madhavan Venkataraman			    (coargs->exp != coargs->time)) {
9900724764Madhavan Venkataraman				return (WALK_NEXT);
9910724764Madhavan Venkataraman			}
9920724764Madhavan Venkataraman			if ((coargs->flags & COF_BEFORE) &&
9930724764Madhavan Venkataraman			    (coargs->exp > coargs->btime)) {
9940724764Madhavan Venkataraman				return (WALK_NEXT);
9950724764Madhavan Venkataraman			}
9960724764Madhavan Venkataraman			if ((coargs->flags & COF_AFTER) &&
9970724764Madhavan Venkataraman			    (coargs->exp < coargs->atime)) {
9980724764Madhavan Venkataraman				return (WALK_NEXT);
9990724764Madhavan Venkataraman			}
10000724764Madhavan Venkataraman		}
10010724764Madhavan Venkataraman		/* tricky part, since both HIRES and ABS can be set */
100251b32bdMadhavan Venkataraman		list_flags = coargs->list_flags;
10030724764Madhavan Venkataraman		if ((coargs->flags & COF_HIRES) && (coargs->flags & COF_ABS)) {
10040724764Madhavan Venkataraman			/* both flags are set, only skip "regular" ones */
100551b32bdMadhavan Venkataraman			if (! (list_flags & COF_LIST_FLAGS)) {
10060724764Madhavan Venkataraman				return (WALK_NEXT);
10070724764Madhavan Venkataraman			}
10080724764Madhavan Venkataraman		} else {
10090724764Madhavan Venkataraman			/* individual flags, or no flags */
10100724764Madhavan Venkataraman			if ((coargs->flags & COF_HIRES) &&
101151b32bdMadhavan Venkataraman			    !(list_flags & CALLOUT_LIST_FLAG_HRESTIME)) {
10120724764Madhavan Venkataraman				return (WALK_NEXT);
10130724764Madhavan Venkataraman			}
10140724764Madhavan Venkataraman			if ((coargs->flags & COF_ABS) &&
101551b32bdMadhavan Venkataraman			    !(list_flags & CALLOUT_LIST_FLAG_ABSOLUTE)) {
10160724764Madhavan Venkataraman				return (WALK_NEXT);
10170724764Madhavan Venkataraman			}
101887a18d3Madhavan Venkataraman		}
1019060cedfMadhavan Venkataraman		/*
1020060cedfMadhavan Venkataraman		 * We do the checks for COF_HEAP and COF_QUEUE here only if we
1021060cedfMadhavan Venkataraman		 * are traversing BYIDH. If the traversal is by callout list,
1022060cedfMadhavan Venkataraman		 * we do this check in callout_list_cb() to be more
1023060cedfMadhavan Venkataraman		 * efficient.
1024060cedfMadhavan Venkataraman		 */
1025060cedfMadhavan Venkataraman		if ((coargs->flags & COF_HEAP) &&
1026060cedfMadhavan Venkataraman		    !(list_flags & CALLOUT_LIST_FLAG_HEAPED)) {
1027060cedfMadhavan Venkataraman			return (WALK_NEXT);
1028060cedfMadhavan Venkataraman		}
1029060cedfMadhavan Venkataraman
1030060cedfMadhavan Venkataraman		if ((coargs->flags & COF_QUEUE) &&
1031060cedfMadhavan Venkataraman		    !(list_flags & CALLOUT_LIST_FLAG_QUEUED)) {
1032060cedfMadhavan Venkataraman			return (WALK_NEXT);
1033060cedfMadhavan Venkataraman		}
103487a18d3Madhavan Venkataraman	}
103587a18d3Madhavan Venkataraman
103687a18d3Madhavan Venkataraman#define	callout_table_mask	((1 << coargs->ctbits) - 1)
103787a18d3Madhavan Venkataraman	tableid = CALLOUT_ID_TO_TABLE(co->c_xid);
103887a18d3Madhavan Venkataraman#undef	callout_table_mask
103987a18d3Madhavan Venkataraman	coid = CO_PLAIN_ID(co->c_xid);
104087a18d3Madhavan Venkataraman
104187a18d3Madhavan Venkataraman	if ((coargs->flags & COF_CHDR) && !(coargs->flags & COF_ADDR)) {
104287a18d3Madhavan Venkataraman		/*
104387a18d3Madhavan Venkataraman		 * We need to print the headers. If walking by id, then
104487a18d3Madhavan Venkataraman		 * the list header isn't printed, so we must include
104587a18d3Madhavan Venkataraman		 * that info here.
104687a18d3Madhavan Venkataraman		 */
104787a18d3Madhavan Venkataraman		if (!(coargs->flags & COF_VERBOSE)) {
104887a18d3Madhavan Venkataraman			mdb_printf("%<u>%3s %-1s %-14s %</u>",
104987a18d3Madhavan Venkataraman			    "SEQ", "T", "EXP");
105087a18d3Madhavan Venkataraman		} else if (coargs->flags & COF_BYIDH) {
105187a18d3Madhavan Venkataraman			mdb_printf("%<u>%-14s %</u>", "EXP");
105287a18d3Madhavan Venkataraman		}
10530724764Madhavan Venkataraman		mdb_printf("%<u>%-4s %-?s %-20s%</u>",
10540724764Madhavan Venkataraman		    "XHAL", "XID", "FUNC(ARG)");
105587a18d3Madhavan Venkataraman		if (coargs->flags & COF_LONGLIST) {
105687a18d3Madhavan Venkataraman			mdb_printf("%<u> %-?s %-?s %-?s %-?s%</u>",
105787a18d3Madhavan Venkataraman			    "PREVID", "NEXTID", "PREVL", "NEXTL");
10580724764Madhavan Venkataraman			mdb_printf("%<u> %-?s %-4s %-?s%</u>",
10590724764Madhavan Venkataraman			    "DONE", "UTOS", "THREAD");
106087a18d3Madhavan Venkataraman		}
106187a18d3Madhavan Venkataraman		mdb_printf("\n");
106287a18d3Madhavan Venkataraman		coargs->flags &= ~COF_CHDR;
106387a18d3Madhavan Venkataraman		coargs->flags |= (COF_THDR | COF_LHDR);
106487a18d3Madhavan Venkataraman	}
106587a18d3Madhavan Venkataraman
106687a18d3Madhavan Venkataraman	if (!(coargs->flags & COF_ADDR)) {
106787a18d3Madhavan Venkataraman		if (!(coargs->flags & COF_VERBOSE)) {
106887a18d3Madhavan Venkataraman			mdb_printf("%-3d %1s %-14llx ",
106987a18d3Madhavan Venkataraman			    TABLE_TO_SEQID(tableid),
107087a18d3Madhavan Venkataraman			    co_typenames[tableid & CALLOUT_TYPE_MASK],
107187a18d3Madhavan Venkataraman			    (coargs->flags & COF_EXPREL) ?
107287a18d3Madhavan Venkataraman			    coargs->exp - coargs->now : coargs->exp);
107387a18d3Madhavan Venkataraman		} else if (coargs->flags & COF_BYIDH) {
107487a18d3Madhavan Venkataraman			mdb_printf("%-14x ",
107587a18d3Madhavan Venkataraman			    (coargs->flags & COF_EXPREL) ?
107687a18d3Madhavan Venkataraman			    coargs->exp - coargs->now : coargs->exp);
107787a18d3Madhavan Venkataraman		}
107851b32bdMadhavan Venkataraman		list_flags = coargs->list_flags;
10790724764Madhavan Venkataraman		mdb_printf("%1s%1s%1s%1s %-?llx %a(%p)",
108087a18d3Madhavan Venkataraman		    (co->c_xid & CALLOUT_EXECUTING) ? "X" : " ",
108151b32bdMadhavan Venkataraman		    (list_flags & CALLOUT_LIST_FLAG_HRESTIME) ? "H" : " ",
108251b32bdMadhavan Venkataraman		    (list_flags & CALLOUT_LIST_FLAG_ABSOLUTE) ? "A" : " ",
108387a18d3Madhavan Venkataraman		    (co->c_xid & CALLOUT_LONGTERM) ? "L" : " ",
108487a18d3Madhavan Venkataraman		    (long long)coid, co->c_func, co->c_arg);
108587a18d3Madhavan Venkataraman		if (coargs->flags & COF_LONGLIST) {
108687a18d3Madhavan Venkataraman			mdb_printf(" %-?p %-?p %-?p %-?p",
108787a18d3Madhavan Venkataraman			    co->c_idprev, co->c_idnext, co->c_clprev,
108887a18d3Madhavan Venkataraman			    co->c_clnext);
10890724764Madhavan Venkataraman			mdb_printf(" %-?p %-4d %-0?p",
10900724764Madhavan Venkataraman			    co->c_done, co->c_waiting, co->c_executor);
109187a18d3Madhavan Venkataraman		}
109287a18d3Madhavan Venkataraman	} else {
109387a18d3Madhavan Venkataraman		/* address only */
109487a18d3Madhavan Venkataraman		mdb_printf("%-0p", addr);
109587a18d3Madhavan Venkataraman	}
109687a18d3Madhavan Venkataraman	mdb_printf("\n");
109787a18d3Madhavan Venkataraman	return (WALK_NEXT);
109887a18d3Madhavan Venkataraman}
109987a18d3Madhavan Venkataraman
110087a18d3Madhavan Venkataraman/* this callback is for callout list handling. idhash is done by callout_t_cb */
110187a18d3Madhavan Venkataraman/*ARGSUSED*/
110287a18d3Madhavan Venkataramanstatic int
110387a18d3Madhavan Venkataramancallout_list_cb(uintptr_t addr, const void *data, void *priv)
110487a18d3Madhavan Venkataraman{
110587a18d3Madhavan Venkataraman	callout_data_t *coargs = (callout_data_t *)priv;
110687a18d3Madhavan Venkataraman	callout_list_t *cl = (callout_list_t *)data;
110787a18d3Madhavan Venkataraman	callout_t *coptr;
110851b32bdMadhavan Venkataraman	int list_flags;
110987a18d3Madhavan Venkataraman
111087a18d3Madhavan Venkataraman	if ((coargs == NULL) || (cl == NULL)) {
111187a18d3Madhavan Venkataraman		return (WALK_ERR);
111287a18d3Madhavan Venkataraman	}
111387a18d3Madhavan Venkataraman
111487a18d3Madhavan Venkataraman	coargs->exp = cl->cl_expiration;
11150724764Madhavan Venkataraman	coargs->list_flags = cl->cl_flags;
111651b32bdMadhavan Venkataraman	if ((coargs->flags & COF_FREE) &&
111751b32bdMadhavan Venkataraman	    !(cl->cl_flags & CALLOUT_LIST_FLAG_FREE)) {
111851b32bdMadhavan Venkataraman		/*
111951b32bdMadhavan Venkataraman		 * The callout list must have been reallocated. No point in
112051b32bdMadhavan Venkataraman		 * walking any more.
112151b32bdMadhavan Venkataraman		 */
112251b32bdMadhavan Venkataraman		return (WALK_DONE);
112351b32bdMadhavan Venkataraman	}
112451b32bdMadhavan Venkataraman	if (!(coargs->flags & COF_FREE) &&
112551b32bdMadhavan Venkataraman	    (cl->cl_flags & CALLOUT_LIST_FLAG_FREE)) {
112651b32bdMadhavan Venkataraman		/*
112751b32bdMadhavan Venkataraman		 * The callout list must have been freed. No point in
112851b32bdMadhavan Venkataraman		 * walking any more.
112951b32bdMadhavan Venkataraman		 */
113051b32bdMadhavan Venkataraman		return (WALK_DONE);
113151b32bdMadhavan Venkataraman	}
113287a18d3Madhavan Venkataraman	if ((coargs->flags & COF_TIME) &&
113387a18d3Madhavan Venkataraman	    (cl->cl_expiration != coargs->time)) {
113487a18d3Madhavan Venkataraman		return (WALK_NEXT);
113587a18d3Madhavan Venkataraman	}
113687a18d3Madhavan Venkataraman	if ((coargs->flags & COF_BEFORE) &&
113787a18d3Madhavan Venkataraman	    (cl->cl_expiration > coargs->btime)) {
113887a18d3Madhavan Venkataraman		return (WALK_NEXT);
113987a18d3Madhavan Venkataraman	}
114087a18d3Madhavan Venkataraman	if ((coargs->flags & COF_AFTER) &&
114187a18d3Madhavan Venkataraman	    (cl->cl_expiration < coargs->atime)) {
114287a18d3Madhavan Venkataraman		return (WALK_NEXT);
114387a18d3Madhavan Venkataraman	}
114487a18d3Madhavan Venkataraman	if (!(coargs->flags & COF_EMPTY) &&
114587a18d3Madhavan Venkataraman	    (cl->cl_callouts.ch_head == NULL)) {
114687a18d3Madhavan Venkataraman		return (WALK_NEXT);
114787a18d3Madhavan Venkataraman	}
11480724764Madhavan Venkataraman	/* FOUR cases, each different, !A!B, !AB, A!B, AB */
11490724764Madhavan Venkataraman	if ((coargs->flags & COF_HIRES) && (coargs->flags & COF_ABS)) {
11500724764Madhavan Venkataraman		/* both flags are set, only skip "regular" ones */
115151b32bdMadhavan Venkataraman		if (! (cl->cl_flags & COF_LIST_FLAGS)) {
11520724764Madhavan Venkataraman			return (WALK_NEXT);
11530724764Madhavan Venkataraman		}
11540724764Madhavan Venkataraman	} else {
11550724764Madhavan Venkataraman		if ((coargs->flags & COF_HIRES) &&
115651b32bdMadhavan Venkataraman		    !(cl->cl_flags & CALLOUT_LIST_FLAG_HRESTIME)) {
11570724764Madhavan Venkataraman			return (WALK_NEXT);
11580724764Madhavan Venkataraman		}
11590724764Madhavan Venkataraman		if ((coargs->flags & COF_ABS) &&
116051b32bdMadhavan Venkataraman		    !(cl->cl_flags & CALLOUT_LIST_FLAG_ABSOLUTE)) {
11610724764Madhavan Venkataraman			return (WALK_NEXT);
11620724764Madhavan Venkataraman		}
11630724764Madhavan Venkataraman	}
116487a18d3Madhavan Venkataraman
1165060cedfMadhavan Venkataraman	if ((coargs->flags & COF_HEAP) &&
1166060cedfMadhavan Venkataraman	    !(coargs->list_flags & CALLOUT_LIST_FLAG_HEAPED)) {
1167060cedfMadhavan Venkataraman		return (WALK_NEXT);
1168060cedfMadhavan Venkataraman	}
1169060cedfMadhavan Venkataraman
1170060cedfMadhavan Venkataraman	if ((coargs->flags & COF_QUEUE) &&
1171060cedfMadhavan Venkataraman	    !(coargs->list_flags & CALLOUT_LIST_FLAG_QUEUED)) {
1172060cedfMadhavan Venkataraman		return (WALK_NEXT);
1173060cedfMadhavan Venkataraman	}
1174060cedfMadhavan Venkataraman
117587a18d3Madhavan Venkataraman	if ((coargs->flags & COF_LHDR) && !(coargs->flags & COF_ADDR) &&
117687a18d3Madhavan Venkataraman	    (coargs->flags & (COF_LIST | COF_VERBOSE))) {
117787a18d3Madhavan Venkataraman		if (!(coargs->flags & COF_VERBOSE)) {
117887a18d3Madhavan Venkataraman			/* don't be redundant again */
117987a18d3Madhavan Venkataraman			mdb_printf("%<u>SEQ T %</u>");
118087a18d3Madhavan Venkataraman		}
11810724764Madhavan Venkataraman		mdb_printf("%<u>EXP            HA BUCKET "
11820724764Madhavan Venkataraman		    "CALLOUTS         %</u>");
118387a18d3Madhavan Venkataraman
118487a18d3Madhavan Venkataraman		if (coargs->flags & COF_LONGLIST) {
11850724764Madhavan Venkataraman			mdb_printf("%<u> %-?s %-?s%</u>",
11860724764Madhavan Venkataraman			    "PREV", "NEXT");
118787a18d3Madhavan Venkataraman		}
118887a18d3Madhavan Venkataraman		mdb_printf("\n");
118987a18d3Madhavan Venkataraman		coargs->flags &= ~COF_LHDR;
119087a18d3Madhavan Venkataraman		coargs->flags |= (COF_THDR | COF_CHDR);
119187a18d3Madhavan Venkataraman	}
119287a18d3Madhavan Venkataraman	if (coargs->flags & (COF_LIST | COF_VERBOSE)) {
119387a18d3Madhavan Venkataraman		if (!(coargs->flags & COF_ADDR)) {
119487a18d3Madhavan Venkataraman			if (!(coargs->flags & COF_VERBOSE)) {
119587a18d3Madhavan Venkataraman				mdb_printf("%3d %1s ",
119687a18d3Madhavan Venkataraman				    TABLE_TO_SEQID(coargs->ndx),
119787a18d3Madhavan Venkataraman				    co_typenames[coargs->ndx &
119887a18d3Madhavan Venkataraman				    CALLOUT_TYPE_MASK]);
119987a18d3Madhavan Venkataraman			}
120087a18d3Madhavan Venkataraman
120151b32bdMadhavan Venkataraman			list_flags = coargs->list_flags;
12020724764Madhavan Venkataraman			mdb_printf("%-14llx %1s%1s %-6d %-0?p ",
120387a18d3Madhavan Venkataraman			    (coargs->flags & COF_EXPREL) ?
120487a18d3Madhavan Venkataraman			    coargs->exp - coargs->now : coargs->exp,
120551b32bdMadhavan Venkataraman			    (list_flags & CALLOUT_LIST_FLAG_HRESTIME) ?
12060724764Madhavan Venkataraman			    "H" : " ",
120751b32bdMadhavan Venkataraman			    (list_flags & CALLOUT_LIST_FLAG_ABSOLUTE) ?
12080724764Madhavan Venkataraman			    "A" : " ",
12090724764Madhavan Venkataraman			    coargs->bucket, cl->cl_callouts.ch_head);
121087a18d3Madhavan Venkataraman
121187a18d3Madhavan Venkataraman			if (coargs->flags & COF_LONGLIST) {
12120724764