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

Cache object: 440fd43c4294701d0ad7502cd23f49b2


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