db_ps.c revision 158456
12322Sdg/*- 22322Sdg * Copyright (c) 1993 The Regents of the University of California. 32322Sdg * All rights reserved. 42322Sdg * 52322Sdg * Redistribution and use in source and binary forms, with or without 62322Sdg * modification, are permitted provided that the following conditions 72322Sdg * are met: 82322Sdg * 1. Redistributions of source code must retain the above copyright 92322Sdg * notice, this list of conditions and the following disclaimer. 102322Sdg * 2. Redistributions in binary form must reproduce the above copyright 112322Sdg * notice, this list of conditions and the following disclaimer in the 122322Sdg * documentation and/or other materials provided with the distribution. 132322Sdg * 4. Neither the name of the University nor the names of its contributors 142322Sdg * may be used to endorse or promote products derived from this software 152322Sdg * without specific prior written permission. 162322Sdg * 172322Sdg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 182322Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 192322Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 202322Sdg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 212322Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 222322Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 232322Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 242322Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 252322Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 262322Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 272322Sdg * SUCH DAMAGE. 282322Sdg */ 29116176Sobrien 30116176Sobrien#include <sys/cdefs.h> 31116176Sobrien__FBSDID("$FreeBSD: head/sys/ddb/db_ps.c 158456 2006-05-11 21:59:55Z jhb $"); 32116176Sobrien 332322Sdg#include <sys/param.h> 34158092Sjhb#include <sys/cons.h> 35158032Sjhb#include <sys/jail.h> 36158032Sjhb#include <sys/kdb.h> 37158032Sjhb#include <sys/linker_set.h> 382322Sdg#include <sys/proc.h> 39158032Sjhb#include <sys/sysent.h> 40158092Sjhb#include <sys/systm.h> 41108338Sjulian#include <vm/vm.h> 42108338Sjulian#include <vm/vm_param.h> 43108338Sjulian#include <vm/pmap.h> 4412734Sbde 4512734Sbde#include <ddb/ddb.h> 4612734Sbde 47158032Sjhbstatic void dumpthread(volatile struct proc *p, volatile struct thread *td, 48158032Sjhb int all); 49158032Sjhb 50158032Sjhb/* 51158032Sjhb * Layout: 52158032Sjhb * - column counts 53158032Sjhb * - header 54158032Sjhb * - single-threaded process 55158032Sjhb * - multi-threaded process 56158032Sjhb * - thread in a MT process 57158032Sjhb * 58158032Sjhb * 1 2 3 4 5 6 7 59158032Sjhb * 1234567890123456789012345678901234567890123456789012345678901234567890 60158032Sjhb * pid uid ppid pgrp state wmesg wchan cmd 61158032Sjhb * <pid> <ui> <ppi> <pgi> <stat> < wmesg > < wchan > <name> 62158032Sjhb * <pid> <ui> <ppi> <pgi> <stat> (threaded) <command> 63158032Sjhb * <tid > <stat> < wmesg > < wchan > <name> 64158032Sjhb * 65158032Sjhb * For machines with 64-bit pointers, we expand the wchan field 8 more 66158032Sjhb * characters. 67158032Sjhb */ 682322Sdgvoid 69158032Sjhbdb_ps(db_expr_t addr, boolean_t hasaddr, db_expr_t count, char *modif) 7010349Sbde{ 7110128Sdg volatile struct proc *p, *pp; 7285207Sjhb volatile struct thread *td; 73158032Sjhb struct ucred *cred; 74158032Sjhb struct pgrp *pgrp; 75158032Sjhb char state[9]; 76158032Sjhb int np, quit, rflag, sflag, dflag, lflag, wflag; 7710128Sdg 782322Sdg np = nprocs; 79118269Sjhb quit = 0; 802322Sdg 8170527Sphk if (!LIST_EMPTY(&allproc)) 8270527Sphk p = LIST_FIRST(&allproc); 8310128Sdg else 8410128Sdg p = &proc0; 8510128Sdg 86137117Sjhb db_setup_paging(db_simple_pager, &quit, db_lines_per_page); 87158456Sjhb#ifdef __LP64__ 88158032Sjhb db_printf(" pid uid ppid pgrp state wmesg wchan cmd\n"); 89158032Sjhb#else 90158032Sjhb db_printf(" pid uid ppid pgrp state wmesg wchan cmd\n"); 91158032Sjhb#endif 92118269Sjhb while (--np >= 0 && !quit) { 9316381Speter if (p == NULL) { 94158032Sjhb db_printf("oops, ran out of processes early!\n"); 9516381Speter break; 9616381Speter } 972322Sdg pp = p->p_pptr; 9810128Sdg if (pp == NULL) 992322Sdg pp = p; 10010128Sdg 101158032Sjhb cred = p->p_ucred; 102158032Sjhb pgrp = p->p_pgrp; 103158032Sjhb db_printf("%5d %4d %5d %5d ", p->p_pid, 104158032Sjhb cred != NULL ? cred->cr_ruid : 0, pp->p_pid, 105158032Sjhb pgrp != NULL ? pgrp->pg_id : 0); 10699072Sjulian 107158032Sjhb /* Determine our primary process state. */ 108158091Sjhb switch (p->p_state) { 10999072Sjulian case PRS_NORMAL: 11099072Sjulian if (P_SHOULDSTOP(p)) 111158032Sjhb state[0] = 'T'; 112158032Sjhb else { 113158032Sjhb /* 114158032Sjhb * One of D, L, R, S, W. For a 115158032Sjhb * multithreaded process we will use 116158032Sjhb * the state of the thread with the 117158032Sjhb * highest precedence. The 118158032Sjhb * precendence order from high to low 119158032Sjhb * is R, L, D, S, W. If no thread is 120158032Sjhb * in a sane state we use '?' for our 121158032Sjhb * primary state. 122158032Sjhb */ 123158032Sjhb rflag = sflag = dflag = lflag = wflag = 0; 124158032Sjhb FOREACH_THREAD_IN_PROC(p, td) { 125158032Sjhb if (td->td_state == TDS_RUNNING || 126158032Sjhb td->td_state == TDS_RUNQ || 127158032Sjhb td->td_state == TDS_CAN_RUN) 128158032Sjhb rflag++; 129158032Sjhb if (TD_ON_LOCK(td)) 130158032Sjhb lflag++; 131158032Sjhb if (TD_IS_SLEEPING(td)) { 132158032Sjhb if (!td->td_flags & TDF_SINTR) 133158032Sjhb dflag++; 134158032Sjhb else 135158032Sjhb sflag++; 136158032Sjhb } 137158032Sjhb if (TD_AWAITING_INTR(td)) 138158032Sjhb wflag++; 139158032Sjhb } 140158032Sjhb if (rflag) 141158032Sjhb state[0] = 'R'; 142158032Sjhb else if (lflag) 143158032Sjhb state[0] = 'L'; 144158032Sjhb else if (dflag) 145158032Sjhb state[0] = 'D'; 146158032Sjhb else if (sflag) 147158032Sjhb state[0] = 'S'; 148158032Sjhb else if (wflag) 149158032Sjhb state[0] = 'W'; 150158032Sjhb else 151158032Sjhb state[0] = '?'; 152158032Sjhb } 15399072Sjulian break; 15499072Sjulian case PRS_NEW: 155158032Sjhb state[0] = 'N'; 15699072Sjulian break; 15799072Sjulian case PRS_ZOMBIE: 158158032Sjhb state[0] = 'Z'; 15999072Sjulian break; 16099072Sjulian default: 161158032Sjhb state[0] = 'U'; 16299072Sjulian break; 16399072Sjulian } 164158032Sjhb state[1] = '\0'; 165158032Sjhb 166158032Sjhb /* Additional process state flags. */ 167158032Sjhb if (!p->p_sflag & PS_INMEM) 168158032Sjhb strlcat(state, "W", sizeof(state)); 169158032Sjhb if (p->p_flag & P_TRACED) 170158032Sjhb strlcat(state, "X", sizeof(state)); 171158032Sjhb if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE) 172158032Sjhb strlcat(state, "E", sizeof(state)); 173158032Sjhb if (p->p_flag & P_PPWAIT) 174158032Sjhb strlcat(state, "V", sizeof(state)); 175158032Sjhb if (p->p_flag & P_SYSTEM || p->p_lock > 0) 176158032Sjhb strlcat(state, "L", sizeof(state)); 177158032Sjhb if (p->p_session != NULL && SESS_LEADER(p)) 178158032Sjhb strlcat(state, "s", sizeof(state)); 179158032Sjhb /* Cheated here and didn't compare pgid's. */ 180158032Sjhb if (p->p_flag & P_CONTROLT) 181158032Sjhb strlcat(state, "+", sizeof(state)); 182158032Sjhb if (cred != NULL && jailed(cred)) 183158032Sjhb strlcat(state, "J", sizeof(state)); 184158032Sjhb db_printf(" %-6.6s ", state); 185134791Sjulian if (p->p_flag & P_HADTHREADS) 186158456Sjhb#ifdef __LP64__ 187158032Sjhb db_printf(" (threaded) %s\n", 188158032Sjhb p->p_comm); 189158032Sjhb#else 190158032Sjhb db_printf(" (threaded) %s\n", p->p_comm); 191158032Sjhb#endif 192103216Sjulian FOREACH_THREAD_IN_PROC(p, td) { 193158032Sjhb dumpthread(p, td, p->p_flag & P_HADTHREADS); 194118269Sjhb if (quit) 195118269Sjhb break; 1962322Sdg } 19794456Sjhb 19870527Sphk p = LIST_NEXT(p, p_list); 19910128Sdg if (p == NULL && np > 0) 20070527Sphk p = LIST_FIRST(&zombproc); 2012322Sdg } 2022322Sdg} 203115903Sjhb 204108338Sjulianstatic void 205158032Sjhbdumpthread(volatile struct proc *p, volatile struct thread *td, int all) 206108338Sjulian{ 207158032Sjhb char state[9], wprefix; 208158032Sjhb const char *wmesg; 209158032Sjhb void *wchan; 210158032Sjhb 211158032Sjhb if (all) { 212158032Sjhb db_printf(" %9d ", td->td_tid); 213158032Sjhb switch (td->td_state) { 214158032Sjhb case TDS_RUNNING: 215158032Sjhb snprintf(state, sizeof(state), "Run"); 216158032Sjhb break; 217158032Sjhb case TDS_RUNQ: 218158032Sjhb snprintf(state, sizeof(state), "RunQ"); 219158032Sjhb break; 220158032Sjhb case TDS_CAN_RUN: 221158032Sjhb snprintf(state, sizeof(state), "CanRun"); 222158032Sjhb break; 223158032Sjhb case TDS_INACTIVE: 224158032Sjhb snprintf(state, sizeof(state), "Inactv"); 225158032Sjhb break; 226158032Sjhb case TDS_INHIBITED: 227158032Sjhb state[0] = '\0'; 228158032Sjhb if (TD_ON_LOCK(td)) 229158032Sjhb strlcat(state, "L", sizeof(state)); 230158032Sjhb if (TD_IS_SLEEPING(td)) { 231158032Sjhb if (td->td_flags & TDF_SINTR) 232158032Sjhb strlcat(state, "S", sizeof(state)); 233158032Sjhb else 234158032Sjhb strlcat(state, "D", sizeof(state)); 235158032Sjhb } 236158032Sjhb if (TD_IS_SWAPPED(td)) 237158032Sjhb strlcat(state, "W", sizeof(state)); 238158032Sjhb if (TD_AWAITING_INTR(td)) 239158032Sjhb strlcat(state, "I", sizeof(state)); 240158032Sjhb if (TD_IS_SUSPENDED(td)) 241158032Sjhb strlcat(state, "s", sizeof(state)); 242158032Sjhb if (state[0] != '\0') 243158032Sjhb break; 244158032Sjhb default: 245158032Sjhb snprintf(state, sizeof(state), "???"); 246158032Sjhb } 247158032Sjhb db_printf(" %-6.6s ", state); 248158032Sjhb } 249158032Sjhb wprefix = ' '; 250158032Sjhb if (TD_ON_LOCK(td)) { 251158032Sjhb wprefix = '*'; 252158032Sjhb wmesg = td->td_lockname; 253158032Sjhb wchan = td->td_blocked; 254158032Sjhb } else if (TD_ON_SLEEPQ(td)) { 255158032Sjhb wmesg = td->td_wmesg; 256158032Sjhb wchan = td->td_wchan; 257158032Sjhb } else if (TD_IS_RUNNING(td)) { 258158032Sjhb snprintf(state, sizeof(state), "CPU %d", td->td_oncpu); 259158032Sjhb wmesg = state; 260158032Sjhb wchan = NULL; 261158032Sjhb } else { 262158032Sjhb wmesg = ""; 263158032Sjhb wchan = NULL; 264158032Sjhb } 265158032Sjhb db_printf("%c%-8.8s ", wprefix, wmesg); 266158032Sjhb if (wchan == NULL) 267158456Sjhb#ifdef __LP64__ 268158032Sjhb db_printf("%18s ", ""); 269158032Sjhb#else 270158032Sjhb db_printf("%10s ", ""); 271158032Sjhb#endif 272158032Sjhb else 273158032Sjhb db_printf("%p ", wchan); 274158032Sjhb if (p->p_flag & P_SYSTEM) 275158032Sjhb db_printf("["); 276158032Sjhb if (td->td_name[0] != '\0') 277158032Sjhb db_printf("%s", td->td_name); 278158032Sjhb else 279158032Sjhb db_printf("%s", td->td_proc->p_comm); 280158032Sjhb if (p->p_flag & P_SYSTEM) 281158032Sjhb db_printf("]"); 282158032Sjhb db_printf("\n"); 283158032Sjhb} 284118228Sjhb 285158032SjhbDB_SHOW_COMMAND(thread, db_show_thread) 286158032Sjhb{ 287158032Sjhb struct thread *td; 288158032Sjhb boolean_t comma; 289158032Sjhb 290158032Sjhb /* Determine which thread to examine. */ 291158032Sjhb if (have_addr) 292158032Sjhb td = db_lookup_thread(addr, FALSE); 293158032Sjhb else 294158032Sjhb td = kdb_thread; 295158032Sjhb 296158032Sjhb db_printf("Thread %d at %p:\n", td->td_tid, td); 297158032Sjhb db_printf(" proc (pid %d): %p ", td->td_proc->p_pid, td->td_proc); 298158032Sjhb db_printf(" ksegrp: %p\n", td->td_ksegrp); 299158032Sjhb if (td->td_name[0] != '\0') 300158032Sjhb db_printf(" name: %s\n", td->td_name); 301158032Sjhb db_printf(" flags: %#x ", td->td_flags); 302158032Sjhb db_printf(" pflags: %#x\n", td->td_pflags); 303158032Sjhb db_printf(" state: "); 304108338Sjulian switch (td->td_state) { 305158032Sjhb case TDS_INACTIVE: 306158032Sjhb db_printf("INACTIVE\n"); 307158032Sjhb break; 308158032Sjhb case TDS_CAN_RUN: 309158032Sjhb db_printf("CAN RUN\n"); 310158032Sjhb break; 311158032Sjhb case TDS_RUNQ: 312158032Sjhb db_printf("RUNQ\n"); 313158032Sjhb break; 314158032Sjhb case TDS_RUNNING: 315158032Sjhb db_printf("RUNNING (CPU %d)\n", td->td_oncpu); 316158032Sjhb break; 317108338Sjulian case TDS_INHIBITED: 318158032Sjhb db_printf("INHIBITED: {"); 319158032Sjhb comma = FALSE; 320108338Sjulian if (TD_IS_SLEEPING(td)) { 321158032Sjhb db_printf("SLEEPING"); 322158032Sjhb comma = TRUE; 323108338Sjulian } 324108338Sjulian if (TD_IS_SUSPENDED(td)) { 325158032Sjhb if (comma) 326158032Sjhb db_printf(", "); 327158032Sjhb db_printf("SUSPENDED"); 328158032Sjhb comma = TRUE; 329108338Sjulian } 330158032Sjhb if (TD_IS_SWAPPED(td)) { 331158032Sjhb if (comma) 332158032Sjhb db_printf(", "); 333158032Sjhb db_printf("SWAPPED"); 334158032Sjhb comma = TRUE; 335158032Sjhb } 336158032Sjhb if (TD_ON_LOCK(td)) { 337158032Sjhb if (comma) 338158032Sjhb db_printf(", "); 339158032Sjhb db_printf("LOCK"); 340158032Sjhb comma = TRUE; 341158032Sjhb } 342108338Sjulian if (TD_AWAITING_INTR(td)) { 343158032Sjhb if (comma) 344158032Sjhb db_printf(", "); 345158032Sjhb db_printf("IWAIT"); 346108338Sjulian } 347158032Sjhb db_printf("}\n"); 348108338Sjulian break; 349158032Sjhb default: 350158032Sjhb db_printf("??? (%#x)\n", td->td_state); 351108338Sjulian break; 352158032Sjhb } 353158032Sjhb if (TD_ON_LOCK(td)) 354158032Sjhb db_printf(" lock: %s turnstile: %p\n", td->td_lockname, 355158032Sjhb td->td_blocked); 356158032Sjhb if (TD_ON_SLEEPQ(td)) 357158032Sjhb db_printf(" wmesg: %s wchan: %p\n", td->td_wmesg, 358158032Sjhb td->td_wchan); 359158032Sjhb db_printf(" priority: %d\n", td->td_priority); 360158032Sjhb} 361158032Sjhb 362158032SjhbDB_SHOW_COMMAND(proc, db_show_proc) 363158032Sjhb{ 364158032Sjhb struct thread *td; 365158032Sjhb struct proc *p; 366158032Sjhb int i, quit; 367158032Sjhb 368158032Sjhb /* Determine which process to examine. */ 369158032Sjhb if (have_addr) 370158032Sjhb p = db_lookup_proc(addr); 371158032Sjhb else 372158032Sjhb p = kdb_thread->td_proc; 373158032Sjhb 374158032Sjhb quit = 0; 375158032Sjhb db_setup_paging(db_simple_pager, &quit, db_lines_per_page); 376158032Sjhb db_printf("Process %d (%s) at %p:\n", p->p_pid, p->p_comm, p); 377158032Sjhb db_printf(" state: "); 378158032Sjhb switch (p->p_state) { 379158032Sjhb case PRS_NEW: 380158032Sjhb db_printf("NEW\n"); 381108338Sjulian break; 382158032Sjhb case PRS_NORMAL: 383158032Sjhb db_printf("NORMAL\n"); 384108338Sjulian break; 385158032Sjhb case PRS_ZOMBIE: 386158032Sjhb db_printf("ZOMBIE\n"); 387115904Sjhb break; 388108338Sjulian default: 389158032Sjhb db_printf("??? (%#x)\n", p->p_state); 390108338Sjulian } 391158032Sjhb if (p->p_ucred != NULL) { 392158032Sjhb db_printf(" uid: %d gids: ", p->p_ucred->cr_uid); 393158032Sjhb for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 394158032Sjhb db_printf("%d", p->p_ucred->cr_groups[i]); 395158032Sjhb if (i < (p->p_ucred->cr_ngroups - 1)) 396158032Sjhb db_printf(", "); 397158032Sjhb } 398108338Sjulian db_printf("\n"); 399158032Sjhb } 400158032Sjhb if (p->p_pptr != NULL) 401158032Sjhb db_printf(" parent: pid %d at %p\n", p->p_pptr->p_pid, 402158032Sjhb p->p_pptr); 403158032Sjhb if (p->p_leader != NULL && p->p_leader != p) 404158032Sjhb db_printf(" leader: pid %d at %p\n", p->p_leader->p_pid, 405158032Sjhb p->p_leader); 406158032Sjhb if (p->p_sysent != NULL) 407158032Sjhb db_printf(" ABI: %s\n", p->p_sysent->sv_name); 408158032Sjhb if (p->p_args != NULL) 409158032Sjhb db_printf(" arguments: %.*s\n", (int)p->p_args->ar_length, 410158032Sjhb p->p_args->ar_args); 411158032Sjhb db_printf(" threads: %d\n", p->p_numthreads); 412158032Sjhb FOREACH_THREAD_IN_PROC(p, td) { 413158032Sjhb dumpthread(p, td, 1); 414158032Sjhb if (quit) 415158032Sjhb break; 416158032Sjhb } 417108338Sjulian} 418