db_ps.c revision 160893
1/*-
2 * Copyright (c) 1993 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/ddb/db_ps.c 160893 2006-08-01 22:30:55Z jhb $");
32
33#include <sys/param.h>
34#include <sys/cons.h>
35#include <sys/jail.h>
36#include <sys/kdb.h>
37#include <sys/linker_set.h>
38#include <sys/proc.h>
39#include <sys/sysent.h>
40#include <sys/systm.h>
41#include <vm/vm.h>
42#include <vm/vm_param.h>
43#include <vm/pmap.h>
44
45#include <ddb/ddb.h>
46
47static void	dumpthread(volatile struct proc *p, volatile struct thread *td,
48		    int all);
49
50/*
51 * Layout:
52 * - column counts
53 * - header
54 * - single-threaded process
55 * - multi-threaded process
56 * - thread in a MT process
57 *
58 *          1         2         3         4         5         6         7
59 * 1234567890123456789012345678901234567890123456789012345678901234567890
60 *   pid  ppid  pgrp   uid   state   wmesg     wchan    cmd
61 * <pid> <ppi> <pgi> <uid>  <stat> < wmesg > < wchan  > <name>
62 * <pid> <ppi> <pgi> <uid>  <stat>  (threaded)          <command>
63 * <tid >                   <stat> < wmesg > < wchan  > <name>
64 *
65 * For machines with 64-bit pointers, we expand the wchan field 8 more
66 * characters.
67 */
68void
69db_ps(db_expr_t addr, boolean_t hasaddr, db_expr_t count, char *modif)
70{
71	volatile struct proc *p, *pp;
72	volatile struct thread *td;
73	struct ucred *cred;
74	struct pgrp *pgrp;
75	char state[9];
76	int np, rflag, sflag, dflag, lflag, wflag;
77
78	np = nprocs;
79
80	if (!LIST_EMPTY(&allproc))
81		p = LIST_FIRST(&allproc);
82	else
83		p = &proc0;
84
85#ifdef __LP64__
86	db_printf("  pid  ppid  pgrp   uid   state   wmesg         wchan        cmd\n");
87#else
88	db_printf("  pid  ppid  pgrp   uid   state   wmesg     wchan    cmd\n");
89#endif
90	while (--np >= 0 && !db_pager_quit) {
91		if (p == NULL) {
92			db_printf("oops, ran out of processes early!\n");
93			break;
94		}
95		pp = p->p_pptr;
96		if (pp == NULL)
97			pp = p;
98
99		cred = p->p_ucred;
100		pgrp = p->p_pgrp;
101		db_printf("%5d %5d %5d %5d ", p->p_pid, pp->p_pid,
102		    pgrp != NULL ? pgrp->pg_id : 0,
103		    cred != NULL ? cred->cr_ruid : 0);
104
105		/* Determine our primary process state. */
106		switch (p->p_state) {
107		case PRS_NORMAL:
108			if (P_SHOULDSTOP(p))
109				state[0] = 'T';
110			else {
111				/*
112				 * One of D, L, R, S, W.  For a
113				 * multithreaded process we will use
114				 * the state of the thread with the
115				 * highest precedence.  The
116				 * precendence order from high to low
117				 * is R, L, D, S, W.  If no thread is
118				 * in a sane state we use '?' for our
119				 * primary state.
120				 */
121				rflag = sflag = dflag = lflag = wflag = 0;
122				FOREACH_THREAD_IN_PROC(p, td) {
123					if (td->td_state == TDS_RUNNING ||
124					    td->td_state == TDS_RUNQ ||
125					    td->td_state == TDS_CAN_RUN)
126						rflag++;
127					if (TD_ON_LOCK(td))
128						lflag++;
129					if (TD_IS_SLEEPING(td)) {
130						if (!td->td_flags & TDF_SINTR)
131							dflag++;
132						else
133							sflag++;
134					}
135					if (TD_AWAITING_INTR(td))
136						wflag++;
137				}
138				if (rflag)
139					state[0] = 'R';
140				else if (lflag)
141					state[0] = 'L';
142				else if (dflag)
143					state[0] = 'D';
144				else if (sflag)
145					state[0] = 'S';
146				else if (wflag)
147					state[0] = 'W';
148				else
149					state[0] = '?';
150			}
151			break;
152		case PRS_NEW:
153			state[0] = 'N';
154			break;
155		case PRS_ZOMBIE:
156			state[0] = 'Z';
157			break;
158		default:
159			state[0] = 'U';
160			break;
161		}
162		state[1] = '\0';
163
164		/* Additional process state flags. */
165		if (!p->p_sflag & PS_INMEM)
166			strlcat(state, "W", sizeof(state));
167		if (p->p_flag & P_TRACED)
168			strlcat(state, "X", sizeof(state));
169		if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE)
170			strlcat(state, "E", sizeof(state));
171		if (p->p_flag & P_PPWAIT)
172			strlcat(state, "V", sizeof(state));
173		if (p->p_flag & P_SYSTEM || p->p_lock > 0)
174			strlcat(state, "L", sizeof(state));
175		if (p->p_session != NULL && SESS_LEADER(p))
176			strlcat(state, "s", sizeof(state));
177		/* Cheated here and didn't compare pgid's. */
178		if (p->p_flag & P_CONTROLT)
179			strlcat(state, "+", sizeof(state));
180		if (cred != NULL && jailed(cred))
181			strlcat(state, "J", sizeof(state));
182		db_printf(" %-6.6s ", state);
183		if (p->p_flag & P_HADTHREADS)
184#ifdef __LP64__
185			db_printf(" (threaded)                  %s\n",
186			    p->p_comm);
187#else
188			db_printf(" (threaded)          %s\n", p->p_comm);
189#endif
190		FOREACH_THREAD_IN_PROC(p, td) {
191			dumpthread(p, td, p->p_flag & P_HADTHREADS);
192			if (db_pager_quit)
193				break;
194		}
195
196		p = LIST_NEXT(p, p_list);
197		if (p == NULL && np > 0)
198			p = LIST_FIRST(&zombproc);
199    	}
200}
201
202static void
203dumpthread(volatile struct proc *p, volatile struct thread *td, int all)
204{
205	char state[9], wprefix;
206	const char *wmesg;
207	void *wchan;
208
209	if (all) {
210		db_printf("%6d                  ", td->td_tid);
211		switch (td->td_state) {
212		case TDS_RUNNING:
213			snprintf(state, sizeof(state), "Run");
214			break;
215		case TDS_RUNQ:
216			snprintf(state, sizeof(state), "RunQ");
217			break;
218		case TDS_CAN_RUN:
219			snprintf(state, sizeof(state), "CanRun");
220			break;
221		case TDS_INACTIVE:
222			snprintf(state, sizeof(state), "Inactv");
223			break;
224		case TDS_INHIBITED:
225			state[0] = '\0';
226			if (TD_ON_LOCK(td))
227				strlcat(state, "L", sizeof(state));
228			if (TD_IS_SLEEPING(td)) {
229				if (td->td_flags & TDF_SINTR)
230					strlcat(state, "S", sizeof(state));
231				else
232					strlcat(state, "D", sizeof(state));
233			}
234			if (TD_IS_SWAPPED(td))
235				strlcat(state, "W", sizeof(state));
236			if (TD_AWAITING_INTR(td))
237				strlcat(state, "I", sizeof(state));
238			if (TD_IS_SUSPENDED(td))
239				strlcat(state, "s", sizeof(state));
240			if (state[0] != '\0')
241				break;
242		default:
243			snprintf(state, sizeof(state), "???");
244		}
245		db_printf(" %-6.6s ", state);
246	}
247	wprefix = ' ';
248	if (TD_ON_LOCK(td)) {
249		wprefix = '*';
250		wmesg = td->td_lockname;
251		wchan = td->td_blocked;
252	} else if (TD_ON_SLEEPQ(td)) {
253		wmesg = td->td_wmesg;
254		wchan = td->td_wchan;
255	} else if (TD_IS_RUNNING(td)) {
256		snprintf(state, sizeof(state), "CPU %d", td->td_oncpu);
257		wmesg = state;
258		wchan = NULL;
259	} else {
260		wmesg = "";
261		wchan = NULL;
262	}
263	db_printf("%c%-8.8s ", wprefix, wmesg);
264	if (wchan == NULL)
265#ifdef __LP64__
266		db_printf("%18s ", "");
267#else
268		db_printf("%10s ", "");
269#endif
270	else
271		db_printf("%p ", wchan);
272	if (p->p_flag & P_SYSTEM)
273		db_printf("[");
274	if (td->td_name[0] != '\0')
275		db_printf("%s", td->td_name);
276	else
277		db_printf("%s", td->td_proc->p_comm);
278	if (p->p_flag & P_SYSTEM)
279		db_printf("]");
280	db_printf("\n");
281}
282
283DB_SHOW_COMMAND(thread, db_show_thread)
284{
285	struct thread *td;
286	boolean_t comma;
287
288	/* Determine which thread to examine. */
289	if (have_addr)
290		td = db_lookup_thread(addr, FALSE);
291	else
292		td = kdb_thread;
293
294	db_printf("Thread %d at %p:\n", td->td_tid, td);
295	db_printf(" proc (pid %d): %p ", td->td_proc->p_pid, td->td_proc);
296	db_printf(" ksegrp: %p\n", td->td_ksegrp);
297	if (td->td_name[0] != '\0')
298		db_printf(" name: %s\n", td->td_name);
299	db_printf(" flags: %#x ", td->td_flags);
300	db_printf(" pflags: %#x\n", td->td_pflags);
301	db_printf(" state: ");
302	switch (td->td_state) {
303	case TDS_INACTIVE:
304		db_printf("INACTIVE\n");
305		break;
306	case TDS_CAN_RUN:
307		db_printf("CAN RUN\n");
308		break;
309	case TDS_RUNQ:
310		db_printf("RUNQ\n");
311		break;
312	case TDS_RUNNING:
313		db_printf("RUNNING (CPU %d)\n", td->td_oncpu);
314		break;
315	case TDS_INHIBITED:
316		db_printf("INHIBITED: {");
317		comma = FALSE;
318		if (TD_IS_SLEEPING(td)) {
319			db_printf("SLEEPING");
320			comma = TRUE;
321		}
322		if (TD_IS_SUSPENDED(td)) {
323			if (comma)
324				db_printf(", ");
325			db_printf("SUSPENDED");
326			comma = TRUE;
327		}
328		if (TD_IS_SWAPPED(td)) {
329			if (comma)
330				db_printf(", ");
331			db_printf("SWAPPED");
332			comma = TRUE;
333		}
334		if (TD_ON_LOCK(td)) {
335			if (comma)
336				db_printf(", ");
337			db_printf("LOCK");
338			comma = TRUE;
339		}
340		if (TD_AWAITING_INTR(td)) {
341			if (comma)
342				db_printf(", ");
343			db_printf("IWAIT");
344		}
345		db_printf("}\n");
346		break;
347	default:
348		db_printf("??? (%#x)\n", td->td_state);
349		break;
350	}
351	if (TD_ON_LOCK(td))
352		db_printf(" lock: %s  turnstile: %p\n", td->td_lockname,
353		    td->td_blocked);
354	if (TD_ON_SLEEPQ(td))
355		db_printf(" wmesg: %s  wchan: %p\n", td->td_wmesg,
356		    td->td_wchan);
357	db_printf(" priority: %d\n", td->td_priority);
358}
359
360DB_SHOW_COMMAND(proc, db_show_proc)
361{
362	struct thread *td;
363	struct proc *p;
364	int i;
365
366	/* Determine which process to examine. */
367	if (have_addr)
368		p = db_lookup_proc(addr);
369	else
370		p = kdb_thread->td_proc;
371
372	db_printf("Process %d (%s) at %p:\n", p->p_pid, p->p_comm, p);
373	db_printf(" state: ");
374	switch (p->p_state) {
375	case PRS_NEW:
376		db_printf("NEW\n");
377		break;
378	case PRS_NORMAL:
379		db_printf("NORMAL\n");
380		break;
381	case PRS_ZOMBIE:
382		db_printf("ZOMBIE\n");
383		break;
384	default:
385		db_printf("??? (%#x)\n", p->p_state);
386	}
387	if (p->p_ucred != NULL) {
388		db_printf(" uid: %d  gids: ", p->p_ucred->cr_uid);
389		for (i = 0; i < p->p_ucred->cr_ngroups; i++) {
390			db_printf("%d", p->p_ucred->cr_groups[i]);
391			if (i < (p->p_ucred->cr_ngroups - 1))
392				db_printf(", ");
393		}
394		db_printf("\n");
395	}
396	if (p->p_pptr != NULL)
397		db_printf(" parent: pid %d at %p\n", p->p_pptr->p_pid,
398		    p->p_pptr);
399	if (p->p_leader != NULL && p->p_leader != p)
400		db_printf(" leader: pid %d at %p\n", p->p_leader->p_pid,
401		    p->p_leader);
402	if (p->p_sysent != NULL)
403		db_printf(" ABI: %s\n", p->p_sysent->sv_name);
404	if (p->p_args != NULL)
405		db_printf(" arguments: %.*s\n", (int)p->p_args->ar_length,
406		    p->p_args->ar_args);
407	db_printf(" threads: %d\n", p->p_numthreads);
408	FOREACH_THREAD_IN_PROC(p, td) {
409		dumpthread(p, td, 1);
410		if (db_pager_quit)
411			break;
412	}
413}
414