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_print.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  * Mach Operating System
    3  * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        db_print.c,v $
   29  * Revision 2.20  93/11/17  16:24:19  dbg
   30  *      Changes for new scheduler:
   31  *        task_priority is gone
   32  *        use policy-specific function to print policy name and priority
   33  *      [93/05/11            dbg]
   34  * 
   35  *      Added include of kern/processor.h.
   36  *      [93/04/10            dbg]
   37  * 
   38  * Revision 2.19  93/03/09  10:53:44  danner
   39  *      String protos.
   40  *      [93/03/07            af]
   41  * 
   42  * Revision 2.18  93/01/14  17:25:33  danner
   43  *      64bit cleanup.
   44  *      [92/11/30            af]
   45  * 
   46  * Revision 2.17  92/08/05  18:02:39  jfriedl
   47  *      Removed silly prototypes.
   48  * 
   49  * Revision 2.16  92/05/21  17:07:35  jfriedl
   50  *      Removed unused variable from db_show_regs().
   51  *      [92/05/16            jfriedl]
   52  * 
   53  * Revision 2.15  92/05/04  11:24:08  danner
   54  *      Converted some db_printsyms to db_task_printsyms.
   55  *      [92/04/10            danner]
   56  * 
   57  * Revision 2.14  92/04/01  19:31:37  rpd
   58  *      Changed db_print_thread so that both display formats
   59  *      show the floating-point-used status of the thread.
   60  *      [92/03/16            rpd]
   61  * 
   62  * Revision 2.13  92/02/20  18:34:28  elf
   63  *      Fixed typo.
   64  *      [92/02/20            elf]
   65  * 
   66  * Revision 2.12  92/02/19  15:07:47  elf
   67  *      Added db_thread_fp_used, to avoid machine-dependent conditionals.
   68  *      [92/02/19            rpd]
   69  * 
   70  *      Added 'F' flag to db_thread_stat showing if the thread has a valid
   71  *      FPU context. Tested on i386 and pmax.
   72  *      [92/02/17            kivinen]
   73  * 
   74  * Revision 2.11  91/11/12  11:50:32  rvb
   75  *      Added OPTION_USER ("/u") to db_show_all_threads, db_show_one_thread,
   76  *      db_show_one_task.  Without it, we display old-style information.
   77  *      [91/10/31            rpd]
   78  * 
   79  * Revision 2.10  91/10/09  16:01:48  af
   80  *      Supported "show registers" for non current thread.
   81  *      Changed display format of thread and task information.
   82  *      Changed "show thread" to print current thread information 
   83  *        if no thread is specified.
   84  *      Added "show_one_task" for "show task" command.
   85  *      Added IPC port print routines for "show ipc_port" command.
   86  *      [91/08/29            tak]
   87  * 
   88  * Revision 2.9  91/08/03  18:17:19  jsb
   89  *      In db_print_thread, if the thread is swapped and there is a
   90  *      continuation function, print the function name in parentheses
   91  *      instead of '(swapped)'.
   92  *      [91/07/04  09:59:27  jsb]
   93  * 
   94  * Revision 2.8  91/07/31  17:30:43  dbg
   95  *      Revise scheduling state machine.
   96  *      [91/07/30  16:43:42  dbg]
   97  * 
   98  * Revision 2.7  91/07/09  23:15:57  danner
   99  *      Fixed a few printf that should be db_printfs. 
  100  *      [91/07/08            danner]
  101  * 
  102  * Revision 2.6  91/05/14  15:35:25  mrt
  103  *      Correcting copyright
  104  * 
  105  * Revision 2.5  91/02/05  17:06:53  mrt
  106  *      Changed to new Mach copyright
  107  *      [91/01/31  16:18:56  mrt]
  108  * 
  109  * Revision 2.4  90/10/25  14:43:54  rwd
  110  *      Changed db_show_regs to print unsigned.
  111  *      [90/10/19            rpd]
  112  *      Generalized the watchpoint support.
  113  *      [90/10/16            rwd]
  114  * 
  115  * Revision 2.3  90/09/09  23:19:52  rpd
  116  *      Avoid totally incorrect guesses of symbol names for small values.
  117  *      [90/08/30  17:39:08  af]
  118  * 
  119  * Revision 2.2  90/08/27  21:51:49  dbg
  120  *      Insist that 'show thread' be called with an explicit address.
  121  *      [90/08/22            dbg]
  122  * 
  123  *      Fix type for db_maxoff.
  124  *      [90/08/20            dbg]
  125  * 
  126  *      Do not dereference the "valuep" field of a variable directly,
  127  *      call the new db_read/write_variable functions instead.
  128  *      Reflected changes in symbol lookup functions.
  129  *      [90/08/20            af]
  130  *      Reduce lint.
  131  *      [90/08/10  14:33:44  dbg]
  132  * 
  133  *      Created.
  134  *      [90/07/25            dbg]
  135  * 
  136  */
  137 /*
  138  *      Author: David B. Golub, Carnegie Mellon University
  139  *      Date:   7/90
  140  */
  141 
  142 /*
  143  * Miscellaneous printing.
  144  */
  145 #include <mach/port.h>
  146 #include <kern/strings.h>
  147 #include <kern/task.h>
  148 #include <kern/thread.h>
  149 #include <kern/processor.h>
  150 #include <kern/queue.h>
  151 #include <ipc/ipc_port.h>
  152 #include <ipc/ipc_space.h>
  153 
  154 #include <machine/db_machdep.h>
  155 #include <machine/thread.h>
  156 
  157 #include <ddb/db_command.h>
  158 #include <ddb/db_lex.h>
  159 #include <ddb/db_output.h>
  160 #include <ddb/db_variables.h>
  161 #include <ddb/db_sym.h>
  162 #include <ddb/db_task_thread.h>
  163 
  164 extern unsigned int     db_maxoff;
  165 
  166 /* ARGSUSED */
  167 void
  168 db_show_regs(
  169         db_expr_t       addr,
  170         boolean_t       have_addr,
  171         db_expr_t       count,
  172         char            *modif)
  173 {
  174         register struct db_variable *regp;
  175         db_expr_t       value;
  176         db_addr_t       offset;
  177         char *          name;
  178         register        i;
  179         struct db_var_aux_param aux_param;
  180         task_t          task = TASK_NULL;
  181 
  182         aux_param.modif = modif;
  183         aux_param.thread = THREAD_NULL;
  184         if (db_option(modif, 't')) {
  185             if (have_addr) {
  186                 if (!db_check_thread_address_valid(addr))
  187                     return;
  188                 aux_param.thread = (thread_t)addr;
  189             } else
  190                 aux_param.thread = db_default_thread;
  191             if (aux_param.thread != THREAD_NULL)
  192                 task = aux_param.thread->task;
  193         }
  194         for (regp = db_regs; regp < db_eregs; regp++) {
  195             if (regp->max_level > 1) {
  196                 db_printf("bad multi-suffixed register %s\n", regp->name);
  197                 continue;
  198             }
  199             aux_param.level = regp->max_level;
  200             for (i = regp->low; i <= regp->high; i++) {
  201                 aux_param.suffix[0] = i;
  202                 db_read_write_variable(regp, &value, DB_VAR_GET, &aux_param);
  203                 if (regp->max_level > 0)
  204                     db_printf("%s%d%*s", regp->name, i, 
  205                                 12-strlen(regp->name)-((i<10)?1:2), "");
  206                 else
  207                     db_printf("%-12s", regp->name);
  208                 db_printf("%#*N", 2+2*sizeof(vm_offset_t), value);
  209                 db_find_xtrn_task_sym_and_offset((db_addr_t)value, &name, 
  210                                                         &offset, task);
  211                 if (name != 0 && offset <= db_maxoff && offset != value) {
  212                     db_printf("\t%s", name);
  213                     if (offset != 0)
  214                         db_printf("+%#r", offset);
  215                 }
  216                 db_printf("\n");
  217             }
  218         }
  219 }
  220 
  221 #define OPTION_LONG             0x001           /* long print option */
  222 #define OPTION_USER             0x002           /* print ps-like stuff */
  223 #define OPTION_INDENT           0x100           /* print with indent */
  224 #define OPTION_THREAD_TITLE     0x200           /* print thread title */
  225 #define OPTION_TASK_TITLE       0x400           /* print thread title */
  226 
  227 #ifndef DB_TASK_NAME
  228 #define DB_TASK_NAME(task)                      /* no task name */
  229 #define DB_TASK_NAME_TITLE      ""              /* no task name */
  230 #endif  DB_TASK_NAME
  231 
  232 #ifndef db_thread_fp_used
  233 #define db_thread_fp_used(thread)       FALSE
  234 #endif
  235 
  236 char *
  237 db_thread_stat(
  238         register thread_t thread,
  239         char     *status)
  240 {
  241         register char *p = status;
  242         
  243         *p++ = (thread->state & TH_RUN)  ? 'R' : '.';
  244         *p++ = (thread->state & TH_WAIT) ? 'W' : '.';
  245         *p++ = (thread->state & TH_SUSP) ? 'S' : '.';
  246         *p++ = (thread->state & TH_SWAPPED) ? 'O' : '.';
  247         *p++ = (thread->state & TH_UNINT) ? 'N' : '.';
  248         /* show if the FPU has been used */
  249         *p++ = db_thread_fp_used(thread) ? 'F' : '.';
  250         *p++ = 0;
  251         return status;
  252 }
  253 
  254 void
  255 db_print_thread(
  256         thread_t thread,
  257         int      thread_id,
  258         int      flag)
  259 {
  260         if (flag & OPTION_USER) {
  261             char status[8];
  262             char *indent = "";
  263 
  264             if (flag & OPTION_LONG) {
  265                 if (flag & OPTION_INDENT)
  266                     indent = "    ";
  267                 if (flag & OPTION_THREAD_TITLE) {
  268                     db_printf("%s ID: THREAD   STAT   STACK    PCB", indent);
  269                     db_printf("      SUS POL PRI CONTINUE,WAIT_FUNC\n");
  270                 }
  271                 db_printf("%s%3d%c %0*X %s %0*X %0*X %3d ",
  272                     indent, thread_id,
  273                     (thread == current_thread())? '#': ':',
  274                     2*sizeof(vm_offset_t), thread,
  275                     db_thread_stat(thread, status),
  276                     2*sizeof(vm_offset_t), thread->kernel_stack,
  277                     2*sizeof(vm_offset_t), thread->pcb,
  278                     thread->suspend_count);
  279                 THREAD_DB_PRINT(thread);        /* pol pri */
  280                 if ((thread->state & TH_SWAPPED) && thread->swap_func) {
  281                     db_task_printsym((db_addr_t)thread->swap_func,
  282                                      DB_STGY_ANY, kernel_task);
  283                     db_printf(", ");
  284                 }
  285                 if (thread->state & TH_WAIT)
  286                     db_task_printsym((db_addr_t)thread->wait_event,
  287                                      DB_STGY_ANY, kernel_task);
  288                 db_printf("\n");
  289             } else {
  290                 if (thread_id % 3 == 0) {
  291                     if (flag & OPTION_INDENT)
  292                         db_printf("\n    ");
  293                 } else
  294                     db_printf(" ");
  295                 db_printf("%3d%c(%0*X,%s)", thread_id, 
  296                     (thread == current_thread())? '#': ':',
  297                     2*sizeof(vm_offset_t), thread,
  298                     db_thread_stat(thread, status));
  299             }
  300         } else {
  301             if (flag & OPTION_INDENT)
  302                 db_printf("            %3d (%0*X) ", thread_id,
  303                           2*sizeof(vm_offset_t), thread);
  304             else
  305                 db_printf("(%0*X) ", 2*sizeof(vm_offset_t), thread);
  306             db_printf("%c%c%c%c%c",
  307                       (thread->state & TH_RUN)  ? 'R' : ' ',
  308                       (thread->state & TH_WAIT) ? 'W' : ' ',
  309                       (thread->state & TH_SUSP) ? 'S' : ' ',
  310                       (thread->state & TH_UNINT)? 'N' : ' ',
  311                       db_thread_fp_used(thread) ? 'F' : ' ');
  312             if (thread->state & TH_SWAPPED) {
  313                 if (thread->swap_func) {
  314                     db_printf("(");
  315                     db_task_printsym((db_addr_t)thread->swap_func, 
  316                                      DB_STGY_ANY, kernel_task);
  317                     db_printf(")");
  318                 } else {
  319                     db_printf("(swapped)");
  320                 }
  321             }
  322             if (thread->state & TH_WAIT) {
  323                 db_printf(" ");
  324                 db_task_printsym((db_addr_t)thread->wait_event, 
  325                             DB_STGY_ANY, kernel_task);
  326             }
  327             db_printf("\n");
  328         }
  329 }
  330 
  331 void
  332 db_print_task(
  333         task_t  task,
  334         int     task_id,
  335         int     flag)
  336 {
  337         thread_t thread;
  338         int thread_id;
  339 
  340         if (flag & OPTION_USER) {
  341             if (flag & OPTION_TASK_TITLE) {
  342                 db_printf(" ID: TASK     MAP      THD SUS %s",
  343                           DB_TASK_NAME_TITLE);
  344                 if ((flag & OPTION_LONG) == 0)
  345                     db_printf("  THREADS");
  346                 db_printf("\n");
  347             }
  348             db_printf("%3d: %0*X %0*X %3d %3d ",
  349                             task_id, 2*sizeof(vm_offset_t), task,
  350                             2*sizeof(vm_offset_t), task->map,
  351                             task->thread_count,
  352                             task->suspend_count);
  353             DB_TASK_NAME(task);
  354             if (flag & OPTION_LONG) {
  355                 if (flag & OPTION_TASK_TITLE)
  356                     flag |= OPTION_THREAD_TITLE;
  357                 db_printf("\n");
  358             } else if (task->thread_count <= 1)
  359                 flag &= ~OPTION_INDENT;
  360             thread_id = 0;
  361             queue_iterate(&task->thread_list, thread, thread_t, thread_list) {
  362                 db_print_thread(thread, thread_id, flag);
  363                 flag &= ~OPTION_THREAD_TITLE;
  364                 thread_id++;
  365             }
  366             if ((flag & OPTION_LONG) == 0)
  367                 db_printf("\n");
  368         } else {
  369             if (flag & OPTION_TASK_TITLE)
  370                 db_printf("    TASK        THREADS\n");
  371             db_printf("%3d (%0*X): ", task_id, 2*sizeof(vm_offset_t), task);
  372             if (task->thread_count == 0) {
  373                 db_printf("no threads\n");
  374             } else {
  375                 if (task->thread_count > 1) {
  376                     db_printf("%d threads: \n", task->thread_count);
  377                     flag |= OPTION_INDENT;
  378                 } else
  379                     flag &= ~OPTION_INDENT;
  380                 thread_id = 0;
  381                 queue_iterate(&task->thread_list, thread,
  382                               thread_t, thread_list)
  383                     db_print_thread(thread, thread_id++, flag);
  384             }
  385         }
  386 }
  387 
  388 /*ARGSUSED*/
  389 void
  390 db_show_all_threads(
  391         db_expr_t       addr,
  392         boolean_t       have_addr,
  393         db_expr_t       count,
  394         char *          modif)
  395 {
  396         task_t task;
  397         int task_id;
  398         int flag;
  399         processor_set_t pset;
  400 
  401         flag = OPTION_TASK_TITLE|OPTION_INDENT;
  402         if (db_option(modif, 'u'))
  403             flag |= OPTION_USER;
  404         if (db_option(modif, 'l'))
  405             flag |= OPTION_LONG;
  406 
  407         task_id = 0;
  408         queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
  409             queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
  410                 db_print_task(task, task_id, flag);
  411                 flag &= ~OPTION_TASK_TITLE;
  412                 task_id++;
  413             }
  414         }
  415 }
  416 
  417 /*ARGSUSED*/
  418 void
  419 db_show_one_thread(
  420         db_expr_t       addr,
  421         boolean_t       have_addr,
  422         db_expr_t       count,
  423         char *          modif)
  424 {
  425         int             flag;
  426         int             thread_id;
  427         thread_t        thread;
  428 
  429         flag = OPTION_THREAD_TITLE;
  430         if (db_option(modif, 'u'))
  431             flag |= OPTION_USER;
  432         if (db_option(modif, 'l'))
  433             flag |= OPTION_LONG;
  434 
  435         if (!have_addr) {
  436             thread = current_thread();
  437             if (thread == THREAD_NULL) {
  438                 db_error("No thread\n");
  439                 /*NOTREACHED*/
  440             }
  441         } else
  442             thread = (thread_t) addr;
  443 
  444         if ((thread_id = db_lookup_thread(thread)) < 0) {
  445             db_printf("bad thread address %#X\n", addr);
  446             db_error(0);
  447             /*NOTREACHED*/
  448         }
  449 
  450         if (flag & OPTION_USER) {
  451             db_printf("TASK%d(%0*X):\n",
  452                       db_lookup_task(thread->task),
  453                       2*sizeof(vm_offset_t), thread->task);
  454             db_print_thread(thread, thread_id, flag);
  455         } else {
  456             db_printf("task %d(%0*X): thread %d",
  457                       db_lookup_task(thread->task),
  458                       2*sizeof(vm_offset_t), thread->task, thread_id);
  459             db_print_thread(thread, thread_id, flag);
  460         }
  461 }
  462 
  463 /*ARGSUSED*/
  464 void
  465 db_show_one_task(
  466         db_expr_t       addr,
  467         boolean_t       have_addr,
  468         db_expr_t       count,
  469         char *          modif)
  470 {
  471         int             flag;
  472         int             task_id;
  473         task_t          task;
  474 
  475         flag = OPTION_TASK_TITLE;
  476         if (db_option(modif, 'u'))
  477             flag |= OPTION_USER;
  478         if (db_option(modif, 'l'))
  479             flag |= OPTION_LONG;
  480 
  481         if (!have_addr) {
  482             task = db_current_task();
  483             if (task == TASK_NULL) {
  484                 db_error("No task\n");
  485                 /*NOTREACHED*/
  486             }
  487         } else
  488             task = (task_t) addr;
  489 
  490         if ((task_id = db_lookup_task(task)) < 0) {
  491             db_printf("bad task address %#X\n", addr);
  492             db_error(0);
  493             /*NOTREACHED*/
  494         }
  495 
  496         db_print_task(task, task_id, flag);
  497 }
  498 
  499 int
  500 db_port_iterate(
  501         thread_t thread,
  502         void (*func)(int, ipc_port_t, unsigned int, int) )
  503 {
  504         ipc_entry_t entry;
  505         int index;
  506         int n = 0;
  507         int size;
  508         ipc_space_t space;
  509 
  510         space = thread->task->itk_space;
  511         entry = space->is_table;
  512         size = space->is_table_size;
  513         for (index = 0; index < size; index++, entry++) {
  514             if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
  515                 (*func)(index, (ipc_port_t) entry->ie_object,
  516                         entry->ie_bits, n++);
  517         }
  518         return n;
  519 }
  520 
  521 ipc_port_t
  522 db_lookup_port(
  523         thread_t thread,
  524         int id)
  525 {
  526         register ipc_space_t space;
  527         register ipc_entry_t entry;
  528 
  529         if (thread == THREAD_NULL)
  530             return 0;
  531         space = thread->task->itk_space;
  532         if (id < 0 || id >= space->is_table_size)
  533             return 0;
  534         entry = &space->is_table[id];
  535         if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
  536             return((ipc_port_t)entry->ie_object);
  537         return 0;
  538 }
  539 
  540 static void
  541 db_print_port_id(
  542         int id,
  543         ipc_port_t port,
  544         unsigned bits,
  545         int n)
  546 {
  547         if (n != 0 && n % 3 == 0)
  548             db_printf("\n");
  549         db_printf("\tport%d(%s,%x)", id,
  550                 (bits & MACH_PORT_TYPE_RECEIVE)? "r":
  551                 (bits & MACH_PORT_TYPE_SEND)? "s": "S", port);
  552 }
  553 
  554 /* ARGSUSED */
  555 void
  556 db_show_port_id(
  557         db_expr_t       addr,
  558         boolean_t       have_addr,
  559         db_expr_t       count,
  560         char *          modif)
  561 {
  562         thread_t thread;
  563 
  564         if (!have_addr) {
  565             thread = current_thread();
  566             if (thread == THREAD_NULL) {
  567                 db_error("No thread\n");
  568                 /*NOTREACHED*/
  569             }
  570         } else
  571             thread = (thread_t) addr;
  572         if (db_lookup_thread(thread) < 0) {
  573             db_printf("Bad thread address %#X\n", addr);
  574             db_error(0);
  575             /*NOTREACHED*/
  576         }
  577         if (db_port_iterate(thread, db_print_port_id))
  578             db_printf("\n");
  579 }

Cache object: 88daafed5e5642b9871615171b9eed06


[ 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.