]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ddb/orig/db_print.c
xnu-344.49.tar.gz
[apple/xnu.git] / osfmk / ddb / orig / db_print.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
26 * @OSF_COPYRIGHT@
27 */
28/*
29 * HISTORY
30 *
31 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
32 * Import of Mac OS X kernel (~semeria)
33 *
34 * Revision 1.2 1998/04/29 17:35:25 mburg
35 * MK7.3 merger
36 *
37 * Revision 1.2.85.1 1998/02/03 09:24:09 gdt
38 * Merge up to MK7.3
39 * [1998/02/03 09:10:24 gdt]
40 *
41 * Revision 1.2.81.1 1997/03/27 18:46:38 barbou
42 * ri-osc CR1565 - clean up db_print_act, removing old !USER code
43 * which had gotten stale (the option made little sense here anyway).
44 * Added routine db_show_one_thread() to take either act/shuttle and
45 * do something sensible. [dwm] Also rationalize plain, /u and /l
46 * output for "show act", "show task" and "show all acts".
47 * [1995/08/28 15:47:00 bolinger]
48 * [97/02/25 barbou]
49 *
50 * Revision 1.2.31.13 1996/01/09 19:16:02 devrcs
51 * Alpha kdebug Changes:
52 * Correct various header spacing to account for 64-bit addresses.
53 * Modify db_show_all_*() functions, so the can be called from kdebug.
54 * ( There's no way to call with "char *modif", so added NULL check. )
55 * Changed db_error() calls to DB_ERROR() macro, so we return on error
56 * on Alpha (we gotta return to kdebug).
57 * Changed declarations of 'register foo' to 'register int foo'.
58 * [1995/12/01 21:42:20 jfraser]
59 *
60 * Merged '64-bit safe' changes from DEC alpha port.
61 * [1995/11/21 18:03:24 jfraser]
62 *
63 * Revision 1.2.31.12 1995/10/09 17:03:30 devrcs
64 * Merge forward.
65 * [1995/08/24 20:56:42 watkins]
66 *
67 * Revision 1.2.59.1 1995/08/04 17:03:17 watkins
68 * Change to stack per shuttle model.
69 * [1995/07/19 20:26:13 watkins]
70 *
71 * Revision 1.2.31.11 1995/09/18 19:08:49 devrcs
72 * Merge forward.
73 * [1995/08/24 20:56:42 watkins]
74 *
75 * Revision 1.2.59.1 1995/08/04 17:03:17 watkins
76 * Change to stack per shuttle model.
77 * [1995/07/19 20:26:13 watkins]
78 *
79 * Revision 1.2.31.10 1995/05/19 15:43:04 bernadat
80 * Fixed db_print_act for empty activations.
81 * Let thread swapping be configurable.
82 * [95/05/19 bernadat]
83 *
84 * Revision 1.2.31.9 1995/05/14 18:10:25 dwm
85 * ri-osc CR1304 - merge (nmk19_latest - nmk19b1) diffs into mainline.
86 * mk6 CR938 - restore mach_msg hot path
87 * remove use of now-defunct fields in thread [mmp,dwm]
88 * [1995/05/14 17:25:05 dwm]
89 *
90 * Revision 1.2.31.8 1995/04/07 18:53:00 barbou
91 * VM Merge - Task Swapper.
92 * Renamed TH_SWAPPED to TH_STACK_HANDOFF and swap_func to continuation
93 * to resolve name conflict.
94 * From kernel/kdb/kdb_mach.c:
95 * Put in changes for swapping.
96 * [1991/11/21 20:32:15 mmp]
97 * [94/07/27 barbou]
98 * [95/03/08 barbou]
99 *
100 * Revision 1.2.31.7 1995/02/28 01:58:38 dwm
101 * mk6 CR1120 - Merge mk6pro_shared into cnmk_shared
102 * * Rev1.2.43.1 1995/01/27 22:01:26 bolinger
103 * * Fix ri-osc CR977: Make "show space" and "show ipc_port" give
104 * * accurate count of ports active in IPC space. Make "show ipc_port"
105 * * output task-visible port name.
106 * [1995/02/28 01:12:46 dwm]
107 *
108 * Revision 1.2.31.6 1995/02/23 21:43:34 alanl
109 * Fix db_show_one_task_vm for thread_act_ts.
110 * [95/01/09 rwd]
111 *
112 * Merged with DIPC2_SHARED.
113 * [95/01/04 alanl]
114 *
115 * Revision 1.2.31.5 1995/01/10 04:49:52 devrcs
116 * mk6 CR801 - merge up from nmk18b4 to nmk18b7
117 * Fix "sh thr/ul"; no cont. to print, fix pri/policy format.
118 * * Rev 1.2.31.4 1994/10/11 16:35:58 emcmanus
119 * Added "show runq" and "show shuttle".
120 * [1994/12/09 20:36:49 dwm]
121 *
122 * mk6 CR668 - 1.3b26 merge
123 * * Revision 1.2.8.6 1994/05/06 18:39:37 tmt
124 * Merged osc1.3dec/shared with osc1.3b19
125 * Merge Alpha changes into osc1.312b source code.
126 * 64bit cleanup.
127 * * End1.3merge
128 * [1994/11/04 08:49:52 dwm]
129 *
130 * Revision 1.2.31.3 1994/09/23 01:20:51 ezf
131 * change marker to not FREE
132 * [1994/09/22 21:10:41 ezf]
133 *
134 * Revision 1.2.31.2 1994/06/14 17:21:05 bolinger
135 * Merge up to NMK17.2.
136 * [1994/06/14 17:20:35 bolinger]
137 *
138 * Revision 1.2.23.4 1994/04/15 18:41:31 paire
139 * Changed interface of db_task_from_space routine.
140 * [94/03/31 paire]
141 *
142 * Revision 1.2.23.3 1994/03/07 16:37:48 paire
143 * Merge with Intel R1_1
144 * Change from NMK14.10 [1993/11/15 16:06:21 rwd]
145 *
146 * Enhanced pretty print routine and added db_task_from_space.
147 * Change from NMK14.10 [93/09/24 sjs]
148 * [94/02/21 paire]
149 *
150 * Exported ANSI prototype of db_port_kmsg_count routine.
151 * Added header file include for the declaration of db_norma_ipc routine.
152 * [94/02/15 paire]
153 *
154 * Revision 1.2.23.2 1994/02/11 14:21:58 paire
155 * Added new vm_print.h header file for db_vm declaration.
156 * [94/02/09 paire]
157 *
158 * Revision 1.2.23.1 1994/02/08 10:58:19 bernadat
159 * print out msgcount for each port in db_port_iterate
160 * Change from NORMA_MK14.6(August 93) [1993/07/27 12:35:17 mmp]
161 *
162 * Removed defintion of db_maxoff (got from <ddb/db_sym.h>).
163 * [93/08/12 paire]
164 *
165 * Show ipc_space_remote msg counts only if NORMA_IPC is on
166 * [93/07/21 bernadat]
167 *
168 * Add /s option to "show ipc_port" to pick out port sets.
169 * Change from NORMA_MK14.6 [1993/02/17 16:29:54 dwm]
170 * [93/07/16 bernadat]
171 * [94/02/07 bernadat]
172 *
173 * Revision 1.2.20.8 1994/06/08 19:11:15 dswartz
174 * Preemption merge.
175 * [1994/06/08 19:10:18 dswartz]
176 *
177 * Revision 1.2.20.7 1994/04/30 21:28:24 bolinger
178 * Thread control ops synchronization: now that TH_SUSP is back,
179 * enable ddb to show it when printing thread state.
180 * [1994/04/28 21:55:42 bolinger]
181 *
182 * Revision 1.2.20.6 1994/03/17 22:35:31 dwm
183 * The infamous name change: thread_activation + thread_shuttle = thread.
184 * [1994/03/17 21:25:46 dwm]
185 *
186 * Revision 1.2.20.5 1994/01/26 15:43:37 bolinger
187 * Move kernel_stack from thread to activation.
188 * [1994/01/25 21:53:11 bolinger]
189 *
190 * Revision 1.2.20.4 1994/01/12 17:50:44 dwm
191 * Coloc: initial restructuring to follow Utah model.
192 * [1994/01/12 17:13:12 dwm]
193 *
194 * Revision 1.2.20.3 1993/11/18 18:11:47 dwm
195 * Coloc: remove continuations entirely; they are incompatible
196 * with migration, and their volume is obfuscatory.
197 * [1993/11/18 18:06:27 dwm]
198 *
199 * Revision 1.2.20.2 1993/10/12 16:38:50 dwm
200 * CoLoc: neuter continuations, ifdef USE_CONTINUATIONS.
201 * [1993/10/12 16:14:46 dwm]
202 *
203 * Revision 1.2.8.4 1993/08/11 20:38:06 elliston
204 * Add ANSI Prototypes. CR #9523.
205 * [1993/08/11 03:33:51 elliston]
206 *
207 * Revision 1.2.8.3 1993/07/27 18:27:55 elliston
208 * Add ANSI prototypes. CR #9523.
209 * [1993/07/27 18:12:39 elliston]
210 *
211 * Revision 1.2.8.2 1993/06/09 02:20:35 gm
212 * CR9176 - ANSI C violations: trailing tokens on CPP
213 * directives, extra semicolons after decl_ ..., asm keywords
214 * [1993/06/07 18:57:22 jeffc]
215 *
216 * Removed a '#if MACH_FIXPRI' which somehow survived the purge. CR #9131.
217 * [1993/05/11 20:56:00 dswartz]
218 *
219 * Revision 1.2 1993/04/19 16:02:50 devrcs
220 * Added printout of thread scheduling policy to long form
221 * of thread display.
222 * [93/01/28 jat]
223 *
224 * Changes from mk78:
225 * Removed unused variable from db_show_regs().
226 * [92/05/16 jfriedl]
227 * Converted some db_printsyms to db_task_printsyms.
228 * [92/04/10 danner]
229 * Changed db_print_thread so that both display formats
230 * show the floating-point-used status of the thread.
231 * [92/03/16 rpd]
232 * [93/02/02 bruel]
233 *
234 * Revision 1.1 1992/09/30 02:01:18 robert
235 * Initial revision
236 *
237 * $EndLog$
238 */
239/* CMU_HIST */
240/*
241 * Revision 2.11.3.2 92/04/08 15:43:10 jeffreyh
242 * Added i option to show thread. This gives wait state information.
243 * [92/04/08 sjs]
244 *
245 * Revision 2.11.3.1 92/03/03 16:13:34 jeffreyh
246 * Pick up changes from TRUNK
247 * [92/02/26 11:00:01 jeffreyh]
248 *
249 * Revision 2.13 92/02/20 18:34:28 elf
250 * Fixed typo.
251 * [92/02/20 elf]
252 *
253 * Revision 2.12 92/02/19 15:07:47 elf
254 * Added db_thread_fp_used, to avoid machine-dependent conditionals.
255 * [92/02/19 rpd]
256 *
257 * Added 'F' flag to db_thread_stat showing if the thread has a valid
258 * FPU context. Tested on i386 and pmax.
259 * [92/02/17 kivinen]
260 *
261 * Revision 2.11 91/11/12 11:50:32 rvb
262 * Added OPTION_USER ("/u") to db_show_all_threads, db_show_one_thread,
263 * db_show_one_task. Without it, we display old-style information.
264 * [91/10/31 rpd]
265 *
266 * Revision 2.10 91/10/09 16:01:48 af
267 * Supported "show registers" for non current thread.
268 * Changed display format of thread and task information.
269 * Changed "show thread" to print current thread information
270 * if no thread is specified.
271 * Added "show_one_task" for "show task" command.
272 * Added IPC port print routines for "show ipc_port" command.
273 * [91/08/29 tak]
274 *
275 * Revision 2.9 91/08/03 18:17:19 jsb
276 * In db_print_thread, if the thread is swapped and there is a
277 * continuation function, print the function name in parentheses
278 * instead of '(swapped)'.
279 * [91/07/04 09:59:27 jsb]
280 *
281 * Revision 2.8 91/07/31 17:30:43 dbg
282 * Revise scheduling state machine.
283 * [91/07/30 16:43:42 dbg]
284 *
285 * Revision 2.7 91/07/09 23:15:57 danner
286 * Fixed a few printf that should be db_printfs.
287 * [91/07/08 danner]
288 *
289 * Revision 2.6 91/05/14 15:35:25 mrt
290 * Correcting copyright
291 *
292 * Revision 2.5 91/02/05 17:06:53 mrt
293 * Changed to new Mach copyright
294 * [91/01/31 16:18:56 mrt]
295 *
296 * Revision 2.4 90/10/25 14:43:54 rwd
297 * Changed db_show_regs to print unsigned.
298 * [90/10/19 rpd]
299 * Generalized the watchpoint support.
300 * [90/10/16 rwd]
301 *
302 * Revision 2.3 90/09/09 23:19:52 rpd
303 * Avoid totally incorrect guesses of symbol names for small values.
304 * [90/08/30 17:39:08 af]
305 *
306 * Revision 2.2 90/08/27 21:51:49 dbg
307 * Insist that 'show thread' be called with an explicit address.
308 * [90/08/22 dbg]
309 *
310 * Fix type for db_maxoff.
311 * [90/08/20 dbg]
312 *
313 * Do not dereference the "valuep" field of a variable directly,
314 * call the new db_read/write_variable functions instead.
315 * Reflected changes in symbol lookup functions.
316 * [90/08/20 af]
317 * Reduce lint.
318 * [90/08/10 14:33:44 dbg]
319 *
320 * Created.
321 * [90/07/25 dbg]
322 *
323 */
324/* CMU_ENDHIST */
325/*
326 * Mach Operating System
327 * Copyright (c) 1991,1990 Carnegie Mellon University
328 * All Rights Reserved.
329 *
330 * Permission to use, copy, modify and distribute this software and its
331 * documentation is hereby granted, provided that both the copyright
332 * notice and this permission notice appear in all copies of the
333 * software, derivative works or modified versions, and any portions
334 * thereof, and that both notices appear in supporting documentation.
335 *
336 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
337 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
338 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
339 *
340 * Carnegie Mellon requests users of this software to return to
341 *
342 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
343 * School of Computer Science
344 * Carnegie Mellon University
345 * Pittsburgh PA 15213-3890
346 *
347 * any improvements or extensions that they make and grant Carnegie Mellon
348 * the rights to redistribute these changes.
349 */
350/*
351 */
352/*
353 * Author: David B. Golub, Carnegie Mellon University
354 * Date: 7/90
355 */
356
357/*
358 * Miscellaneous printing.
359 */
360#include <dipc.h>
361#include <task_swapper.h>
362
363#include <string.h> /* For strlen() */
364#include <mach/port.h>
365#include <kern/task.h>
366#include <kern/thread.h>
367#include <kern/thread_swap.h>
368#include <kern/queue.h>
369#include <ipc/ipc_port.h>
370#include <ipc/ipc_space.h>
371#include <ipc/ipc_pset.h>
372#include <vm/vm_print.h> /* for db_vm() */
373
374#include <machine/db_machdep.h>
375#include <machine/thread.h>
376
377#include <ddb/db_lex.h>
378#include <ddb/db_variables.h>
379#include <ddb/db_sym.h>
380#include <ddb/db_task_thread.h>
381#include <ddb/db_command.h>
382#include <ddb/db_output.h> /* For db_printf() */
383#include <ddb/db_print.h>
384
385#include <kern/sf.h>
386#include <kern/sp_mk.h> /*** ??? fix so this can be removed ***/
387
388#if TASK_SWAPPER
389#include <kern/task_swap.h>
390#endif /* TASK_SWAPPER */
391
392/* Prototypes for functions local to this file. XXX -- should be static!
393 */
394
395char *db_act_stat(
396 register thread_act_t thr_act,
397 char *status);
398
399char *db_act_swap_stat(
400 register thread_act_t thr_act,
401 char *status);
402
403void db_print_task(
404 task_t task,
405 int task_id,
406 int flag);
407
408void db_reset_print_entry(
409 void);
410
411void db_print_one_entry(
412 ipc_entry_t entry,
413 int index,
414 mach_port_name_t name,
415 boolean_t is_pset);
416
417int db_port_iterate(
418 thread_act_t thr_act,
419 boolean_t is_pset,
420 boolean_t do_output);
421
422ipc_port_t db_lookup_port(
423 thread_act_t thr_act,
424 int id);
425
426static void db_print_port_id(
427 int id,
428 ipc_port_t port,
429 unsigned bits,
430 int n);
431
432void db_print_act(
433 thread_act_t thr_act,
434 int act_id,
435 int flag);
436
437void db_print_space(
438 task_t task,
439 int task_id,
440 int flag);
441
442void db_print_task_vm(
443 task_t task,
444 int task_id,
445 boolean_t title,
446 char *modif);
447
448void db_system_stats(void);
449
450
451void
452db_show_regs(
453 db_expr_t addr,
454 boolean_t have_addr,
455 db_expr_t count,
456 char *modif)
457{
458 register struct db_variable *regp;
459 db_expr_t value;
460 db_addr_t offset;
461 char * name;
462 register int i;
463 struct db_var_aux_param aux_param;
464 task_t task = TASK_NULL;
465
466 aux_param.modif = modif;
467 aux_param.thr_act = THR_ACT_NULL;
468 if (db_option(modif, 't')) {
469 if (have_addr) {
470 if (!db_check_act_address_valid((thread_act_t)addr))
471 return;
472 aux_param.thr_act = (thread_act_t)addr;
473 } else
474 aux_param.thr_act = db_default_act;
475 if (aux_param.thr_act != THR_ACT_NULL)
476 task = aux_param.thr_act->task;
477 }
478 for (regp = db_regs; regp < db_eregs; regp++) {
479 if (regp->max_level > 1) {
480 db_printf("bad multi-suffixed register %s\n", regp->name);
481 continue;
482 }
483 aux_param.level = regp->max_level;
484 for (i = regp->low; i <= regp->high; i++) {
485 aux_param.suffix[0] = i;
486 db_read_write_variable(regp, &value, DB_VAR_GET, &aux_param);
487 if (regp->max_level > 0)
488 db_printf("%s%d%*s", regp->name, i,
489 12-strlen(regp->name)-((i<10)?1:2), "");
490 else
491 db_printf("%-12s", regp->name);
492 db_printf("%#*N", 2+2*sizeof(vm_offset_t), value);
493 db_find_xtrn_task_sym_and_offset((db_addr_t)value, &name,
494 &offset, task);
495 if (name != 0 && offset <= db_maxoff && offset != value) {
496 db_printf("\t%s", name);
497 if (offset != 0)
498 db_printf("+%#r", offset);
499 }
500 db_printf("\n");
501 }
502 }
503}
504
505#define OPTION_LONG 0x001 /* long print option */
506#define OPTION_USER 0x002 /* print ps-like stuff */
507#define OPTION_INDENT 0x100 /* print with indent */
508#define OPTION_THREAD_TITLE 0x200 /* print thread title */
509#define OPTION_TASK_TITLE 0x400 /* print thread title */
510
511#ifndef DB_TASK_NAME
512#define DB_TASK_NAME(task) /* no task name */
513#define DB_TASK_NAME_TITLE "" /* no task name */
514#endif /* DB_TASK_NAME */
515
516#ifndef db_act_fp_used
517#define db_act_fp_used(thr_act) FALSE
518#endif
519
520char *
521db_act_stat(
522 register thread_act_t thr_act,
523 char *status)
524{
525 register char *p = status;
526
527 if (!thr_act->active) {
528 *p++ = 'D',
529 *p++ = 'y',
530 *p++ = 'i',
531 *p++ = 'n',
532 *p++ = 'g';
533 *p++ = ' ';
534 } else if (!thr_act->thread) {
535 *p++ = 'E',
536 *p++ = 'm',
537 *p++ = 'p',
538 *p++ = 't',
539 *p++ = 'y';
540 *p++ = ' ';
541 } else {
542 thread_t athread = thr_act->thread;
543
544 *p++ = (athread->state & TH_RUN) ? 'R' : '.';
545 *p++ = (athread->state & TH_WAIT) ? 'W' : '.';
546 *p++ = (athread->state & TH_SUSP) ? 'S' : '.';
547 *p++ = (athread->state & TH_SWAPPED_OUT) ? 'O' : '.';
548 *p++ = (athread->state & TH_UNINT) ? 'N' : '.';
549 /* show if the FPU has been used */
550 *p++ = db_act_fp_used(thr_act) ? 'F' : '.';
551 }
552 *p++ = 0;
553 return(status);
554}
555
556char *
557db_act_swap_stat(
558 register thread_act_t thr_act,
559 char *status)
560{
561 register char *p = status;
562
563#if THREAD_SWAPPER
564 switch (thr_act->swap_state & TH_SW_STATE) {
565 case TH_SW_UNSWAPPABLE:
566 *p++ = 'U';
567 break;
568 case TH_SW_IN:
569 *p++ = 'I';
570 break;
571 case TH_SW_GOING_OUT:
572 *p++ = 'G';
573 break;
574 case TH_SW_WANT_IN:
575 *p++ = 'W';
576 break;
577 case TH_SW_OUT:
578 *p++ = 'O';
579 break;
580 case TH_SW_COMING_IN:
581 *p++ = 'C';
582 break;
583 default:
584 *p++ = '?';
585 break;
586 }
587 *p++ = (thr_act->swap_state & TH_SW_TASK_SWAPPING) ? 'T' : '.';
588#endif /* THREAD_SWAPPER */
589 *p++ = 0;
590
591 return status;
592}
593
594char *policy_list[] = { "TS", "RR", "??", "FF",
595 "??", "??", "??", "BE"};
596
597void
598db_print_act(
599 thread_act_t thr_act,
600 int act_id,
601 int flag)
602{
603 thread_t athread;
604 char status[8];
605 char swap_status[3];
606 char *indent = "";
607 int policy;
608
609 if (!thr_act) {
610 db_printf("db_print_act(NULL)!\n");
611 return;
612 }
613
614 athread = thr_act->thread;
615 if (flag & OPTION_USER) {
616
617 if (flag & OPTION_LONG) {
618 if (flag & OPTION_INDENT)
619 indent = " ";
620 if (flag & OPTION_THREAD_TITLE) {
621 db_printf("%s ID: ACT STAT SW STACK SHUTTLE", indent);
622 db_printf(" SUS PRI WAIT_FUNC\n");
623 }
624 policy = (athread ? athread->policy : 2);
625 db_printf("%s%3d%c %0*X %s %s %0*X %0*X %3d %3d/%s ",
626 indent, act_id,
627 (thr_act == current_act())? '#': ':',
628 2*sizeof(vm_offset_t), thr_act,
629 db_act_stat(thr_act, status),
630 db_act_swap_stat(thr_act, swap_status),
631 2*sizeof(vm_offset_t), (athread ?athread->kernel_stack:0),
632 2*sizeof(vm_offset_t), athread,
633 thr_act->suspend_count,
634 (athread ? athread->sched_pri : 999), /* XXX */
635 policy_list[policy-1]);
636 if (athread) {
637 /* no longer TH_SWAP, no continuation to print */
638 if (athread->state & TH_WAIT)
639 db_task_printsym((db_addr_t)athread->wait_event,
640 DB_STGY_ANY, kernel_task);
641 }
642 db_printf("\n");
643 } else {
644 if (act_id % 3 == 0) {
645 if (flag & OPTION_INDENT)
646 db_printf("\n ");
647 } else
648 db_printf(" ");
649 db_printf("%3d%c(%0*X,%s)", act_id,
650 (thr_act == current_act())? '#': ':',
651 2*sizeof(vm_offset_t), thr_act,
652 db_act_stat(thr_act, status));
653 }
654 } else {
655 if (flag & OPTION_INDENT)
656 db_printf(" %3d (%0*X) ", act_id,
657 2*sizeof(vm_offset_t), thr_act);
658 else
659 db_printf("(%0*X) ", 2*sizeof(vm_offset_t), thr_act);
660 if (athread) {
661 db_printf("%c%c%c%c%c",
662 (athread->state & TH_RUN) ? 'R' : ' ',
663 (athread->state & TH_WAIT) ? 'W' : ' ',
664 (athread->state & TH_SUSP) ? 'S' : ' ',
665 (athread->state & TH_UNINT)? 'N' : ' ',
666 db_act_fp_used(thr_act) ? 'F' : ' ');
667 /* Obsolete TH_STACK_HANDOFF code, left for now; might enhance
668 * to print out safe_points instead */
669 if (athread->state & TH_STACK_HANDOFF) {
670 if (athread->continuation) {
671 db_printf("(");
672 db_task_printsym((db_addr_t)athread->continuation,
673 DB_STGY_ANY, kernel_task);
674 db_printf(")");
675 } else {
676 db_printf("(handoff)");
677 }
678 }
679 if (athread->state & TH_WAIT) {
680 db_printf(" ");
681 db_task_printsym((db_addr_t)athread->wait_event,
682 DB_STGY_ANY, kernel_task);
683 }
684 } else
685 db_printf("Empty");
686 db_printf("\n");
687 }
688}
689
690void
691db_print_task(
692 task_t task,
693 int task_id,
694 int flag)
695{
696 thread_act_t thr_act;
697 int act_id;
698 char sstate;
699
700 if (flag & OPTION_USER) {
701 if (flag & OPTION_TASK_TITLE) {
702 db_printf(" ID: TASK MAP THD RES SUS PR SW %s",
703 DB_TASK_NAME_TITLE);
704 if ((flag & OPTION_LONG) == 0)
705 db_printf(" ACTS");
706 db_printf("\n");
707 }
708#if TASK_SWAPPER
709 switch ((int) task->swap_state) {
710 case TASK_SW_IN:
711 sstate = 'I';
712 break;
713 case TASK_SW_OUT:
714 sstate = 'O';
715 break;
716 case TASK_SW_GOING_OUT:
717 sstate = 'G';
718 break;
719 case TASK_SW_COMING_IN:
720 sstate = 'C';
721 break;
722 case TASK_SW_UNSWAPPABLE:
723 sstate = 'U';
724 break;
725 default:
726 sstate = '?';
727 break;
728 }
729#else /* TASK_SWAPPER */
730 sstate = 'I';
731#endif /* TASK_SWAPPER */
732 /*** ??? fix me ***/
733 db_printf("%3d: %0*X %0*X %3d %3d %3d %2d %c ",
734 task_id, 2*sizeof(vm_offset_t), task,
735 2*sizeof(vm_offset_t), task->map,
736 task->thr_act_count, task->res_act_count,
737 task->suspend_count,
738 ((mk_sp_attributes_t)(task->sp_attributes))->priority,
739 sstate);
740 DB_TASK_NAME(task);
741 if (flag & OPTION_LONG) {
742 if (flag & OPTION_TASK_TITLE)
743 flag |= OPTION_THREAD_TITLE;
744 db_printf("\n");
745 } else if (task->thr_act_count <= 1)
746 flag &= ~OPTION_INDENT;
747 act_id = 0;
748 queue_iterate(&task->thr_acts, thr_act, thread_act_t, thr_acts) {
749 db_print_act(thr_act, act_id, flag);
750 flag &= ~OPTION_THREAD_TITLE;
751 act_id++;
752 }
753 if ((flag & OPTION_LONG) == 0)
754 db_printf("\n");
755 } else {
756 if (flag & OPTION_LONG) {
757 if (flag & OPTION_TASK_TITLE) {
758 db_printf(" TASK ACT\n");
759 if (task->thr_act_count > 1)
760 flag |= OPTION_THREAD_TITLE;
761 }
762 }
763 db_printf("%3d (%0*X): ", task_id, 2*sizeof(vm_offset_t), task);
764 if (task->thr_act_count == 0) {
765 db_printf("no threads\n");
766 } else {
767 if (task->thr_act_count > 1) {
768 db_printf("%d threads: \n", task->thr_act_count);
769 flag |= OPTION_INDENT;
770 } else
771 flag &= ~OPTION_INDENT;
772 act_id = 0;
773 queue_iterate(&task->thr_acts, thr_act,
774 thread_act_t, thr_acts) {
775 db_print_act(thr_act, act_id++, flag);
776 flag &= ~OPTION_THREAD_TITLE;
777 }
778 }
779 }
780}
781
782void
783db_print_space(
784 task_t task,
785 int task_id,
786 int flag)
787{
788 ipc_space_t space;
789 thread_act_t act = (thread_act_t)queue_first(&task->thr_acts);
790 int count;
791
792 count = 0;
793 space = task->itk_space;
794 if (act)
795 count = db_port_iterate(act, FALSE, FALSE);
796 db_printf("%3d: %08x %08x %08x %sactive %d\n",
797 task_id, task, space, task->map,
798 space->is_active? "":"!", count);
799}
800
801void
802db_print_task_vm(
803 task_t task,
804 int task_id,
805 boolean_t title,
806 char *modif)
807{
808 vm_map_t map;
809 pmap_t pmap;
810 vm_size_t size;
811 long resident;
812 long wired;
813
814 if (title) {
815 db_printf("id task map pmap virtual rss pg rss mem wir pg wir mem\n");
816 }
817
818 map = task->map;
819 pmap = vm_map_pmap(map);
820
821 size = db_vm_map_total_size(map);
822 resident = pmap->stats.resident_count;
823 wired = pmap->stats.wired_count;
824
825 db_printf("%2d %08x %08x %08x %7dK %6d %6dK %6d %6dK\n",
826 task_id,
827 task,
828 map,
829 pmap,
830 size / 1024,
831 resident, (resident * PAGE_SIZE) / 1024,
832 wired, (wired * PAGE_SIZE) / 1024);
833}
834
835
836void
837db_show_one_task_vm(
838 db_expr_t addr,
839 boolean_t have_addr,
840 db_expr_t count,
841 char *modif)
842{
843 thread_act_t thread;
844 task_t task;
845 int task_id;
846
847 if (have_addr == FALSE) {
848 if ((thread = db_default_act) == THR_ACT_NULL) {
849 if ((thread = current_act()) == THR_ACT_NULL) {
850 db_printf("no thread.\n");
851 return;
852 }
853 }
854 task = thread->task;
855 } else {
856 task = (task_t) addr;
857 }
858
859 task_id = db_lookup_task(task);
860 if (task_id < 0) {
861 db_printf("0x%x is not a task_t\n", addr);
862 return;
863 }
864
865 db_print_task_vm(task, task_id, TRUE, modif);
866}
867
868void
869db_show_all_task_vm(
870 db_expr_t addr,
871 boolean_t have_addr,
872 db_expr_t count,
873 char *modif)
874{
875 task_t task;
876 int task_id;
877 boolean_t title = TRUE;
878 processor_set_t pset;
879
880 task_id = 0;
881 queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
882 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
883 db_print_task_vm(task, task_id, title, modif);
884 title = FALSE;
885 task_id++;
886 }
887 }
888}
889
890void
891db_show_all_acts(
892 db_expr_t addr,
893 boolean_t have_addr,
894 db_expr_t count,
895 char * modif)
896{
897 task_t task;
898 int task_id;
899 int flag;
900 processor_set_t pset;
901
902 flag = OPTION_TASK_TITLE|OPTION_INDENT;
903 if (db_option(modif, 'u'))
904 flag |= OPTION_USER;
905 if (db_option(modif, 'l'))
906 flag |= OPTION_LONG;
907
908 task_id = 0;
909 queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
910 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
911 db_print_task(task, task_id, flag);
912 flag &= ~OPTION_TASK_TITLE;
913 task_id++;
914 if ((flag & (OPTION_LONG|OPTION_INDENT)) == OPTION_INDENT)
915 db_printf("\n");
916 }
917 }
918}
919
920void
921db_show_one_space(
922 db_expr_t addr,
923 boolean_t have_addr,
924 db_expr_t count,
925 char * modif)
926{
927 int flag;
928 int task_id;
929 task_t task;
930
931 flag = OPTION_TASK_TITLE;
932 if (db_option(modif, 'u'))
933 flag |= OPTION_USER;
934 if (db_option(modif, 'l'))
935 flag |= OPTION_LONG;
936
937 if (!have_addr) {
938 task = db_current_task();
939 if (task == TASK_NULL) {
940 db_error("No task\n");
941 /*NOTREACHED*/
942 }
943 } else
944 task = (task_t) addr;
945
946 if ((task_id = db_lookup_task(task)) < 0) {
947 db_printf("bad task address 0x%x\n", addr);
948 db_error(0);
949 /*NOTREACHED*/
950 }
951
952 db_printf(" ID: TASK SPACE MAP COUNT\n");
953 db_print_space(task, task_id, flag);
954}
955
956void
957db_show_all_spaces(
958 db_expr_t addr,
959 boolean_t have_addr,
960 db_expr_t count,
961 char * modif)
962{
963 task_t task;
964 int task_id = 0;
965 int flag;
966 processor_set_t pset;
967
968 flag = OPTION_TASK_TITLE|OPTION_INDENT;
969 if (db_option(modif, 'u'))
970 flag |= OPTION_USER;
971 if (db_option(modif, 'l'))
972 flag |= OPTION_LONG;
973
974 db_printf(" ID: TASK SPACE MAP COUNT\n");
975 queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
976 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
977 db_print_space(task, task_id, flag);
978 task_id++;
979 }
980 }
981}
982
983db_addr_t
984db_task_from_space(
985 ipc_space_t space,
986 int *task_id)
987{
988 task_t task;
989 int tid = 0;
990 processor_set_t pset;
991
992 queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
993 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
994 if (task->itk_space == space) {
995 *task_id = tid;
996 return (db_addr_t)task;
997 }
998 tid++;
999 }
1000 }
1001 *task_id = 0;
1002 return (0);
1003}
1004
1005void
1006db_show_one_act(
1007 db_expr_t addr,
1008 boolean_t have_addr,
1009 db_expr_t count,
1010 char * modif)
1011{
1012 int flag;
1013 int act_id;
1014 thread_act_t thr_act;
1015
1016 flag = OPTION_THREAD_TITLE;
1017 if (db_option(modif, 'u'))
1018 flag |= OPTION_USER;
1019 if (db_option(modif, 'l'))
1020 flag |= OPTION_LONG;
1021
1022 if (!have_addr) {
1023 thr_act = current_act();
1024 if (thr_act == THR_ACT_NULL) {
1025 db_error("No thr_act\n");
1026 /*NOTREACHED*/
1027 }
1028 } else
1029 thr_act = (thread_act_t) addr;
1030
1031 if ((act_id = db_lookup_act(thr_act)) < 0) {
1032 db_printf("bad thr_act address %#x\n", addr);
1033 db_error(0);
1034 /*NOTREACHED*/
1035 }
1036
1037 if (flag & OPTION_USER) {
1038 db_printf("TASK%d(%0*X):\n",
1039 db_lookup_task(thr_act->task),
1040 2*sizeof(vm_offset_t), thr_act->task);
1041 db_print_act(thr_act, act_id, flag);
1042 } else {
1043 db_printf("task %d(%0*Xx): thr_act %d",
1044 db_lookup_task(thr_act->task),
1045 2*sizeof(vm_offset_t), thr_act->task, act_id);
1046 db_print_act(thr_act, act_id, flag);
1047 }
1048 if (db_option(modif, 'i') && thr_act->thread &&
1049 (thr_act->thread->state & TH_WAIT) &&
1050 thr_act->thread->kernel_stack == 0) {
1051
1052 db_printf("Wait State: option 0x%x\n",
1053 thr_act->thread->ith_option);
1054 }
1055}
1056
1057void
1058db_show_one_task(
1059 db_expr_t addr,
1060 boolean_t have_addr,
1061 db_expr_t count,
1062 char * modif)
1063{
1064 int flag;
1065 int task_id;
1066 task_t task;
1067
1068 flag = OPTION_TASK_TITLE|OPTION_INDENT;
1069 if (db_option(modif, 'u'))
1070 flag |= OPTION_USER;
1071 if (db_option(modif, 'l'))
1072 flag |= OPTION_LONG;
1073
1074 if (!have_addr) {
1075 task = db_current_task();
1076 if (task == TASK_NULL) {
1077 db_error("No task\n");
1078 /*NOTREACHED*/
1079 }
1080 } else
1081 task = (task_t) addr;
1082
1083 if ((task_id = db_lookup_task(task)) < 0) {
1084 db_printf("bad task address 0x%x\n", addr);
1085 db_error(0);
1086 /*NOTREACHED*/
1087 }
1088
1089 db_print_task(task, task_id, flag);
1090}
1091
1092void
1093db_show_shuttle(
1094 db_expr_t addr,
1095 boolean_t have_addr,
1096 db_expr_t count,
1097 char * modif)
1098{
1099 thread_shuttle_t shuttle;
1100 thread_act_t thr_act;
1101
1102 if (have_addr)
1103 shuttle = (thread_shuttle_t) addr;
1104 else {
1105 thr_act = current_act();
1106 if (thr_act == THR_ACT_NULL) {
1107 db_error("No thr_act\n");
1108 /*NOTREACHED*/
1109 }
1110 shuttle = thr_act->thread;
1111 if (shuttle == THREAD_NULL) {
1112 db_error("No shuttle associated with current thr_act\n");
1113 /*NOTREACHED*/
1114 }
1115 }
1116 db_printf("shuttle %x:\n", shuttle);
1117 if (shuttle->top_act == THR_ACT_NULL)
1118 db_printf(" no activations\n");
1119 else {
1120 db_printf(" activations:");
1121 for (thr_act = shuttle->top_act; thr_act != THR_ACT_NULL;
1122 thr_act = thr_act->lower) {
1123 if (thr_act != shuttle->top_act)
1124 printf(" from");
1125 printf(" $task%d.%d(%x)", db_lookup_task(thr_act->task),
1126 db_lookup_act(thr_act), thr_act);
1127 }
1128 db_printf("\n");
1129 }
1130}
1131
1132#define db_pset_kmsg_count(port) \
1133 (ipc_list_count((port)->ip_pset->ips_messages.imq_messages.ikmq_base))
1134
1135int
1136db_port_kmsg_count(
1137 ipc_port_t port)
1138{
1139 return (port->ip_pset ? db_pset_kmsg_count(port) : port->ip_msgcount);
1140}
1141
1142static int db_print_ent_cnt = 0;
1143
1144void db_reset_print_entry(
1145 void)
1146{
1147 db_print_ent_cnt = 0;
1148}
1149
1150void
1151db_print_one_entry(
1152 ipc_entry_t entry,
1153 int index,
1154 mach_port_t name,
1155 boolean_t is_pset)
1156{
1157 ipc_port_t aport = (ipc_port_t)entry->ie_object;
1158 unsigned bits = entry->ie_bits;
1159
1160 if (is_pset && !aport->ip_pset)
1161 return;
1162 if (db_print_ent_cnt && db_print_ent_cnt % 2 == 0)
1163 db_printf("\n");
1164 if (!name)
1165 db_printf("\t%s%d[%x]",
1166 !is_pset && aport->ip_pset ? "pset" : "port",
1167 index,
1168 MACH_PORT_MAKE(index, IE_BITS_GEN(bits)));
1169 else
1170 db_printf("\t%s[%x]",
1171 !is_pset && aport->ip_pset ? "pset" : "port",
1172 name);
1173 if (!is_pset) {
1174 db_printf("(%s,%x,%d)",
1175 (bits & MACH_PORT_TYPE_RECEIVE)? "r":
1176 (bits & MACH_PORT_TYPE_SEND)? "s": "S",
1177 aport,
1178 db_port_kmsg_count(aport));
1179 db_print_ent_cnt++;
1180 }
1181 else {
1182 db_printf("(%s,%x,set=%x,%d)",
1183 (bits & MACH_PORT_TYPE_RECEIVE)? "r":
1184 (bits & MACH_PORT_TYPE_SEND)? "s": "S",
1185 aport,
1186 aport->ip_pset,
1187 db_pset_kmsg_count(aport));
1188 db_print_ent_cnt++;
1189 }
1190}
1191
1192int
1193db_port_iterate(
1194 thread_act_t thr_act,
1195 boolean_t is_pset,
1196 boolean_t do_output)
1197{
1198 ipc_entry_t entry;
1199 ipc_tree_entry_t tentry;
1200 int index;
1201 int size;
1202 int count;
1203 ipc_space_t space;
1204
1205 count = 0;
1206 space = thr_act->task->itk_space;
1207 entry = space->is_table;
1208 size = space->is_table_size;
1209 db_reset_print_entry();
1210 for (index = 0; index < size; ++index, ++entry) {
1211 if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) {
1212 if (do_output)
1213 db_print_one_entry(entry,
1214 index, (mach_port_t)0, is_pset);
1215 ++count;
1216 }
1217 }
1218 for (tentry = ipc_splay_traverse_start(&space->is_tree);
1219 tentry != ITE_NULL;
1220 tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) {
1221 entry = &tentry->ite_entry;
1222 if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) {
1223 if (do_output)
1224 db_print_one_entry(entry,
1225 0, tentry->ite_name, is_pset);
1226 ++count;
1227 }
1228 }
1229 return (count);
1230}
1231
1232ipc_port_t
1233db_lookup_port(
1234 thread_act_t thr_act,
1235 int id)
1236{
1237 register ipc_space_t space;
1238 register ipc_entry_t entry;
1239
1240 if (thr_act == THR_ACT_NULL)
1241 return(0);
1242 space = thr_act->task->itk_space;
1243 if (id < 0 || id >= space->is_table_size)
1244 return(0);
1245 entry = &space->is_table[id];
1246 if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
1247 return((ipc_port_t)entry->ie_object);
1248 return(0);
1249}
1250
1251static void
1252db_print_port_id(
1253 int id,
1254 ipc_port_t port,
1255 unsigned bits,
1256 int n)
1257{
1258 if (n != 0 && n % 3 == 0)
1259 db_printf("\n");
1260 db_printf("\tport%d(%s,%x)", id,
1261 (bits & MACH_PORT_TYPE_RECEIVE)? "r":
1262 (bits & MACH_PORT_TYPE_SEND)? "s": "S", port);
1263}
1264
1265void
1266db_show_port_id(
1267 db_expr_t addr,
1268 boolean_t have_addr,
1269 db_expr_t count,
1270 char * modif)
1271{
1272 thread_act_t thr_act;
1273
1274 if (!have_addr) {
1275 thr_act = current_act();
1276 if (thr_act == THR_ACT_NULL) {
1277 db_error("No thr_act\n");
1278 /*NOTREACHED*/
1279 }
1280 } else
1281 thr_act = (thread_act_t) addr;
1282 if (db_lookup_act(thr_act) < 0) {
1283 db_printf("Bad thr_act address 0x%x\n", addr);
1284 db_error(0);
1285 /*NOTREACHED*/
1286 }
1287 if (db_port_iterate(thr_act, db_option(modif,'s'), TRUE))
1288 db_printf("\n");
1289}
1290
1291/*
1292 * Useful system state when the world has hung.
1293 */
1294void
1295db_system_stats()
1296{
1297 extern void db_device(void);
1298 extern void db_sched(void);
1299#if DIPC
1300 extern void db_dipc_stats(void);
1301 extern void db_show_kkt(void);
1302#endif /* DIPC */
1303
1304 db_sched();
1305 iprintf("\n");
1306 db_vm();
1307 iprintf("\n");
1308 db_device();
1309#if DIPC
1310 iprintf("\n");
1311 db_dipc_stats();
1312 iprintf("\n");
1313 db_show_kkt();
1314#endif /* DIPC */
1315 iprintf("\n");
1316 db_printf("current_{thread/task} 0x%x 0x%x\n",
1317 current_thread(),current_task());
1318}
1319
1320void db_show_one_runq(run_queue_t runq);
1321
1322void
1323db_show_runq(
1324 db_expr_t addr,
1325 boolean_t have_addr,
1326 db_expr_t count,
1327 char * modif)
1328{
1329 processor_set_t pset;
1330 processor_t proc;
1331 run_queue_t runq;
1332 boolean_t showedany = FALSE;
1333
1334 queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
1335#if NCPUS > 1 /* This code has not been tested. */
1336 queue_iterate(&pset->processors, proc, processor_t, processors) {
1337 runq = &proc->runq;
1338 if (runq->count > 0) {
1339 db_printf("PROCESSOR %x IN SET %x\n", proc, pset);
1340 db_show_one_runq(runq);
1341 showedany = TRUE;
1342 }
1343 }
1344#endif /* NCPUS > 1 */
1345#ifndef NCPUS
1346#error NCPUS undefined
1347#endif
1348 runq = &pset->runq;
1349 if (runq->count > 0) {
1350 db_printf("PROCESSOR SET %x\n", pset);
1351 db_show_one_runq(runq);
1352 showedany = TRUE;
1353 }
1354 }
1355 if (!showedany)
1356 db_printf("No runnable threads\n");
1357}
1358
1359void
1360db_show_one_runq(
1361 run_queue_t runq)
1362{
1363 int i, task_id, thr_act_id;
1364 queue_t q;
1365 thread_act_t thr_act;
1366 thread_t thread;
1367 task_t task;
1368
1369 printf("PRI TASK.ACTIVATION\n");
1370 for (i = runq->low, q = runq->runq + i; i < NRQS; i++, q++) {
1371 if (!queue_empty(q)) {
1372 db_printf("%3d:", i);
1373 queue_iterate(q, thread, thread_t, links) {
1374 thr_act = thread->top_act;
1375 task = thr_act->task;
1376 task_id = db_lookup_task(task);
1377 thr_act_id = db_lookup_task_act(task, thr_act);
1378 db_printf(" %d.%d", task_id, thr_act_id);
1379 }
1380 db_printf("\n");
1381 }
1382 }
1383}