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 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/cons.h> 35 #include <sys/jail.h> 36 #include <sys/kdb.h> 37 #include <sys/linker_set.h> 38 #include <sys/proc.h> 39 #include <sys/sysent.h> 40 #include <sys/systm.h> 41 #include <vm/vm.h> 42 #include <vm/vm_param.h> 43 #include <vm/pmap.h> 44 45 #include <ddb/ddb.h> 46 47 static void dumpthread(volatile struct proc *p, volatile struct thread *td, 48 int all); 49 50 /* 51 * Layout: 52 * - column counts 53 * - header 54 * - single-threaded process 55 * - multi-threaded process 56 * - thread in a MT process 57 * 58 * 1 2 3 4 5 6 7 59 * 1234567890123456789012345678901234567890123456789012345678901234567890 60 * pid uid ppid pgrp state wmesg wchan cmd 61 * <pid> <ui> <ppi> <pgi> <stat> < wmesg > < wchan > <name> 62 * <pid> <ui> <ppi> <pgi> <stat> (threaded) <command> 63 * <tid > <stat> < wmesg > < wchan > <name> 64 * 65 * For machines with 64-bit pointers, we expand the wchan field 8 more 66 * characters. 67 */ 68 void 69 db_ps(db_expr_t addr, boolean_t hasaddr, db_expr_t count, char *modif) 70 { 71 volatile struct proc *p, *pp; 72 volatile struct thread *td; 73 struct ucred *cred; 74 struct pgrp *pgrp; 75 char state[9]; 76 int np, quit, rflag, sflag, dflag, lflag, wflag; 77 78 np = nprocs; 79 quit = 0; 80 81 if (!LIST_EMPTY(&allproc)) 82 p = LIST_FIRST(&allproc); 83 else 84 p = &proc0; 85 86 db_setup_paging(db_simple_pager, &quit, db_lines_per_page); 87 #ifdef __LP64__ 88 db_printf(" pid uid ppid pgrp state wmesg wchan cmd\n"); 89 #else 90 db_printf(" pid uid ppid pgrp state wmesg wchan cmd\n"); 91 #endif 92 while (--np >= 0 && !quit) { 93 if (p == NULL) { 94 db_printf("oops, ran out of processes early!\n"); 95 break; 96 } 97 pp = p->p_pptr; 98 if (pp == NULL) 99 pp = p; 100 101 cred = p->p_ucred; 102 pgrp = p->p_pgrp; 103 db_printf("%5d %4d %5d %5d ", p->p_pid, 104 cred != NULL ? cred->cr_ruid : 0, pp->p_pid, 105 pgrp != NULL ? pgrp->pg_id : 0); 106 107 /* Determine our primary process state. */ 108 switch (p->p_state) { 109 case PRS_NORMAL: 110 if (P_SHOULDSTOP(p)) 111 state[0] = 'T'; 112 else { 113 /* 114 * One of D, L, R, S, W. For a 115 * multithreaded process we will use 116 * the state of the thread with the 117 * highest precedence. The 118 * precendence order from high to low 119 * is R, L, D, S, W. If no thread is 120 * in a sane state we use '?' for our 121 * primary state. 122 */ 123 rflag = sflag = dflag = lflag = wflag = 0; 124 FOREACH_THREAD_IN_PROC(p, td) { 125 if (td->td_state == TDS_RUNNING || 126 td->td_state == TDS_RUNQ || 127 td->td_state == TDS_CAN_RUN) 128 rflag++; 129 if (TD_ON_LOCK(td)) 130 lflag++; 131 if (TD_IS_SLEEPING(td)) { 132 if (!td->td_flags & TDF_SINTR) 133 dflag++; 134 else 135 sflag++; 136 } 137 if (TD_AWAITING_INTR(td)) 138 wflag++; 139 } 140 if (rflag) 141 state[0] = 'R'; 142 else if (lflag) 143 state[0] = 'L'; 144 else if (dflag) 145 state[0] = 'D'; 146 else if (sflag) 147 state[0] = 'S'; 148 else if (wflag) 149 state[0] = 'W'; 150 else 151 state[0] = '?'; 152 } 153 break; 154 case PRS_NEW: 155 state[0] = 'N'; 156 break; 157 case PRS_ZOMBIE: 158 state[0] = 'Z'; 159 break; 160 default: 161 state[0] = 'U'; 162 break; 163 } 164 state[1] = '\0'; 165 166 /* Additional process state flags. */ 167 if (!p->p_sflag & PS_INMEM) 168 strlcat(state, "W", sizeof(state)); 169 if (p->p_flag & P_TRACED) 170 strlcat(state, "X", sizeof(state)); 171 if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE) 172 strlcat(state, "E", sizeof(state)); 173 if (p->p_flag & P_PPWAIT) 174 strlcat(state, "V", sizeof(state)); 175 if (p->p_flag & P_SYSTEM || p->p_lock > 0) 176 strlcat(state, "L", sizeof(state)); 177 if (p->p_session != NULL && SESS_LEADER(p)) 178 strlcat(state, "s", sizeof(state)); 179 /* Cheated here and didn't compare pgid's. */ 180 if (p->p_flag & P_CONTROLT) 181 strlcat(state, "+", sizeof(state)); 182 if (cred != NULL && jailed(cred)) 183 strlcat(state, "J", sizeof(state)); 184 db_printf(" %-6.6s ", state); 185 if (p->p_flag & P_HADTHREADS) 186 #ifdef __LP64__ 187 db_printf(" (threaded) %s\n", 188 p->p_comm); 189 #else 190 db_printf(" (threaded) %s\n", p->p_comm); 191 #endif 192 FOREACH_THREAD_IN_PROC(p, td) { 193 dumpthread(p, td, p->p_flag & P_HADTHREADS); 194 if (quit) 195 break; 196 } 197 198 p = LIST_NEXT(p, p_list); 199 if (p == NULL && np > 0) 200 p = LIST_FIRST(&zombproc); 201 } 202 } 203 204 static void 205 dumpthread(volatile struct proc *p, volatile struct thread *td, int all) 206 { 207 char state[9], wprefix; 208 const char *wmesg; 209 void *wchan; 210 211 if (all) { 212 db_printf(" %9d ", td->td_tid); 213 switch (td->td_state) { 214 case TDS_RUNNING: 215 snprintf(state, sizeof(state), "Run"); 216 break; 217 case TDS_RUNQ: 218 snprintf(state, sizeof(state), "RunQ"); 219 break; 220 case TDS_CAN_RUN: 221 snprintf(state, sizeof(state), "CanRun"); 222 break; 223 case TDS_INACTIVE: 224 snprintf(state, sizeof(state), "Inactv"); 225 break; 226 case TDS_INHIBITED: 227 state[0] = '\0'; 228 if (TD_ON_LOCK(td)) 229 strlcat(state, "L", sizeof(state)); 230 if (TD_IS_SLEEPING(td)) { 231 if (td->td_flags & TDF_SINTR) 232 strlcat(state, "S", sizeof(state)); 233 else 234 strlcat(state, "D", sizeof(state)); 235 } 236 if (TD_IS_SWAPPED(td)) 237 strlcat(state, "W", sizeof(state)); 238 if (TD_AWAITING_INTR(td)) 239 strlcat(state, "I", sizeof(state)); 240 if (TD_IS_SUSPENDED(td)) 241 strlcat(state, "s", sizeof(state)); 242 if (state[0] != '\0') 243 break; 244 default: 245 snprintf(state, sizeof(state), "???"); 246 } 247 db_printf(" %-6.6s ", state); 248 } 249 wprefix = ' '; 250 if (TD_ON_LOCK(td)) { 251 wprefix = '*'; 252 wmesg = td->td_lockname; 253 wchan = td->td_blocked; 254 } else if (TD_ON_SLEEPQ(td)) { 255 wmesg = td->td_wmesg; 256 wchan = td->td_wchan; 257 } else if (TD_IS_RUNNING(td)) { 258 snprintf(state, sizeof(state), "CPU %d", td->td_oncpu); 259 wmesg = state; 260 wchan = NULL; 261 } else { 262 wmesg = ""; 263 wchan = NULL; 264 } 265 db_printf("%c%-8.8s ", wprefix, wmesg); 266 if (wchan == NULL) 267 #ifdef __LP64__ 268 db_printf("%18s ", ""); 269 #else 270 db_printf("%10s ", ""); 271 #endif 272 else 273 db_printf("%p ", wchan); 274 if (p->p_flag & P_SYSTEM) 275 db_printf("["); 276 if (td->td_name[0] != '\0') 277 db_printf("%s", td->td_name); 278 else 279 db_printf("%s", td->td_proc->p_comm); 280 if (p->p_flag & P_SYSTEM) 281 db_printf("]"); 282 db_printf("\n"); 283 } 284 285 DB_SHOW_COMMAND(thread, db_show_thread) 286 { 287 struct thread *td; 288 boolean_t comma; 289 290 /* Determine which thread to examine. */ 291 if (have_addr) 292 td = db_lookup_thread(addr, FALSE); 293 else 294 td = kdb_thread; 295 296 db_printf("Thread %d at %p:\n", td->td_tid, td); 297 db_printf(" proc (pid %d): %p ", td->td_proc->p_pid, td->td_proc); 298 db_printf(" ksegrp: %p\n", td->td_ksegrp); 299 if (td->td_name[0] != '\0') 300 db_printf(" name: %s\n", td->td_name); 301 db_printf(" flags: %#x ", td->td_flags); 302 db_printf(" pflags: %#x\n", td->td_pflags); 303 db_printf(" state: "); 304 switch (td->td_state) { 305 case TDS_INACTIVE: 306 db_printf("INACTIVE\n"); 307 break; 308 case TDS_CAN_RUN: 309 db_printf("CAN RUN\n"); 310 break; 311 case TDS_RUNQ: 312 db_printf("RUNQ\n"); 313 break; 314 case TDS_RUNNING: 315 db_printf("RUNNING (CPU %d)\n", td->td_oncpu); 316 break; 317 case TDS_INHIBITED: 318 db_printf("INHIBITED: {"); 319 comma = FALSE; 320 if (TD_IS_SLEEPING(td)) { 321 db_printf("SLEEPING"); 322 comma = TRUE; 323 } 324 if (TD_IS_SUSPENDED(td)) { 325 if (comma) 326 db_printf(", "); 327 db_printf("SUSPENDED"); 328 comma = TRUE; 329 } 330 if (TD_IS_SWAPPED(td)) { 331 if (comma) 332 db_printf(", "); 333 db_printf("SWAPPED"); 334 comma = TRUE; 335 } 336 if (TD_ON_LOCK(td)) { 337 if (comma) 338 db_printf(", "); 339 db_printf("LOCK"); 340 comma = TRUE; 341 } 342 if (TD_AWAITING_INTR(td)) { 343 if (comma) 344 db_printf(", "); 345 db_printf("IWAIT"); 346 } 347 db_printf("}\n"); 348 break; 349 default: 350 db_printf("??? (%#x)\n", td->td_state); 351 break; 352 } 353 if (TD_ON_LOCK(td)) 354 db_printf(" lock: %s turnstile: %p\n", td->td_lockname, 355 td->td_blocked); 356 if (TD_ON_SLEEPQ(td)) 357 db_printf(" wmesg: %s wchan: %p\n", td->td_wmesg, 358 td->td_wchan); 359 db_printf(" priority: %d\n", td->td_priority); 360 } 361 362 DB_SHOW_COMMAND(proc, db_show_proc) 363 { 364 struct thread *td; 365 struct proc *p; 366 int i, quit; 367 368 /* Determine which process to examine. */ 369 if (have_addr) 370 p = db_lookup_proc(addr); 371 else 372 p = kdb_thread->td_proc; 373 374 quit = 0; 375 db_setup_paging(db_simple_pager, &quit, db_lines_per_page); 376 db_printf("Process %d (%s) at %p:\n", p->p_pid, p->p_comm, p); 377 db_printf(" state: "); 378 switch (p->p_state) { 379 case PRS_NEW: 380 db_printf("NEW\n"); 381 break; 382 case PRS_NORMAL: 383 db_printf("NORMAL\n"); 384 break; 385 case PRS_ZOMBIE: 386 db_printf("ZOMBIE\n"); 387 break; 388 default: 389 db_printf("??? (%#x)\n", p->p_state); 390 } 391 if (p->p_ucred != NULL) { 392 db_printf(" uid: %d gids: ", p->p_ucred->cr_uid); 393 for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 394 db_printf("%d", p->p_ucred->cr_groups[i]); 395 if (i < (p->p_ucred->cr_ngroups - 1)) 396 db_printf(", "); 397 } 398 db_printf("\n"); 399 } 400 if (p->p_pptr != NULL) 401 db_printf(" parent: pid %d at %p\n", p->p_pptr->p_pid, 402 p->p_pptr); 403 if (p->p_leader != NULL && p->p_leader != p) 404 db_printf(" leader: pid %d at %p\n", p->p_leader->p_pid, 405 p->p_leader); 406 if (p->p_sysent != NULL) 407 db_printf(" ABI: %s\n", p->p_sysent->sv_name); 408 if (p->p_args != NULL) 409 db_printf(" arguments: %.*s\n", (int)p->p_args->ar_length, 410 p->p_args->ar_args); 411 db_printf(" threads: %d\n", p->p_numthreads); 412 FOREACH_THREAD_IN_PROC(p, td) { 413 dumpthread(p, td, 1); 414 if (quit) 415 break; 416 } 417 } 418