db_ps.c revision 158032
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 158032 2006-04-25 20:34:04Z jhb $"); 32116176Sobrien 332322Sdg#include <sys/param.h> 342322Sdg#include <sys/systm.h> 35158032Sjhb#include <sys/jail.h> 36158032Sjhb#include <sys/kdb.h> 37158032Sjhb#include <sys/linker_set.h> 3874914Sjhb#include <sys/lock.h> 3974914Sjhb#include <sys/mutex.h> 402322Sdg#include <sys/proc.h> 41158032Sjhb#include <sys/sysent.h> 4249558Sphk#include <sys/cons.h> 43108338Sjulian#include <vm/vm.h> 44108338Sjulian#include <vm/vm_param.h> 45108338Sjulian#include <vm/pmap.h> 4612734Sbde 4712734Sbde#include <ddb/ddb.h> 4812734Sbde 49158032Sjhb/* XXX I'd prefer a better way. */ 50158032Sjhb#if defined(__alpha__) || defined(__amd64__) || defined(__ia64__) || defined(__sparc64__) 51158032Sjhb#define PTR64 52158032Sjhb#endif 53115903Sjhb 54158032Sjhb#ifdef PTR64 55158032SjhbCTASSERT(sizeof(uintptr_t) == sizeof(uint64_t)); 56158032Sjhb#else 57158032SjhbCTASSERT(sizeof(uintptr_t) == sizeof(uint32_t)); 58158032Sjhb#endif 59158032Sjhb 60158032Sjhbstatic void dumpthread(volatile struct proc *p, volatile struct thread *td, 61158032Sjhb int all); 62158032Sjhb 63158032Sjhb/* 64158032Sjhb * Layout: 65158032Sjhb * - column counts 66158032Sjhb * - header 67158032Sjhb * - single-threaded process 68158032Sjhb * - multi-threaded process 69158032Sjhb * - thread in a MT process 70158032Sjhb * 71158032Sjhb * 1 2 3 4 5 6 7 72158032Sjhb * 1234567890123456789012345678901234567890123456789012345678901234567890 73158032Sjhb * pid uid ppid pgrp state wmesg wchan cmd 74158032Sjhb * <pid> <ui> <ppi> <pgi> <stat> < wmesg > < wchan > <name> 75158032Sjhb * <pid> <ui> <ppi> <pgi> <stat> (threaded) <command> 76158032Sjhb * <tid > <stat> < wmesg > < wchan > <name> 77158032Sjhb * 78158032Sjhb * For machines with 64-bit pointers, we expand the wchan field 8 more 79158032Sjhb * characters. 80158032Sjhb */ 812322Sdgvoid 82158032Sjhbdb_ps(db_expr_t addr, boolean_t hasaddr, db_expr_t count, char *modif) 8310349Sbde{ 8410128Sdg volatile struct proc *p, *pp; 8585207Sjhb volatile struct thread *td; 86158032Sjhb struct ucred *cred; 87158032Sjhb struct pgrp *pgrp; 88158032Sjhb char state[9]; 89158032Sjhb int np, quit, rflag, sflag, dflag, lflag, wflag; 9010128Sdg 912322Sdg np = nprocs; 92118269Sjhb quit = 0; 932322Sdg 9494456Sjhb /* sx_slock(&allproc_lock); */ 9570527Sphk if (!LIST_EMPTY(&allproc)) 9670527Sphk p = LIST_FIRST(&allproc); 9710128Sdg else 9810128Sdg p = &proc0; 9910128Sdg 100137117Sjhb db_setup_paging(db_simple_pager, &quit, db_lines_per_page); 101158032Sjhb#ifdef PTR64 102158032Sjhb db_printf(" pid uid ppid pgrp state wmesg wchan cmd\n"); 103158032Sjhb#else 104158032Sjhb db_printf(" pid uid ppid pgrp state wmesg wchan cmd\n"); 105158032Sjhb#endif 106118269Sjhb while (--np >= 0 && !quit) { 10716381Speter if (p == NULL) { 108158032Sjhb db_printf("oops, ran out of processes early!\n"); 10916381Speter break; 11016381Speter } 11194456Sjhb /* PROC_LOCK(p); */ 1122322Sdg pp = p->p_pptr; 11310128Sdg if (pp == NULL) 1142322Sdg pp = p; 11510128Sdg 116158032Sjhb cred = p->p_ucred; 117158032Sjhb pgrp = p->p_pgrp; 118158032Sjhb db_printf("%5d %4d %5d %5d ", p->p_pid, 119158032Sjhb cred != NULL ? cred->cr_ruid : 0, pp->p_pid, 120158032Sjhb pgrp != NULL ? pgrp->pg_id : 0); 12199072Sjulian 122158032Sjhb /* Determine our primary process state. */ 12399072Sjulian switch(p->p_state) { 12499072Sjulian case PRS_NORMAL: 12599072Sjulian if (P_SHOULDSTOP(p)) 126158032Sjhb state[0] = 'T'; 127158032Sjhb else { 128158032Sjhb /* 129158032Sjhb * One of D, L, R, S, W. For a 130158032Sjhb * multithreaded process we will use 131158032Sjhb * the state of the thread with the 132158032Sjhb * highest precedence. The 133158032Sjhb * precendence order from high to low 134158032Sjhb * is R, L, D, S, W. If no thread is 135158032Sjhb * in a sane state we use '?' for our 136158032Sjhb * primary state. 137158032Sjhb */ 138158032Sjhb rflag = sflag = dflag = lflag = wflag = 0; 139158032Sjhb FOREACH_THREAD_IN_PROC(p, td) { 140158032Sjhb if (td->td_state == TDS_RUNNING || 141158032Sjhb td->td_state == TDS_RUNQ || 142158032Sjhb td->td_state == TDS_CAN_RUN) 143158032Sjhb rflag++; 144158032Sjhb if (TD_ON_LOCK(td)) 145158032Sjhb lflag++; 146158032Sjhb if (TD_IS_SLEEPING(td)) { 147158032Sjhb if (!td->td_flags & TDF_SINTR) 148158032Sjhb dflag++; 149158032Sjhb else 150158032Sjhb sflag++; 151158032Sjhb } 152158032Sjhb if (TD_AWAITING_INTR(td)) 153158032Sjhb wflag++; 154158032Sjhb } 155158032Sjhb if (rflag) 156158032Sjhb state[0] = 'R'; 157158032Sjhb else if (lflag) 158158032Sjhb state[0] = 'L'; 159158032Sjhb else if (dflag) 160158032Sjhb state[0] = 'D'; 161158032Sjhb else if (sflag) 162158032Sjhb state[0] = 'S'; 163158032Sjhb else if (wflag) 164158032Sjhb state[0] = 'W'; 165158032Sjhb else 166158032Sjhb state[0] = '?'; 167158032Sjhb } 16899072Sjulian break; 16999072Sjulian case PRS_NEW: 170158032Sjhb state[0] = 'N'; 17199072Sjulian break; 17299072Sjulian case PRS_ZOMBIE: 173158032Sjhb state[0] = 'Z'; 17499072Sjulian break; 17599072Sjulian default: 176158032Sjhb state[0] = 'U'; 17799072Sjulian break; 17899072Sjulian } 179158032Sjhb state[1] = '\0'; 180158032Sjhb 181158032Sjhb /* Additional process state flags. */ 182158032Sjhb if (!p->p_sflag & PS_INMEM) 183158032Sjhb strlcat(state, "W", sizeof(state)); 184158032Sjhb if (p->p_flag & P_TRACED) 185158032Sjhb strlcat(state, "X", sizeof(state)); 186158032Sjhb if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE) 187158032Sjhb strlcat(state, "E", sizeof(state)); 188158032Sjhb if (p->p_flag & P_PPWAIT) 189158032Sjhb strlcat(state, "V", sizeof(state)); 190158032Sjhb if (p->p_flag & P_SYSTEM || p->p_lock > 0) 191158032Sjhb strlcat(state, "L", sizeof(state)); 192158032Sjhb if (p->p_session != NULL && SESS_LEADER(p)) 193158032Sjhb strlcat(state, "s", sizeof(state)); 194158032Sjhb /* Cheated here and didn't compare pgid's. */ 195158032Sjhb if (p->p_flag & P_CONTROLT) 196158032Sjhb strlcat(state, "+", sizeof(state)); 197158032Sjhb if (cred != NULL && jailed(cred)) 198158032Sjhb strlcat(state, "J", sizeof(state)); 199158032Sjhb db_printf(" %-6.6s ", state); 200134791Sjulian if (p->p_flag & P_HADTHREADS) 201158032Sjhb#ifdef PTR64 202158032Sjhb db_printf(" (threaded) %s\n", 203158032Sjhb p->p_comm); 204158032Sjhb#else 205158032Sjhb db_printf(" (threaded) %s\n", p->p_comm); 206158032Sjhb#endif 207103216Sjulian FOREACH_THREAD_IN_PROC(p, td) { 208158032Sjhb dumpthread(p, td, p->p_flag & P_HADTHREADS); 209118269Sjhb if (quit) 210118269Sjhb break; 2112322Sdg } 21294456Sjhb /* PROC_UNLOCK(p); */ 21394456Sjhb 21470527Sphk p = LIST_NEXT(p, p_list); 21510128Sdg if (p == NULL && np > 0) 21670527Sphk p = LIST_FIRST(&zombproc); 2172322Sdg } 21894456Sjhb /* sx_sunlock(&allproc_lock); */ 2192322Sdg} 220115903Sjhb 221108338Sjulianstatic void 222158032Sjhbdumpthread(volatile struct proc *p, volatile struct thread *td, int all) 223108338Sjulian{ 224158032Sjhb char state[9], wprefix; 225158032Sjhb const char *wmesg; 226158032Sjhb void *wchan; 227158032Sjhb 228158032Sjhb if (all) { 229158032Sjhb db_printf(" %9d ", td->td_tid); 230158032Sjhb switch (td->td_state) { 231158032Sjhb case TDS_RUNNING: 232158032Sjhb snprintf(state, sizeof(state), "Run"); 233158032Sjhb break; 234158032Sjhb case TDS_RUNQ: 235158032Sjhb snprintf(state, sizeof(state), "RunQ"); 236158032Sjhb break; 237158032Sjhb case TDS_CAN_RUN: 238158032Sjhb snprintf(state, sizeof(state), "CanRun"); 239158032Sjhb break; 240158032Sjhb case TDS_INACTIVE: 241158032Sjhb snprintf(state, sizeof(state), "Inactv"); 242158032Sjhb break; 243158032Sjhb case TDS_INHIBITED: 244158032Sjhb state[0] = '\0'; 245158032Sjhb if (TD_ON_LOCK(td)) 246158032Sjhb strlcat(state, "L", sizeof(state)); 247158032Sjhb if (TD_IS_SLEEPING(td)) { 248158032Sjhb if (td->td_flags & TDF_SINTR) 249158032Sjhb strlcat(state, "S", sizeof(state)); 250158032Sjhb else 251158032Sjhb strlcat(state, "D", sizeof(state)); 252158032Sjhb } 253158032Sjhb if (TD_IS_SWAPPED(td)) 254158032Sjhb strlcat(state, "W", sizeof(state)); 255158032Sjhb if (TD_AWAITING_INTR(td)) 256158032Sjhb strlcat(state, "I", sizeof(state)); 257158032Sjhb if (TD_IS_SUSPENDED(td)) 258158032Sjhb strlcat(state, "s", sizeof(state)); 259158032Sjhb if (state[0] != '\0') 260158032Sjhb break; 261158032Sjhb default: 262158032Sjhb snprintf(state, sizeof(state), "???"); 263158032Sjhb } 264158032Sjhb db_printf(" %-6.6s ", state); 265158032Sjhb } 266158032Sjhb wprefix = ' '; 267158032Sjhb if (TD_ON_LOCK(td)) { 268158032Sjhb wprefix = '*'; 269158032Sjhb wmesg = td->td_lockname; 270158032Sjhb wchan = td->td_blocked; 271158032Sjhb } else if (TD_ON_SLEEPQ(td)) { 272158032Sjhb wmesg = td->td_wmesg; 273158032Sjhb wchan = td->td_wchan; 274158032Sjhb } else if (TD_IS_RUNNING(td)) { 275158032Sjhb snprintf(state, sizeof(state), "CPU %d", td->td_oncpu); 276158032Sjhb wmesg = state; 277158032Sjhb wchan = NULL; 278158032Sjhb } else { 279158032Sjhb wmesg = ""; 280158032Sjhb wchan = NULL; 281158032Sjhb } 282158032Sjhb db_printf("%c%-8.8s ", wprefix, wmesg); 283158032Sjhb if (wchan == NULL) 284158032Sjhb#ifdef PTR64 285158032Sjhb db_printf("%18s ", ""); 286158032Sjhb#else 287158032Sjhb db_printf("%10s ", ""); 288158032Sjhb#endif 289158032Sjhb else 290158032Sjhb db_printf("%p ", wchan); 291158032Sjhb if (p->p_flag & P_SYSTEM) 292158032Sjhb db_printf("["); 293158032Sjhb if (td->td_name[0] != '\0') 294158032Sjhb db_printf("%s", td->td_name); 295158032Sjhb else 296158032Sjhb db_printf("%s", td->td_proc->p_comm); 297158032Sjhb if (p->p_flag & P_SYSTEM) 298158032Sjhb db_printf("]"); 299158032Sjhb db_printf("\n"); 300158032Sjhb} 301118228Sjhb 302158032SjhbDB_SHOW_COMMAND(thread, db_show_thread) 303158032Sjhb{ 304158032Sjhb struct thread *td; 305158032Sjhb boolean_t comma; 306158032Sjhb 307158032Sjhb /* Determine which thread to examine. */ 308158032Sjhb if (have_addr) 309158032Sjhb td = db_lookup_thread(addr, FALSE); 310158032Sjhb else 311158032Sjhb td = kdb_thread; 312158032Sjhb 313158032Sjhb db_printf("Thread %d at %p:\n", td->td_tid, td); 314158032Sjhb db_printf(" proc (pid %d): %p ", td->td_proc->p_pid, td->td_proc); 315158032Sjhb db_printf(" ksegrp: %p\n", td->td_ksegrp); 316158032Sjhb if (td->td_name[0] != '\0') 317158032Sjhb db_printf(" name: %s\n", td->td_name); 318158032Sjhb db_printf(" flags: %#x ", td->td_flags); 319158032Sjhb db_printf(" pflags: %#x\n", td->td_pflags); 320158032Sjhb db_printf(" state: "); 321108338Sjulian switch (td->td_state) { 322158032Sjhb case TDS_INACTIVE: 323158032Sjhb db_printf("INACTIVE\n"); 324158032Sjhb break; 325158032Sjhb case TDS_CAN_RUN: 326158032Sjhb db_printf("CAN RUN\n"); 327158032Sjhb break; 328158032Sjhb case TDS_RUNQ: 329158032Sjhb db_printf("RUNQ\n"); 330158032Sjhb break; 331158032Sjhb case TDS_RUNNING: 332158032Sjhb db_printf("RUNNING (CPU %d)\n", td->td_oncpu); 333158032Sjhb break; 334108338Sjulian case TDS_INHIBITED: 335158032Sjhb db_printf("INHIBITED: {"); 336158032Sjhb comma = FALSE; 337108338Sjulian if (TD_IS_SLEEPING(td)) { 338158032Sjhb db_printf("SLEEPING"); 339158032Sjhb comma = TRUE; 340108338Sjulian } 341108338Sjulian if (TD_IS_SUSPENDED(td)) { 342158032Sjhb if (comma) 343158032Sjhb db_printf(", "); 344158032Sjhb db_printf("SUSPENDED"); 345158032Sjhb comma = TRUE; 346108338Sjulian } 347158032Sjhb if (TD_IS_SWAPPED(td)) { 348158032Sjhb if (comma) 349158032Sjhb db_printf(", "); 350158032Sjhb db_printf("SWAPPED"); 351158032Sjhb comma = TRUE; 352158032Sjhb } 353158032Sjhb if (TD_ON_LOCK(td)) { 354158032Sjhb if (comma) 355158032Sjhb db_printf(", "); 356158032Sjhb db_printf("LOCK"); 357158032Sjhb comma = TRUE; 358158032Sjhb } 359108338Sjulian if (TD_AWAITING_INTR(td)) { 360158032Sjhb if (comma) 361158032Sjhb db_printf(", "); 362158032Sjhb db_printf("IWAIT"); 363108338Sjulian } 364158032Sjhb db_printf("}\n"); 365108338Sjulian break; 366158032Sjhb default: 367158032Sjhb db_printf("??? (%#x)\n", td->td_state); 368108338Sjulian break; 369158032Sjhb } 370158032Sjhb if (TD_ON_LOCK(td)) 371158032Sjhb db_printf(" lock: %s turnstile: %p\n", td->td_lockname, 372158032Sjhb td->td_blocked); 373158032Sjhb if (TD_ON_SLEEPQ(td)) 374158032Sjhb db_printf(" wmesg: %s wchan: %p\n", td->td_wmesg, 375158032Sjhb td->td_wchan); 376158032Sjhb db_printf(" priority: %d\n", td->td_priority); 377158032Sjhb} 378158032Sjhb 379158032SjhbDB_SHOW_COMMAND(proc, db_show_proc) 380158032Sjhb{ 381158032Sjhb struct thread *td; 382158032Sjhb struct proc *p; 383158032Sjhb int i, quit; 384158032Sjhb 385158032Sjhb /* Determine which process to examine. */ 386158032Sjhb if (have_addr) 387158032Sjhb p = db_lookup_proc(addr); 388158032Sjhb else 389158032Sjhb p = kdb_thread->td_proc; 390158032Sjhb 391158032Sjhb quit = 0; 392158032Sjhb db_setup_paging(db_simple_pager, &quit, db_lines_per_page); 393158032Sjhb db_printf("Process %d (%s) at %p:\n", p->p_pid, p->p_comm, p); 394158032Sjhb db_printf(" state: "); 395158032Sjhb switch (p->p_state) { 396158032Sjhb case PRS_NEW: 397158032Sjhb db_printf("NEW\n"); 398108338Sjulian break; 399158032Sjhb case PRS_NORMAL: 400158032Sjhb db_printf("NORMAL\n"); 401108338Sjulian break; 402158032Sjhb case PRS_ZOMBIE: 403158032Sjhb db_printf("ZOMBIE\n"); 404115904Sjhb break; 405108338Sjulian default: 406158032Sjhb db_printf("??? (%#x)\n", p->p_state); 407108338Sjulian } 408158032Sjhb if (p->p_ucred != NULL) { 409158032Sjhb db_printf(" uid: %d gids: ", p->p_ucred->cr_uid); 410158032Sjhb for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 411158032Sjhb db_printf("%d", p->p_ucred->cr_groups[i]); 412158032Sjhb if (i < (p->p_ucred->cr_ngroups - 1)) 413158032Sjhb db_printf(", "); 414158032Sjhb } 415108338Sjulian db_printf("\n"); 416158032Sjhb } 417158032Sjhb if (p->p_pptr != NULL) 418158032Sjhb db_printf(" parent: pid %d at %p\n", p->p_pptr->p_pid, 419158032Sjhb p->p_pptr); 420158032Sjhb if (p->p_leader != NULL && p->p_leader != p) 421158032Sjhb db_printf(" leader: pid %d at %p\n", p->p_leader->p_pid, 422158032Sjhb p->p_leader); 423158032Sjhb if (p->p_sysent != NULL) 424158032Sjhb db_printf(" ABI: %s\n", p->p_sysent->sv_name); 425158032Sjhb if (p->p_args != NULL) 426158032Sjhb db_printf(" arguments: %.*s\n", (int)p->p_args->ar_length, 427158032Sjhb p->p_args->ar_args); 428158032Sjhb db_printf(" threads: %d\n", p->p_numthreads); 429158032Sjhb FOREACH_THREAD_IN_PROC(p, td) { 430158032Sjhb dumpthread(p, td, 1); 431158032Sjhb if (quit) 432158032Sjhb break; 433158032Sjhb } 434108338Sjulian} 435