db_ps.c revision 164936
1152521Spjd/*- 2127412Sgad * Copyright (c) 1993 The Regents of the University of California. 3127412Sgad * All rights reserved. 4127412Sgad * 5152518Spjd * Redistribution and use in source and binary forms, with or without 6127412Sgad * modification, are permitted provided that the following conditions 7127412Sgad * are met: 8127412Sgad * 1. Redistributions of source code must retain the above copyright 9127412Sgad * notice, this list of conditions and the following disclaimer. 10127412Sgad * 2. Redistributions in binary form must reproduce the above copyright 11127412Sgad * notice, this list of conditions and the following disclaimer in the 12127412Sgad * documentation and/or other materials provided with the distribution. 13127412Sgad * 4. Neither the name of the University nor the names of its contributors 14127412Sgad * may be used to endorse or promote products derived from this software 15127412Sgad * without specific prior written permission. 16127412Sgad * 17127412Sgad * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18127412Sgad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19127412Sgad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20127412Sgad * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21127412Sgad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22127412Sgad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23127412Sgad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24127412Sgad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25127412Sgad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26127412Sgad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27127412Sgad * SUCH DAMAGE. 28127412Sgad */ 29127412Sgad 30127412Sgad#include <sys/cdefs.h> 31127412Sgad__FBSDID("$FreeBSD: head/sys/ddb/db_ps.c 164936 2006-12-06 06:34:57Z julian $"); 32127412Sgad 33127412Sgad#include <sys/param.h> 34127412Sgad#include <sys/cons.h> 35127412Sgad#include <sys/jail.h> 36127412Sgad#include <sys/kdb.h> 37127412Sgad#include <sys/linker_set.h> 38127412Sgad#include <sys/proc.h> 39127412Sgad#include <sys/sysent.h> 40127412Sgad#include <sys/systm.h> 41127412Sgad#include <vm/vm.h> 42127412Sgad#include <vm/vm_param.h> 43127412Sgad#include <vm/pmap.h> 44127412Sgad 45127412Sgad#include <ddb/ddb.h> 46127412Sgad 47127412Sgadstatic void dumpthread(volatile struct proc *p, volatile struct thread *td, 48127412Sgad int all); 49143878Spjd 50127425Sgad/* 51127412Sgad * Layout: 52203802Spjd * - column counts 53127412Sgad * - header 54127412Sgad * - single-threaded process 55127412Sgad * - multi-threaded process 56127425Sgad * - thread in a MT process 57127412Sgad * 58127412Sgad * 1 2 3 4 5 6 7 59127412Sgad * 1234567890123456789012345678901234567890123456789012345678901234567890 60127412Sgad * pid ppid pgrp uid state wmesg wchan cmd 61127412Sgad * <pid> <ppi> <pgi> <uid> <stat> < wmesg > < wchan > <name> 62127425Sgad * <pid> <ppi> <pgi> <uid> <stat> (threaded) <command> 63127412Sgad * <tid > <stat> < wmesg > < wchan > <name> 64127412Sgad * 65127412Sgad * For machines with 64-bit pointers, we expand the wchan field 8 more 66127412Sgad * characters. 67127412Sgad */ 68132198Stjrvoid 69127412Sgaddb_ps(db_expr_t addr, boolean_t hasaddr, db_expr_t count, char *modif) 70127412Sgad{ 71127412Sgad volatile struct proc *p, *pp; 72127412Sgad volatile struct thread *td; 73127412Sgad struct ucred *cred; 74127412Sgad struct pgrp *pgrp; 75143874Spjd char state[9]; 76143874Spjd int np, rflag, sflag, dflag, lflag, wflag; 77143874Spjd 78143877Spjd np = nprocs; 79143877Spjd 80143877Spjd if (!LIST_EMPTY(&allproc)) 81127425Sgad p = LIST_FIRST(&allproc); 82127412Sgad else 83127412Sgad p = &proc0; 84127412Sgad 85127412Sgad#ifdef __LP64__ 86127412Sgad db_printf(" pid ppid pgrp uid state wmesg wchan cmd\n"); 87127412Sgad#else 88164558Syar db_printf(" pid ppid pgrp uid state wmesg wchan cmd\n"); 89127412Sgad#endif 90127412Sgad while (--np >= 0 && !db_pager_quit) { 91127412Sgad if (p == NULL) { 92127412Sgad db_printf("oops, ran out of processes early!\n"); 93127412Sgad break; 94127412Sgad } 95127412Sgad pp = p->p_pptr; 96127412Sgad if (pp == NULL) 97127412Sgad pp = p; 98127412Sgad 99152521Spjd cred = p->p_ucred; 100152521Spjd pgrp = p->p_pgrp; 101152521Spjd db_printf("%5d %5d %5d %5d ", p->p_pid, pp->p_pid, 102152521Spjd pgrp != NULL ? pgrp->pg_id : 0, 103152521Spjd cred != NULL ? cred->cr_ruid : 0); 104152521Spjd 105152521Spjd /* Determine our primary process state. */ 106152521Spjd switch (p->p_state) { 107152521Spjd case PRS_NORMAL: 108152521Spjd if (P_SHOULDSTOP(p)) 109152521Spjd state[0] = 'T'; 110152521Spjd else { 111152521Spjd /* 112152521Spjd * One of D, L, R, S, W. For a 113152521Spjd * multithreaded process we will use 114203802Spjd * the state of the thread with the 115152521Spjd * highest precedence. The 116152521Spjd * precendence order from high to low 117127412Sgad * is R, L, D, S, W. If no thread is 118201145Santoine * in a sane state we use '?' for our 119201145Santoine * primary state. 120201145Santoine */ 121201145Santoine rflag = sflag = dflag = lflag = wflag = 0; 122201145Santoine FOREACH_THREAD_IN_PROC(p, td) { 123201145Santoine if (td->td_state == TDS_RUNNING || 124201145Santoine td->td_state == TDS_RUNQ || 125201145Santoine td->td_state == TDS_CAN_RUN) 126127412Sgad rflag++; 127152521Spjd if (TD_ON_LOCK(td)) 128152521Spjd lflag++; 129152521Spjd if (TD_IS_SLEEPING(td)) { 130152521Spjd if (!td->td_flags & TDF_SINTR) 131152521Spjd dflag++; 132127412Sgad else 133127412Sgad sflag++; 134127412Sgad } 135127412Sgad if (TD_AWAITING_INTR(td)) 136149471Spjd wflag++; 137127462Sgad } 138192242Sbrian if (rflag) 139149471Spjd state[0] = 'R'; 140127430Sgad else if (lflag) 141152521Spjd state[0] = 'L'; 142127425Sgad else if (dflag) 143127412Sgad state[0] = 'D'; 144127430Sgad else if (sflag) 145127412Sgad state[0] = 'S'; 146127412Sgad else if (wflag) 147192242Sbrian state[0] = 'W'; 148127412Sgad else 149132198Stjr state[0] = '?'; 150132198Stjr } 151127412Sgad break; 152127412Sgad case PRS_NEW: 153127412Sgad state[0] = 'N'; 154127412Sgad break; 155127412Sgad case PRS_ZOMBIE: 156127412Sgad state[0] = 'Z'; 157127412Sgad break; 158127412Sgad default: 159127412Sgad state[0] = 'U'; 160127412Sgad break; 161127412Sgad } 162127412Sgad state[1] = '\0'; 163127412Sgad 164127412Sgad /* Additional process state flags. */ 165127412Sgad if (!p->p_sflag & PS_INMEM) 166127412Sgad strlcat(state, "W", sizeof(state)); 167127412Sgad if (p->p_flag & P_TRACED) 168127412Sgad strlcat(state, "X", sizeof(state)); 169127412Sgad if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE) 170127412Sgad strlcat(state, "E", sizeof(state)); 171127412Sgad if (p->p_flag & P_PPWAIT) 172127412Sgad strlcat(state, "V", sizeof(state)); 173127412Sgad if (p->p_flag & P_SYSTEM || p->p_lock > 0) 174127412Sgad strlcat(state, "L", sizeof(state)); 175127412Sgad if (p->p_session != NULL && SESS_LEADER(p)) 176127412Sgad strlcat(state, "s", sizeof(state)); 177127412Sgad /* Cheated here and didn't compare pgid's. */ 178127412Sgad if (p->p_flag & P_CONTROLT) 179127412Sgad strlcat(state, "+", sizeof(state)); 180192242Sbrian if (cred != NULL && jailed(cred)) 181127412Sgad strlcat(state, "J", sizeof(state)); 182127433Sgad db_printf(" %-6.6s ", state); 183149471Spjd if (p->p_flag & P_HADTHREADS) 184149471Spjd#ifdef __LP64__ 185203802Spjd db_printf(" (threaded) %s\n", 186203688Sbrucec p->p_comm); 187203688Sbrucec#else 188127412Sgad db_printf(" (threaded) %s\n", p->p_comm); 189203802Spjd#endif 190127412Sgad FOREACH_THREAD_IN_PROC(p, td) { 191127433Sgad dumpthread(p, td, p->p_flag & P_HADTHREADS); 192127433Sgad if (db_pager_quit) 193127433Sgad break; 194143874Spjd } 195149471Spjd 196143874Spjd p = LIST_NEXT(p, p_list); 197143874Spjd if (p == NULL && np > 0) 198127412Sgad p = LIST_FIRST(&zombproc); 199127412Sgad } 200127412Sgad} 201127412Sgad 202152518Spjdstatic void 203152518Spjddumpthread(volatile struct proc *p, volatile struct thread *td, int all) 204152518Spjd{ 205152518Spjd char state[9], wprefix; 206152518Spjd const char *wmesg; 207149471Spjd void *wchan; 208149471Spjd 209149471Spjd if (all) { 210127427Sgad db_printf("%6d ", td->td_tid); 211127427Sgad switch (td->td_state) { 212127427Sgad case TDS_RUNNING: 213127427Sgad snprintf(state, sizeof(state), "Run"); 214127427Sgad break; 215127427Sgad case TDS_RUNQ: 216127412Sgad snprintf(state, sizeof(state), "RunQ"); 217127412Sgad break; 218127412Sgad case TDS_CAN_RUN: 219127412Sgad snprintf(state, sizeof(state), "CanRun"); 220143877Spjd break; 221143877Spjd case TDS_INACTIVE: 222143877Spjd snprintf(state, sizeof(state), "Inactv"); 223143877Spjd break; 224143877Spjd case TDS_INHIBITED: 225127412Sgad state[0] = '\0'; 226127412Sgad if (TD_ON_LOCK(td)) 227127412Sgad strlcat(state, "L", sizeof(state)); 228127412Sgad if (TD_IS_SLEEPING(td)) { 229192242Sbrian if (td->td_flags & TDF_SINTR) 230192242Sbrian strlcat(state, "S", sizeof(state)); 231192242Sbrian else 232127412Sgad strlcat(state, "D", sizeof(state)); 233127412Sgad } 234127412Sgad if (TD_IS_SWAPPED(td)) 235127412Sgad strlcat(state, "W", sizeof(state)); 236127412Sgad if (TD_AWAITING_INTR(td)) 237127412Sgad strlcat(state, "I", sizeof(state)); 238127412Sgad if (TD_IS_SUSPENDED(td)) 239127412Sgad strlcat(state, "s", sizeof(state)); 240127412Sgad if (state[0] != '\0') 241127412Sgad break; 242127412Sgad default: 243127412Sgad snprintf(state, sizeof(state), "???"); 244143875Spjd } 245143875Spjd db_printf(" %-6.6s ", state); 246143875Spjd } 247143873Spjd wprefix = ' '; 248164558Syar if (TD_ON_LOCK(td)) { 249143873Spjd wprefix = '*'; 250143873Spjd wmesg = td->td_lockname; 251127412Sgad wchan = td->td_blocked; 252127412Sgad } else if (TD_ON_SLEEPQ(td)) { 253127412Sgad wmesg = td->td_wmesg; 254127412Sgad wchan = td->td_wchan; 255127412Sgad } else if (TD_IS_RUNNING(td)) { 256127412Sgad snprintf(state, sizeof(state), "CPU %d", td->td_oncpu); 257127412Sgad wmesg = state; 258127412Sgad wchan = NULL; 259127412Sgad } else { 260143878Spjd wmesg = ""; 261143878Spjd wchan = NULL; 262143878Spjd } 263143878Spjd db_printf("%c%-8.8s ", wprefix, wmesg); 264203802Spjd if (wchan == NULL) 265203802Spjd#ifdef __LP64__ 266203802Spjd db_printf("%18s ", ""); 267203802Spjd#else 268203802Spjd db_printf("%10s ", ""); 269127412Sgad#endif 270127412Sgad else 271127412Sgad db_printf("%p ", wchan); 272127412Sgad if (p->p_flag & P_SYSTEM) 273127412Sgad db_printf("["); 274127412Sgad if (td->td_name[0] != '\0') 275127412Sgad db_printf("%s", td->td_name); 276127412Sgad else 277127412Sgad db_printf("%s", td->td_proc->p_comm); 278127412Sgad if (p->p_flag & P_SYSTEM) 279127412Sgad db_printf("]"); 280127412Sgad db_printf("\n"); 281127412Sgad} 282127412Sgad 283127412SgadDB_SHOW_COMMAND(thread, db_show_thread) 284127412Sgad{ 285127412Sgad struct thread *td; 286127412Sgad boolean_t comma; 287127412Sgad 288127412Sgad /* Determine which thread to examine. */ 289127412Sgad if (have_addr) 290127412Sgad td = db_lookup_thread(addr, FALSE); 291127412Sgad else 292127412Sgad td = kdb_thread; 293127412Sgad 294127412Sgad db_printf("Thread %d at %p:\n", td->td_tid, td); 295127412Sgad db_printf(" proc (pid %d): %p\n", td->td_proc->p_pid, td->td_proc); 296127412Sgad if (td->td_name[0] != '\0') 297127412Sgad db_printf(" name: %s\n", td->td_name); 298143878Spjd db_printf(" flags: %#x ", td->td_flags); 299152521Spjd db_printf(" pflags: %#x\n", td->td_pflags); 300149471Spjd db_printf(" state: "); 301149471Spjd switch (td->td_state) { 302149471Spjd case TDS_INACTIVE: 303152521Spjd db_printf("INACTIVE\n"); 304152521Spjd break; 305152521Spjd case TDS_CAN_RUN: 306152521Spjd db_printf("CAN RUN\n"); 307149471Spjd break; 308149471Spjd case TDS_RUNQ: 309127412Sgad db_printf("RUNQ\n"); 310127412Sgad break; 311127412Sgad case TDS_RUNNING: 312127412Sgad db_printf("RUNNING (CPU %d)\n", td->td_oncpu); 313127412Sgad break; 314127412Sgad case TDS_INHIBITED: 315127462Sgad db_printf("INHIBITED: {"); 316127412Sgad comma = FALSE; 317152521Spjd if (TD_IS_SLEEPING(td)) { 318127412Sgad db_printf("SLEEPING"); 319127622Sgad comma = TRUE; 320127622Sgad } 321127622Sgad if (TD_IS_SUSPENDED(td)) { 322127622Sgad if (comma) 323127622Sgad db_printf(", "); 324152521Spjd db_printf("SUSPENDED"); 325152521Spjd comma = TRUE; 326152521Spjd } 327152521Spjd if (TD_IS_SWAPPED(td)) { 328127412Sgad if (comma) 329127412Sgad db_printf(", "); 330127412Sgad db_printf("SWAPPED"); 331127412Sgad comma = TRUE; 332127412Sgad } 333152521Spjd if (TD_ON_LOCK(td)) { 334152521Spjd if (comma) 335152521Spjd db_printf(", "); 336152521Spjd db_printf("LOCK"); 337127412Sgad comma = TRUE; 338127412Sgad } 339127412Sgad if (TD_AWAITING_INTR(td)) { 340127412Sgad if (comma) 341127412Sgad db_printf(", "); 342127412Sgad db_printf("IWAIT"); 343143875Spjd } 344127412Sgad db_printf("}\n"); 345152521Spjd break; 346152521Spjd default: 347152521Spjd db_printf("??? (%#x)\n", td->td_state); 348127412Sgad break; 349127412Sgad } 350127412Sgad if (TD_ON_LOCK(td)) 351143877Spjd db_printf(" lock: %s turnstile: %p\n", td->td_lockname, 352127433Sgad td->td_blocked); 353127434Sgad if (TD_ON_SLEEPQ(td)) 354127433Sgad db_printf(" wmesg: %s wchan: %p\n", td->td_wmesg, 355127412Sgad td->td_wchan); 356127433Sgad db_printf(" priority: %d\n", td->td_priority); 357127412Sgad} 358143877Spjd 359143877SpjdDB_SHOW_COMMAND(proc, db_show_proc) 360127430Sgad{ 361127430Sgad struct thread *td; 362127430Sgad struct proc *p; 363127430Sgad int i; 364127412Sgad 365127412Sgad /* Determine which process to examine. */ 366127412Sgad if (have_addr) 367127412Sgad p = db_lookup_proc(addr); 368127412Sgad else 369127412Sgad p = kdb_thread->td_proc; 370127425Sgad 371127412Sgad db_printf("Process %d (%s) at %p:\n", p->p_pid, p->p_comm, p); 372127412Sgad db_printf(" state: "); 373127412Sgad switch (p->p_state) { 374127412Sgad case PRS_NEW: 375127412Sgad db_printf("NEW\n"); 376127431Sgad break; 377127431Sgad case PRS_NORMAL: 378127412Sgad db_printf("NORMAL\n"); 379127412Sgad break; 380127412Sgad case PRS_ZOMBIE: 381127412Sgad db_printf("ZOMBIE\n"); 382127412Sgad break; 383152521Spjd default: 384152521Spjd db_printf("??? (%#x)\n", p->p_state); 385152521Spjd } 386127412Sgad if (p->p_ucred != NULL) { 387127433Sgad db_printf(" uid: %d gids: ", p->p_ucred->cr_uid); 388127433Sgad for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 389127433Sgad db_printf("%d", p->p_ucred->cr_groups[i]); 390127433Sgad if (i < (p->p_ucred->cr_ngroups - 1)) 391127434Sgad db_printf(", "); 392127433Sgad } 393127433Sgad db_printf("\n"); 394127412Sgad } 395127412Sgad if (p->p_pptr != NULL) 396127412Sgad db_printf(" parent: pid %d at %p\n", p->p_pptr->p_pid, 397127412Sgad p->p_pptr); 398127412Sgad if (p->p_leader != NULL && p->p_leader != p) 399127412Sgad db_printf(" leader: pid %d at %p\n", p->p_leader->p_pid, 400143877Spjd p->p_leader); 401127412Sgad if (p->p_sysent != NULL) 402127412Sgad db_printf(" ABI: %s\n", p->p_sysent->sv_name); 403143874Spjd if (p->p_args != NULL) 404143874Spjd db_printf(" arguments: %.*s\n", (int)p->p_args->ar_length, 405143874Spjd p->p_args->ar_args); 406143874Spjd db_printf(" threads: %d\n", p->p_numthreads); 407143874Spjd FOREACH_THREAD_IN_PROC(p, td) { 408127412Sgad dumpthread(p, td, 1); 409127425Sgad if (db_pager_quit) 410127412Sgad break; 411127412Sgad } 412127412Sgad} 413127412Sgad