db_ps.c revision 116361
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 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/ddb/db_ps.c 116361 2003-06-15 00:31:24Z davidxu $");
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/lock.h>
40#include <sys/mutex.h>
41#include <sys/proc.h>
42#include <sys/cons.h>
43#include <vm/vm.h>
44#include <vm/vm_param.h>
45#include <vm/pmap.h>
46
47#include <ddb/ddb.h>
48
49static void	dumpthread(volatile struct proc *p, volatile struct thread *td);
50
51void
52db_ps(dummy1, dummy2, dummy3, dummy4)
53	db_expr_t	dummy1;
54	boolean_t	dummy2;
55	db_expr_t	dummy3;
56	char *		dummy4;
57{
58	int np;
59	int nl = 0;
60	volatile struct proc *p, *pp;
61	volatile struct thread *td;
62	char *state;
63
64	np = nprocs;
65
66	/* sx_slock(&allproc_lock); */
67	if (!LIST_EMPTY(&allproc))
68		p = LIST_FIRST(&allproc);
69	else
70		p = &proc0;
71
72	db_printf("  pid   proc     addr    uid  ppid  pgrp  flag   stat  wmesg    wchan  cmd\n");
73	while (--np >= 0) {
74		/*
75		 * XXX just take 20 for now...
76		 */
77		if (nl++ >= 20) {
78			int c;
79
80			db_printf("--More--");
81			c = cngetc();
82			db_printf("\r");
83			/*
84			 * A whole screenfull or just one line?
85			 */
86			switch (c) {
87			case '\n':		/* just one line */
88				nl = 20;
89				break;
90			case ' ':
91				nl = 0;		/* another screenfull */
92				break;
93			default:		/* exit */
94				db_printf("\n");
95				return;
96			}
97		}
98		if (p == NULL) {
99			printf("oops, ran out of processes early!\n");
100			break;
101		}
102		/* PROC_LOCK(p); */
103		pp = p->p_pptr;
104		if (pp == NULL)
105			pp = p;
106
107
108		switch(p->p_state) {
109		case PRS_NORMAL:
110			if (P_SHOULDSTOP(p))
111				state = "stop";
112			else
113				state = "";
114			break;
115		case PRS_NEW:
116			state = "new ";
117			break;
118		case PRS_ZOMBIE:
119			state = "zomb";
120			break;
121		default:
122			state = "Unkn";
123			break;
124		}
125		db_printf("%5d %8p %8p %4d %5d %5d %07x %s",
126		    p->p_pid, (volatile void *)p, (void *)p->p_uarea,
127		    p->p_ucred != NULL ? p->p_ucred->cr_ruid : 0, pp->p_pid,
128		    p->p_pgrp != NULL ? p->p_pgrp->pg_id : 0, p->p_flag,
129		    state);
130		if (p->p_flag & P_SA)
131			db_printf("(threaded)  %s\n", p->p_comm);
132		FOREACH_THREAD_IN_PROC(p, td) {
133			dumpthread(p, td);
134			nl++;
135		}
136		/* PROC_UNLOCK(p); */
137
138		p = LIST_NEXT(p, p_list);
139		if (p == NULL && np > 0)
140			p = LIST_FIRST(&zombproc);
141    	}
142	/* sx_sunlock(&allproc_lock); */
143}
144
145static void
146dumpthread(volatile struct proc *p, volatile struct thread *td)
147{
148	if (p->p_flag & P_SA)
149		db_printf( "   thread %p ksegrp %p ", td, td->td_ksegrp);
150	if (TD_ON_SLEEPQ(td)) {
151		if (td->td_flags & TDF_CVWAITQ)
152			if (TD_IS_SLEEPING(td))
153				db_printf("[CV]");
154			else
155				db_printf("[CVQ");
156		else
157			if (TD_IS_SLEEPING(td))
158				db_printf("[SLP]");
159			else
160				db_printf("[SLPQ");
161		db_printf("%s %p]", td->td_wmesg,
162		    (void *)td->td_wchan);
163	}
164	switch (td->td_state) {
165	case TDS_INHIBITED:
166		if (TD_ON_LOCK(td)) {
167			db_printf("[LOCK %6s %8p]",
168			    td->td_lockname,
169			    (void *)td->td_blocked);
170		}
171#if 0 /* covered above */
172		if (TD_IS_SLEEPING(td)) {
173			db_printf("[SLP]");
174		}
175#endif
176		if (TD_IS_SWAPPED(td)) {
177			db_printf("[SWAP]");
178		}
179		if (TD_IS_SUSPENDED(td)) {
180			db_printf("[SUSP]");
181		}
182		if (TD_AWAITING_INTR(td)) {
183			db_printf("[IWAIT]");
184		}
185		break;
186	case TDS_CAN_RUN:
187		db_printf("[Can run]");
188		break;
189	case TDS_RUNQ:
190		db_printf("[RUNQ]");
191		break;
192	case TDS_RUNNING:
193		db_printf("[CPU %d]", td->td_oncpu);
194		break;
195	case TDS_INACTIVE:
196		db_printf("[INACTIVE]");
197		break;
198	default:
199		db_printf("[UNK: %#x]", td->td_state);
200	}
201	if (p->p_flag & P_SA) {
202		if (td->td_kse)
203			db_printf("[kse %p]", td->td_kse);
204		db_printf("\n");
205	} else
206		db_printf(" %s\n", p->p_comm);
207}
208
209
210#define INKERNEL(va)    (((vm_offset_t)(va)) >= USRSTACK)
211void
212db_show_one_thread(db_expr_t addr, boolean_t have_addr,
213		db_expr_t count, char *modif)
214{
215	struct proc *p;
216	struct thread *td;
217
218	if (!have_addr)
219		td = curthread;
220	else if (!INKERNEL(addr)) {
221		printf("bad thread address");
222		return;
223	} else
224		td = (struct thread *)addr;
225	/* quick sanity check */
226	if ((p = td->td_proc) != td->td_ksegrp->kg_proc)
227		return;
228	printf("Proc %p ",p);
229	dumpthread(p, td);
230#ifdef	__i386__
231	db_stack_thread((db_expr_t)td, 1, count, modif);
232#endif
233}
234