The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_ps.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 1993 The Regents of the University of California.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include "opt_kstack_pages.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/cons.h>
   39 #include <sys/jail.h>
   40 #include <sys/kdb.h>
   41 #include <sys/kernel.h>
   42 #include <sys/proc.h>
   43 #include <sys/sysent.h>
   44 #include <sys/systm.h>
   45 #include <sys/_kstack_cache.h>
   46 #include <vm/vm.h>
   47 #include <vm/vm_param.h>
   48 #include <vm/pmap.h>
   49 #include <vm/vm_map.h>
   50 
   51 #include <ddb/ddb.h>
   52 
   53 #define PRINT_NONE      0
   54 #define PRINT_ARGS      1
   55 
   56 static void     dumpthread(volatile struct proc *p, volatile struct thread *td,
   57                     int all);
   58 static int      ps_mode;
   59 
   60 /*
   61  * At least one non-optional show-command must be implemented using
   62  * DB_SHOW_ALL_COMMAND() so that db_show_all_cmd_set gets created.
   63  * Here is one.
   64  */
   65 DB_SHOW_ALL_COMMAND(procs, db_procs_cmd)
   66 {
   67         db_ps(addr, have_addr, count, modif);
   68 }
   69 
   70 static void
   71 dump_args(volatile struct proc *p)
   72 {
   73         char *args;
   74         int i, len;
   75 
   76         if (p->p_args == NULL)
   77                 return;
   78         args = p->p_args->ar_args;
   79         len = (int)p->p_args->ar_length;
   80         for (i = 0; i < len; i++) {
   81                 if (args[i] == '\0')
   82                         db_printf(" ");
   83                 else
   84                         db_printf("%c", args[i]);
   85         }
   86 }
   87 
   88 /*
   89  * Layout:
   90  * - column counts
   91  * - header
   92  * - single-threaded process
   93  * - multi-threaded process
   94  * - thread in a MT process
   95  *
   96  *          1         2         3         4         5         6         7
   97  * 1234567890123456789012345678901234567890123456789012345678901234567890
   98  *   pid  ppid  pgrp   uid  state   wmesg   wchan       cmd
   99  * <pid> <ppi> <pgi> <uid>  <stat>  <wmesg> <wchan   >  <name>
  100  * <pid> <ppi> <pgi> <uid>  <stat>  (threaded)          <command>
  101  * <tid >                   <stat>  <wmesg> <wchan   >  <name>
  102  *
  103  * For machines with 64-bit pointers, we expand the wchan field 8 more
  104  * characters.
  105  */
  106 void
  107 db_ps(db_expr_t addr, bool hasaddr, db_expr_t count, char *modif)
  108 {
  109         volatile struct proc *p, *pp;
  110         volatile struct thread *td;
  111         struct ucred *cred;
  112         struct pgrp *pgrp;
  113         char state[9];
  114         int np, rflag, sflag, dflag, lflag, wflag;
  115 
  116         ps_mode = modif[0] == 'a' ? PRINT_ARGS : PRINT_NONE;
  117         np = nprocs;
  118 
  119         if (!LIST_EMPTY(&allproc))
  120                 p = LIST_FIRST(&allproc);
  121         else
  122                 p = &proc0;
  123 
  124 #ifdef __LP64__
  125         db_printf("  pid  ppid  pgrp   uid  state   wmesg   wchan               cmd\n");
  126 #else
  127         db_printf("  pid  ppid  pgrp   uid  state   wmesg   wchan       cmd\n");
  128 #endif
  129         while (--np >= 0 && !db_pager_quit) {
  130                 if (p == NULL) {
  131                         db_printf("oops, ran out of processes early!\n");
  132                         break;
  133                 }
  134                 pp = p->p_pptr;
  135                 if (pp == NULL)
  136                         pp = p;
  137 
  138                 cred = p->p_ucred;
  139                 pgrp = p->p_pgrp;
  140                 db_printf("%5d %5d %5d %5d ", p->p_pid, pp->p_pid,
  141                     pgrp != NULL ? pgrp->pg_id : 0,
  142                     cred != NULL ? cred->cr_ruid : 0);
  143 
  144                 /* Determine our primary process state. */
  145                 switch (p->p_state) {
  146                 case PRS_NORMAL:
  147                         if (P_SHOULDSTOP(p))
  148                                 state[0] = 'T';
  149                         else {
  150                                 /*
  151                                  * One of D, L, R, S, W.  For a
  152                                  * multithreaded process we will use
  153                                  * the state of the thread with the
  154                                  * highest precedence.  The
  155                                  * precendence order from high to low
  156                                  * is R, L, D, S, W.  If no thread is
  157                                  * in a sane state we use '?' for our
  158                                  * primary state.
  159                                  */
  160                                 rflag = sflag = dflag = lflag = wflag = 0;
  161                                 FOREACH_THREAD_IN_PROC(p, td) {
  162                                         if (td->td_state == TDS_RUNNING ||
  163                                             td->td_state == TDS_RUNQ ||
  164                                             td->td_state == TDS_CAN_RUN)
  165                                                 rflag++;
  166                                         if (TD_ON_LOCK(td))
  167                                                 lflag++;
  168                                         if (TD_IS_SLEEPING(td)) {
  169                                                 if (!(td->td_flags & TDF_SINTR))
  170                                                         dflag++;
  171                                                 else
  172                                                         sflag++;
  173                                         }
  174                                         if (TD_AWAITING_INTR(td))
  175                                                 wflag++;
  176                                 }
  177                                 if (rflag)
  178                                         state[0] = 'R';
  179                                 else if (lflag)
  180                                         state[0] = 'L';
  181                                 else if (dflag)
  182                                         state[0] = 'D';
  183                                 else if (sflag)
  184                                         state[0] = 'S';
  185                                 else if (wflag)
  186                                         state[0] = 'W';
  187                                 else
  188                                         state[0] = '?';
  189                         }
  190                         break;
  191                 case PRS_NEW:
  192                         state[0] = 'N';
  193                         break;
  194                 case PRS_ZOMBIE:
  195                         state[0] = 'Z';
  196                         break;
  197                 default:
  198                         state[0] = 'U';
  199                         break;
  200                 }
  201                 state[1] = '\0';
  202 
  203                 /* Additional process state flags. */
  204                 if (!(p->p_flag & P_INMEM))
  205                         strlcat(state, "W", sizeof(state));
  206                 if (p->p_flag & P_TRACED)
  207                         strlcat(state, "X", sizeof(state));
  208                 if (p->p_flag & P_WEXIT && p->p_state != PRS_ZOMBIE)
  209                         strlcat(state, "E", sizeof(state));
  210                 if (p->p_flag & P_PPWAIT)
  211                         strlcat(state, "V", sizeof(state));
  212                 if (p->p_flag & P_SYSTEM || p->p_lock > 0)
  213                         strlcat(state, "L", sizeof(state));
  214                 if (p->p_pgrp != NULL && p->p_session != NULL &&
  215                     SESS_LEADER(p))
  216                         strlcat(state, "s", sizeof(state));
  217                 /* Cheated here and didn't compare pgid's. */
  218                 if (p->p_flag & P_CONTROLT)
  219                         strlcat(state, "+", sizeof(state));
  220                 if (cred != NULL && jailed(cred))
  221                         strlcat(state, "J", sizeof(state));
  222                 db_printf(" %-6.6s ", state);
  223                 if (p->p_flag & P_HADTHREADS) {
  224 #ifdef __LP64__
  225                         db_printf(" (threaded)                  ");
  226 #else
  227                         db_printf(" (threaded)          ");
  228 #endif
  229                         if (p->p_flag & P_SYSTEM)
  230                                 db_printf("[");
  231                         db_printf("%s", p->p_comm);
  232                         if (p->p_flag & P_SYSTEM)
  233                                 db_printf("]");
  234                         if (ps_mode == PRINT_ARGS) {
  235                                 db_printf(" ");
  236                                 dump_args(p);
  237                         }
  238                         db_printf("\n");
  239                 }
  240                 FOREACH_THREAD_IN_PROC(p, td) {
  241                         dumpthread(p, td, p->p_flag & P_HADTHREADS);
  242                         if (db_pager_quit)
  243                                 break;
  244                 }
  245 
  246                 p = LIST_NEXT(p, p_list);
  247                 if (p == NULL && np > 0)
  248                         p = LIST_FIRST(&zombproc);
  249         }
  250 }
  251 
  252 static void
  253 dumpthread(volatile struct proc *p, volatile struct thread *td, int all)
  254 {
  255         char state[9], wprefix;
  256         const char *wmesg;
  257         void *wchan;
  258         
  259         if (all) {
  260                 db_printf("%6d                  ", td->td_tid);
  261                 switch (td->td_state) {
  262                 case TDS_RUNNING:
  263                         snprintf(state, sizeof(state), "Run");
  264                         break;
  265                 case TDS_RUNQ:
  266                         snprintf(state, sizeof(state), "RunQ");
  267                         break;
  268                 case TDS_CAN_RUN:
  269                         snprintf(state, sizeof(state), "CanRun");
  270                         break;
  271                 case TDS_INACTIVE:
  272                         snprintf(state, sizeof(state), "Inactv");
  273                         break;
  274                 case TDS_INHIBITED:
  275                         state[0] = '\0';
  276                         if (TD_ON_LOCK(td))
  277                                 strlcat(state, "L", sizeof(state));
  278                         if (TD_IS_SLEEPING(td)) {
  279                                 if (td->td_flags & TDF_SINTR)
  280                                         strlcat(state, "S", sizeof(state));
  281                                 else
  282                                         strlcat(state, "D", sizeof(state));
  283                         }
  284                         if (TD_IS_SWAPPED(td))
  285                                 strlcat(state, "W", sizeof(state));
  286                         if (TD_AWAITING_INTR(td))
  287                                 strlcat(state, "I", sizeof(state));
  288                         if (TD_IS_SUSPENDED(td))
  289                                 strlcat(state, "s", sizeof(state));
  290                         if (state[0] != '\0')
  291                                 break;
  292                 default:
  293                         snprintf(state, sizeof(state), "???");
  294                 }                       
  295                 db_printf(" %-6.6s ", state);
  296         }
  297         wprefix = ' ';
  298         if (TD_ON_LOCK(td)) {
  299                 wprefix = '*';
  300                 wmesg = td->td_lockname;
  301                 wchan = td->td_blocked;
  302         } else if (TD_ON_SLEEPQ(td)) {
  303                 wmesg = td->td_wmesg;
  304                 wchan = td->td_wchan;
  305         } else if (TD_IS_RUNNING(td)) {
  306                 snprintf(state, sizeof(state), "CPU %d", td->td_oncpu);
  307                 wmesg = state;
  308                 wchan = NULL;
  309         } else {
  310                 wmesg = "";
  311                 wchan = NULL;
  312         }
  313         db_printf("%c%-7.7s ", wprefix, wmesg);
  314         if (wchan == NULL)
  315 #ifdef __LP64__
  316                 db_printf("%18s  ", "");
  317 #else
  318                 db_printf("%10s  ", "");
  319 #endif
  320         else
  321                 db_printf("%p  ", wchan);
  322         if (p->p_flag & P_SYSTEM)
  323                 db_printf("[");
  324         if (td->td_name[0] != '\0')
  325                 db_printf("%s", td->td_name);
  326         else
  327                 db_printf("%s", td->td_proc->p_comm);
  328         if (p->p_flag & P_SYSTEM)
  329                 db_printf("]");
  330         if (ps_mode == PRINT_ARGS && all == 0) {
  331                 db_printf(" ");
  332                 dump_args(p);
  333         }
  334         db_printf("\n");
  335 }
  336 
  337 DB_SHOW_COMMAND(thread, db_show_thread)
  338 {
  339         struct thread *td;
  340         struct lock_object *lock;
  341         bool comma;
  342         int delta;
  343 
  344         /* Determine which thread to examine. */
  345         if (have_addr)
  346                 td = db_lookup_thread(addr, false);
  347         else
  348                 td = kdb_thread;
  349         lock = (struct lock_object *)td->td_lock;
  350 
  351         db_printf("Thread %d at %p:\n", td->td_tid, td);
  352         db_printf(" proc (pid %d): %p\n", td->td_proc->p_pid, td->td_proc);
  353         if (td->td_name[0] != '\0')
  354                 db_printf(" name: %s\n", td->td_name);
  355         db_printf(" stack: %p-%p\n", (void *)td->td_kstack,
  356             (void *)(td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 1));
  357         db_printf(" flags: %#x ", td->td_flags);
  358         db_printf(" pflags: %#x\n", td->td_pflags);
  359         db_printf(" state: ");
  360         switch (td->td_state) {
  361         case TDS_INACTIVE:
  362                 db_printf("INACTIVE\n");
  363                 break;
  364         case TDS_CAN_RUN:
  365                 db_printf("CAN RUN\n");
  366                 break;
  367         case TDS_RUNQ:
  368                 db_printf("RUNQ\n");
  369                 break;
  370         case TDS_RUNNING:
  371                 db_printf("RUNNING (CPU %d)\n", td->td_oncpu);
  372                 break;
  373         case TDS_INHIBITED:
  374                 db_printf("INHIBITED: {");
  375                 comma = false;
  376                 if (TD_IS_SLEEPING(td)) {
  377                         db_printf("SLEEPING");
  378                         comma = true;
  379                 }
  380                 if (TD_IS_SUSPENDED(td)) {
  381                         if (comma)
  382                                 db_printf(", ");
  383                         db_printf("SUSPENDED");
  384                         comma = true;
  385                 }
  386                 if (TD_IS_SWAPPED(td)) {
  387                         if (comma)
  388                                 db_printf(", ");
  389                         db_printf("SWAPPED");
  390                         comma = true;
  391                 }
  392                 if (TD_ON_LOCK(td)) {
  393                         if (comma)
  394                                 db_printf(", ");
  395                         db_printf("LOCK");
  396                         comma = true;
  397                 }
  398                 if (TD_AWAITING_INTR(td)) {
  399                         if (comma)
  400                                 db_printf(", ");
  401                         db_printf("IWAIT");
  402                 }
  403                 db_printf("}\n");
  404                 break;
  405         default:
  406                 db_printf("??? (%#x)\n", td->td_state);
  407                 break;
  408         }
  409         if (TD_ON_LOCK(td))
  410                 db_printf(" lock: %s  turnstile: %p\n", td->td_lockname,
  411                     td->td_blocked);
  412         if (TD_ON_SLEEPQ(td))
  413                 db_printf(
  414             " wmesg: %s  wchan: %p sleeptimo %lx. %jx (curr %lx. %jx)\n",
  415                     td->td_wmesg, td->td_wchan,
  416                     (long)sbttobt(td->td_sleeptimo).sec,
  417                     (uintmax_t)sbttobt(td->td_sleeptimo).frac,
  418                     (long)sbttobt(sbinuptime()).sec,
  419                     (uintmax_t)sbttobt(sbinuptime()).frac);
  420         db_printf(" priority: %d\n", td->td_priority);
  421         db_printf(" container lock: %s (%p)\n", lock->lo_name, lock);
  422         if (td->td_swvoltick != 0) {
  423                 delta = (u_int)ticks - (u_int)td->td_swvoltick;
  424                 db_printf(" last voluntary switch: %d ms ago\n",
  425                     1000 * delta / hz);
  426         }
  427         if (td->td_swinvoltick != 0) {
  428                 delta = (u_int)ticks - (u_int)td->td_swinvoltick;
  429                 db_printf(" last involuntary switch: %d ms ago\n",
  430                     1000 * delta / hz);
  431         }
  432 }
  433 
  434 DB_SHOW_COMMAND(proc, db_show_proc)
  435 {
  436         struct thread *td;
  437         struct proc *p;
  438         int i;
  439 
  440         /* Determine which process to examine. */
  441         if (have_addr)
  442                 p = db_lookup_proc(addr);
  443         else
  444                 p = kdb_thread->td_proc;
  445 
  446         db_printf("Process %d (%s) at %p:\n", p->p_pid, p->p_comm, p);
  447         db_printf(" state: ");
  448         switch (p->p_state) {
  449         case PRS_NEW:
  450                 db_printf("NEW\n");
  451                 break;
  452         case PRS_NORMAL:
  453                 db_printf("NORMAL\n");
  454                 break;
  455         case PRS_ZOMBIE:
  456                 db_printf("ZOMBIE\n");
  457                 break;
  458         default:
  459                 db_printf("??? (%#x)\n", p->p_state);
  460         }
  461         if (p->p_ucred != NULL) {
  462                 db_printf(" uid: %d  gids: ", p->p_ucred->cr_uid);
  463                 for (i = 0; i < p->p_ucred->cr_ngroups; i++) {
  464                         db_printf("%d", p->p_ucred->cr_groups[i]);
  465                         if (i < (p->p_ucred->cr_ngroups - 1))
  466                                 db_printf(", ");
  467                 }
  468                 db_printf("\n");
  469         }
  470         if (p->p_pptr != NULL)
  471                 db_printf(" parent: pid %d at %p\n", p->p_pptr->p_pid,
  472                     p->p_pptr);
  473         if (p->p_leader != NULL && p->p_leader != p)
  474                 db_printf(" leader: pid %d at %p\n", p->p_leader->p_pid,
  475                     p->p_leader);
  476         if (p->p_sysent != NULL)
  477                 db_printf(" ABI: %s\n", p->p_sysent->sv_name);
  478         if (p->p_args != NULL) {
  479                 db_printf(" arguments: ");
  480                 dump_args(p);
  481                 db_printf("\n");
  482         }
  483         db_printf(" repear: %p reapsubtree: %d\n",
  484             p->p_reaper, p->p_reapsubtree);
  485         db_printf(" sigparent: %d\n", p->p_sigparent);
  486         db_printf(" vmspace: %p\n", p->p_vmspace);
  487         db_printf("   (map %p)\n",
  488             (p->p_vmspace != NULL) ? &p->p_vmspace->vm_map : 0);
  489         db_printf("   (map.pmap %p)\n",
  490             (p->p_vmspace != NULL) ? &p->p_vmspace->vm_map.pmap : 0);
  491         db_printf("   (pmap %p)\n",
  492             (p->p_vmspace != NULL) ? &p->p_vmspace->vm_pmap : 0);
  493         db_printf(" threads: %d\n", p->p_numthreads);
  494         FOREACH_THREAD_IN_PROC(p, td) {
  495                 dumpthread(p, td, 1);
  496                 if (db_pager_quit)
  497                         break;
  498         }
  499 }
  500 
  501 void
  502 db_findstack_cmd(db_expr_t addr, bool have_addr, db_expr_t dummy3 __unused,
  503     char *dummy4 __unused)
  504 {
  505         struct proc *p;
  506         struct thread *td;
  507         struct kstack_cache_entry *ks_ce;
  508         vm_offset_t saddr;
  509 
  510         if (have_addr)
  511                 saddr = addr;
  512         else {
  513                 db_printf("Usage: findstack <address>\n");
  514                 return;
  515         }
  516 
  517         FOREACH_PROC_IN_SYSTEM(p) {
  518                 FOREACH_THREAD_IN_PROC(p, td) {
  519                         if (td->td_kstack <= saddr && saddr < td->td_kstack +
  520                             PAGE_SIZE * td->td_kstack_pages) {
  521                                 db_printf("Thread %p\n", td);
  522                                 return;
  523                         }
  524                 }
  525         }
  526 
  527         for (ks_ce = kstack_cache; ks_ce != NULL;
  528              ks_ce = ks_ce->next_ks_entry) {
  529                 if ((vm_offset_t)ks_ce <= saddr && saddr < (vm_offset_t)ks_ce +
  530                     PAGE_SIZE * kstack_pages) {
  531                         db_printf("Cached stack %p\n", ks_ce);
  532                         return;
  533                 }
  534         }
  535 }

Cache object: 7c3c4929fe050f5a3237399c80a78bf6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.