db_ps.c revision 179861
162642Sn_hibma/*- 262642Sn_hibma * Copyright (c) 1993 The Regents of the University of California. 362642Sn_hibma * All rights reserved. 462642Sn_hibma * 562642Sn_hibma * Redistribution and use in source and binary forms, with or without 662642Sn_hibma * modification, are permitted provided that the following conditions 762642Sn_hibma * are met: 862642Sn_hibma * 1. Redistributions of source code must retain the above copyright 962642Sn_hibma * notice, this list of conditions and the following disclaimer. 1062642Sn_hibma * 2. Redistributions in binary form must reproduce the above copyright 1162642Sn_hibma * notice, this list of conditions and the following disclaimer in the 1262642Sn_hibma * documentation and/or other materials provided with the distribution. 1362642Sn_hibma * 4. Neither the name of the University nor the names of its contributors 1462642Sn_hibma * may be used to endorse or promote products derived from this software 1562642Sn_hibma * without specific prior written permission. 1662642Sn_hibma * 1762642Sn_hibma * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1862642Sn_hibma * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1962642Sn_hibma * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2062642Sn_hibma * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2162642Sn_hibma * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2262642Sn_hibma * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2362642Sn_hibma * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2462642Sn_hibma * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2562642Sn_hibma * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2662642Sn_hibma * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2762642Sn_hibma * SUCH DAMAGE. 2862642Sn_hibma */ 2962642Sn_hibma 3062642Sn_hibma#include <sys/cdefs.h> 3162642Sn_hibma__FBSDID("$FreeBSD: head/sys/ddb/db_ps.c 179861 2008-06-18 20:42:01Z attilio $"); 3262642Sn_hibma 3362642Sn_hibma#include <sys/param.h> 3462642Sn_hibma#include <sys/cons.h> 3562642Sn_hibma#include <sys/jail.h> 3662642Sn_hibma#include <sys/kdb.h> 3762642Sn_hibma#include <sys/linker_set.h> 3862642Sn_hibma#include <sys/proc.h> 3962642Sn_hibma#include <sys/sysent.h> 4062642Sn_hibma#include <sys/systm.h> 4162642Sn_hibma#include <vm/vm.h> 42113273Smdodd#include <vm/vm_param.h> 43188945Sthompsa#include <vm/pmap.h> 4462642Sn_hibma 45225839Smav#include <ddb/ddb.h> 46225839Smav 47225839Smavstatic void dumpthread(volatile struct proc *p, volatile struct thread *td, 48225839Smav int all); 49225839Smav/* 50225839Smav * At least one non-optional show-command must be implemented using 51225839Smav * DB_SHOW_ALL_COMMAND() so that db_show_all_cmd_set gets created. 52225839Smav * Here is one. 5362642Sn_hibma */ 5462642Sn_hibmaDB_SHOW_ALL_COMMAND(procs, db_procs_cmd) 55164531Sgrog{ 56225839Smav db_ps(addr, have_addr, count, modif); 57225839Smav} 5862642Sn_hibma 59225839Smav/* 60225839Smav * Layout: 61225839Smav * - column counts 62225839Smav * - header 63225839Smav * - single-threaded process 64225839Smav * - multi-threaded process 6562642Sn_hibma * - thread in a MT process 66225839Smav * 67225839Smav * 1 2 3 4 5 6 7 6862642Sn_hibma * 1234567890123456789012345678901234567890123456789012345678901234567890 69225839Smav * pid ppid pgrp uid state wmesg wchan cmd 70225839Smav * <pid> <ppi> <pgi> <uid> <stat> < wmesg > < wchan > <name> 71225839Smav * <pid> <ppi> <pgi> <uid> <stat> (threaded) <command> 72225839Smav * <tid > <stat> < wmesg > < wchan > <name> 73225839Smav * 74225839Smav * For machines with 64-bit pointers, we expand the wchan field 8 more 7562642Sn_hibma * characters. 76225839Smav */ 77225839Smavvoid 78225839Smavdb_ps(db_expr_t addr, boolean_t hasaddr, db_expr_t count, char *modif) 79225839Smav{ 80225839Smav volatile struct proc *p, *pp; 81225839Smav volatile struct thread *td; 82225839Smav struct ucred *cred; 83225839Smav struct pgrp *pgrp; 84225839Smav char state[9]; 85225839Smav int np, rflag, sflag, dflag, lflag, wflag; 86225839Smav 87225839Smav np = nprocs; 88225839Smav 89225839Smav if (!LIST_EMPTY(&allproc)) 90225839Smav p = LIST_FIRST(&allproc); 91225839Smav else 92225839Smav p = &proc0; 93225839Smav 94225839Smav#ifdef __LP64__ 95225839Smav db_printf(" pid ppid pgrp uid state wmesg wchan cmd\n"); 96225839Smav#else 97225839Smav db_printf(" pid ppid pgrp uid state wmesg wchan cmd\n"); 98225839Smav#endif 99225839Smav while (--np >= 0 && !db_pager_quit) { 100225839Smav if (p == NULL) { 101225839Smav db_printf("oops, ran out of processes early!\n"); 102225839Smav break; 103225839Smav } 104225839Smav pp = p->p_pptr; 105225839Smav if (pp == NULL) 106225839Smav pp = p; 107225839Smav 108225839Smav cred = p->p_ucred; 109225839Smav pgrp = p->p_pgrp; 110225839Smav db_printf("%5d %5d %5d %5d ", p->p_pid, pp->p_pid, 111225839Smav pgrp != NULL ? pgrp->pg_id : 0, 112225839Smav cred != NULL ? cred->cr_ruid : 0); 113225839Smav 114225839Smav /* Determine our primary process state. */ 115225839Smav switch (p->p_state) { 116225839Smav case PRS_NORMAL: 117225839Smav if (P_SHOULDSTOP(p)) 118225839Smav state[0] = 'T'; 119225839Smav else { 120225839Smav /* 121225839Smav * One of D, L, R, S, W. For a 122225839Smav * multithreaded process we will use 123225839Smav * the state of the thread with the 124225839Smav * highest precedence. The 125225839Smav * precendence order from high to low 126225839Smav * is R, L, D, S, W. If no thread is 127225839Smav * in a sane state we use '?' for our 128225839Smav * primary state. 129225839Smav */ 130225839Smav rflag = sflag = dflag = lflag = wflag = 0; 131225839Smav FOREACH_THREAD_IN_PROC(p, td) { 13262642Sn_hibma if (td->td_state == TDS_RUNNING || 133225839Smav td->td_state == TDS_RUNQ || 134225839Smav td->td_state == TDS_CAN_RUN) 135225839Smav rflag++; 136225839Smav if (TD_ON_LOCK(td)) 137225839Smav lflag++; 138225839Smav if (TD_IS_SLEEPING(td)) { 139225839Smav if (!td->td_flags & TDF_SINTR) 140225839Smav dflag++; 141225839Smav else 142225839Smav sflag++; 143225839Smav } 144225839Smav if (TD_AWAITING_INTR(td)) 145225839Smav wflag++; 146225839Smav } 147225839Smav if (rflag) 148225839Smav state[0] = 'R'; 149225839Smav else if (lflag) 150225839Smav state[0] = 'L'; 151225839Smav else if (dflag) 152225839Smav state[0] = 'D'; 153225839Smav else if (sflag) 154225839Smav state[0] = 'S'; 155225839Smav else if (wflag) 156225839Smav state[0] = 'W'; 157225839Smav else 158225839Smav state[0] = '?'; 159225839Smav } 160225839Smav break; 161225839Smav case PRS_NEW: 162225839Smav state[0] = 'N'; 163225839Smav break; 164225839Smav case PRS_ZOMBIE: 165225839Smav state[0] = 'Z'; 166225839Smav break; 167225839Smav default: 168225839Smav state[0] = 'U'; 169225839Smav break; 170225839Smav } 171225839Smav state[1] = '\0'; 172225839Smav 173225839Smav /* Additional process state flags. */ 174225839Smav if (!p->p_flag & P_INMEM) 175225839Smav strlcat(state, "W", sizeof(state)); 176225839Smav if (p->p_flag & P_TRACED) 17762642Sn_hibma strlcat(state, "X", sizeof(state)); 17862642Sn_hibma if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE) 179225839Smav strlcat(state, "E", sizeof(state)); 18062642Sn_hibma if (p->p_flag & P_PPWAIT) 18162642Sn_hibma strlcat(state, "V", sizeof(state)); 18262642Sn_hibma if (p->p_flag & P_SYSTEM || p->p_lock > 0) 183164531Sgrog strlcat(state, "L", sizeof(state)); 184164531Sgrog if (p->p_session != NULL && SESS_LEADER(p)) 185164544Sgrog strlcat(state, "s", sizeof(state)); 186194789Sdelphij /* Cheated here and didn't compare pgid's. */ 187164531Sgrog if (p->p_flag & P_CONTROLT) 188164531Sgrog strlcat(state, "+", sizeof(state)); 189164544Sgrog if (cred != NULL && jailed(cred)) 190194789Sdelphij strlcat(state, "J", sizeof(state)); 191225839Smav db_printf(" %-6.6s ", state); 192225839Smav if (p->p_flag & P_HADTHREADS) 193225839Smav#ifdef __LP64__ 194225839Smav db_printf(" (threaded) %s\n", 19562642Sn_hibma p->p_comm); 19662642Sn_hibma#else 19762642Sn_hibma db_printf(" (threaded) %s\n", p->p_comm); 198225839Smav#endif 19987699Smarkm FOREACH_THREAD_IN_PROC(p, td) { 20062642Sn_hibma dumpthread(p, td, p->p_flag & P_HADTHREADS); 20162642Sn_hibma if (db_pager_quit) 20262642Sn_hibma break; 203224511Smav } 204224511Smav 205164531Sgrog p = LIST_NEXT(p, p_list); 20662642Sn_hibma if (p == NULL && np > 0) 207224511Smav p = LIST_FIRST(&zombproc); 208224511Smav } 20962642Sn_hibma} 21062642Sn_hibma 21162642Sn_hibmastatic void 21262642Sn_hibmadumpthread(volatile struct proc *p, volatile struct thread *td, int all) 21362642Sn_hibma{ 21462642Sn_hibma char state[9], wprefix; 21562642Sn_hibma const char *wmesg; 21662642Sn_hibma void *wchan; 21762642Sn_hibma 21862642Sn_hibma if (all) { 219224511Smav db_printf("%6d ", td->td_tid); 220224511Smav switch (td->td_state) { 221224511Smav case TDS_RUNNING: 222224511Smav snprintf(state, sizeof(state), "Run"); 223224511Smav break; 224224511Smav case TDS_RUNQ: 225224511Smav snprintf(state, sizeof(state), "RunQ"); 226224511Smav break; 227224511Smav case TDS_CAN_RUN: 228224511Smav snprintf(state, sizeof(state), "CanRun"); 229224511Smav break; 230224511Smav case TDS_INACTIVE: 231224511Smav snprintf(state, sizeof(state), "Inactv"); 232224511Smav break; 233224511Smav case TDS_INHIBITED: 234224511Smav state[0] = '\0'; 235224511Smav if (TD_ON_LOCK(td)) 236224511Smav strlcat(state, "L", sizeof(state)); 237225839Smav if (TD_IS_SLEEPING(td)) { 23862642Sn_hibma if (td->td_flags & TDF_SINTR) 23962642Sn_hibma strlcat(state, "S", sizeof(state)); 24062642Sn_hibma else 24162642Sn_hibma strlcat(state, "D", sizeof(state)); 24267256Sn_hibma } 24362642Sn_hibma if (TD_IS_SWAPPED(td)) 244224511Smav strlcat(state, "W", sizeof(state)); 24562642Sn_hibma if (TD_AWAITING_INTR(td)) 24662642Sn_hibma strlcat(state, "I", sizeof(state)); 247224511Smav if (TD_IS_SUSPENDED(td)) 248224511Smav strlcat(state, "s", sizeof(state)); 249164531Sgrog if (state[0] != '\0') 25062642Sn_hibma break; 25162642Sn_hibma default: 25262642Sn_hibma snprintf(state, sizeof(state), "???"); 25362642Sn_hibma } 25462642Sn_hibma db_printf(" %-6.6s ", state); 25562642Sn_hibma } 25662642Sn_hibma wprefix = ' '; 25762642Sn_hibma if (TD_ON_LOCK(td)) { 25862642Sn_hibma wprefix = '*'; 25962642Sn_hibma wmesg = td->td_lockname; 26062642Sn_hibma wchan = td->td_blocked; 26162642Sn_hibma } else if (TD_ON_SLEEPQ(td)) { 26262642Sn_hibma wmesg = td->td_wmesg; 26362642Sn_hibma wchan = td->td_wchan; 26462642Sn_hibma } else if (TD_IS_RUNNING(td)) { 26562642Sn_hibma snprintf(state, sizeof(state), "CPU %d", td->td_oncpu); 26662642Sn_hibma wmesg = state; 267224511Smav wchan = NULL; 26875606Sn_hibma } else { 26962642Sn_hibma wmesg = ""; 270224511Smav wchan = NULL; 27167256Sn_hibma } 27267256Sn_hibma db_printf("%c%-8.8s ", wprefix, wmesg); 273224511Smav if (wchan == NULL) 27467256Sn_hibma#ifdef __LP64__ 27562642Sn_hibma db_printf("%18s ", ""); 27662642Sn_hibma#else 277225839Smav db_printf("%10s ", ""); 27862642Sn_hibma#endif 27962642Sn_hibma else 28062642Sn_hibma db_printf("%p ", wchan); 28162642Sn_hibma if (p->p_flag & P_SYSTEM) 28262642Sn_hibma db_printf("["); 28362642Sn_hibma if (td->td_name[0] != '\0') 28462642Sn_hibma db_printf("%s", td->td_name); 28562642Sn_hibma else 286224511Smav db_printf("%s", td->td_proc->p_comm); 287224511Smav if (p->p_flag & P_SYSTEM) 28862642Sn_hibma db_printf("]"); 28962642Sn_hibma db_printf("\n"); 29062642Sn_hibma} 29162642Sn_hibma 292164531SgrogDB_SHOW_COMMAND(thread, db_show_thread) 293164531Sgrog{ 294224511Smav struct thread *td; 29562642Sn_hibma struct lock_object *lock; 296224511Smav boolean_t comma; 29762642Sn_hibma 29862642Sn_hibma /* Determine which thread to examine. */ 299225839Smav if (have_addr) 30062642Sn_hibma td = db_lookup_thread(addr, FALSE); 30162642Sn_hibma else 302225839Smav td = kdb_thread; 303225839Smav lock = (struct lock_object *)td->td_lock; 30462642Sn_hibma 305225839Smav db_printf("Thread %d at %p:\n", td->td_tid, td); 30662642Sn_hibma db_printf(" proc (pid %d): %p\n", td->td_proc->p_pid, td->td_proc); 307225839Smav if (td->td_name[0] != '\0') 308225839Smav db_printf(" name: %s\n", td->td_name); 309225839Smav db_printf(" stack: %p-%p\n", (void *)td->td_kstack, 310225839Smav (void *)(td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 1)); 311225839Smav db_printf(" flags: %#x ", td->td_flags); 312225839Smav db_printf(" pflags: %#x\n", td->td_pflags); 313225839Smav db_printf(" state: "); 314225839Smav switch (td->td_state) { 315225839Smav case TDS_INACTIVE: 316225839Smav db_printf("INACTIVE\n"); 317225839Smav break; 318225839Smav case TDS_CAN_RUN: 319225839Smav db_printf("CAN RUN\n"); 320225839Smav break; 321225839Smav case TDS_RUNQ: 322225839Smav db_printf("RUNQ\n"); 323225839Smav break; 324225839Smav case TDS_RUNNING: 325225839Smav db_printf("RUNNING (CPU %d)\n", td->td_oncpu); 326225839Smav break; 327225839Smav case TDS_INHIBITED: 32862642Sn_hibma db_printf("INHIBITED: {"); 329225839Smav comma = FALSE; 330225839Smav if (TD_IS_SLEEPING(td)) { 331225839Smav db_printf("SLEEPING"); 332225839Smav comma = TRUE; 333225839Smav } 334225839Smav if (TD_IS_SUSPENDED(td)) { 335225839Smav if (comma) 336225839Smav db_printf(", "); 337225839Smav db_printf("SUSPENDED"); 338225839Smav comma = TRUE; 339225839Smav } 340225839Smav if (TD_IS_SWAPPED(td)) { 341225839Smav if (comma) 342225839Smav db_printf(", "); 343225839Smav db_printf("SWAPPED"); 34462642Sn_hibma comma = TRUE; 345225839Smav } 346225839Smav if (TD_ON_LOCK(td)) { 347225839Smav if (comma) 348225839Smav db_printf(", "); 349225839Smav db_printf("LOCK"); 350225839Smav comma = TRUE; 351225839Smav } 352225839Smav if (TD_AWAITING_INTR(td)) { 353225839Smav if (comma) 354225839Smav db_printf(", "); 35562642Sn_hibma db_printf("IWAIT"); 356225839Smav } 357225839Smav db_printf("}\n"); 358225839Smav break; 359224511Smav default: 360225839Smav db_printf("??? (%#x)\n", td->td_state); 361225839Smav break; 362225839Smav } 363225839Smav if (TD_ON_LOCK(td)) 364225839Smav db_printf(" lock: %s turnstile: %p\n", td->td_lockname, 365225839Smav td->td_blocked); 366225839Smav if (TD_ON_SLEEPQ(td)) 367225839Smav db_printf(" wmesg: %s wchan: %p\n", td->td_wmesg, 368225839Smav td->td_wchan); 369225839Smav db_printf(" priority: %d\n", td->td_priority); 370225839Smav db_printf(" container lock: %s (%p)\n", lock->lo_name, lock); 371225839Smav} 372225839Smav 373225839SmavDB_SHOW_COMMAND(proc, db_show_proc) 374225839Smav{ 375225839Smav struct thread *td; 376225839Smav struct proc *p; 377225839Smav int i; 378225839Smav 379225839Smav /* Determine which process to examine. */ 380225839Smav if (have_addr) 381225839Smav p = db_lookup_proc(addr); 382225839Smav else 383225839Smav p = kdb_thread->td_proc; 384225839Smav 385225839Smav db_printf("Process %d (%s) at %p:\n", p->p_pid, p->p_comm, p); 386225839Smav db_printf(" state: "); 387225839Smav switch (p->p_state) { 388225839Smav case PRS_NEW: 389225839Smav db_printf("NEW\n"); 390225839Smav break; 391225839Smav case PRS_NORMAL: 392225839Smav db_printf("NORMAL\n"); 393225839Smav break; 394225839Smav case PRS_ZOMBIE: 395225839Smav db_printf("ZOMBIE\n"); 396225839Smav break; 397225839Smav default: 398225839Smav db_printf("??? (%#x)\n", p->p_state); 399225839Smav } 400225839Smav if (p->p_ucred != NULL) { 401225839Smav db_printf(" uid: %d gids: ", p->p_ucred->cr_uid); 402225839Smav for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 403225839Smav db_printf("%d", p->p_ucred->cr_groups[i]); 404225839Smav if (i < (p->p_ucred->cr_ngroups - 1)) 405225839Smav db_printf(", "); 406225839Smav } 407225839Smav db_printf("\n"); 40862642Sn_hibma } 40962642Sn_hibma if (p->p_pptr != NULL) 410225839Smav db_printf(" parent: pid %d at %p\n", p->p_pptr->p_pid, 411225839Smav p->p_pptr); 412225839Smav if (p->p_leader != NULL && p->p_leader != p) 413225839Smav db_printf(" leader: pid %d at %p\n", p->p_leader->p_pid, 414225839Smav p->p_leader); 415225839Smav if (p->p_sysent != NULL) 416225839Smav db_printf(" ABI: %s\n", p->p_sysent->sv_name); 417225839Smav if (p->p_args != NULL) 418225839Smav db_printf(" arguments: %.*s\n", (int)p->p_args->ar_length, 41962642Sn_hibma p->p_args->ar_args); 420225839Smav db_printf(" threads: %d\n", p->p_numthreads); 421225839Smav FOREACH_THREAD_IN_PROC(p, td) { 422225839Smav dumpthread(p, td, 1); 423225839Smav if (db_pager_quit) 424225839Smav break; 425225839Smav } 426225839Smav} 427225839Smav