]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ddb/db_print.c
xnu-344.23.tar.gz
[apple/xnu.git] / osfmk / ddb / db_print.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
de355530
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
de355530
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
de355530
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_COPYRIGHT@
24 */
25/*
26 * Mach Operating System
27 * Copyright (c) 1991,1990 Carnegie Mellon University
28 * All Rights Reserved.
29 *
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
35 *
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39 *
40 * Carnegie Mellon requests users of this software to return to
41 *
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
46 *
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
49 */
50/*
51 */
52/*
53 * Author: David B. Golub, Carnegie Mellon University
54 * Date: 7/90
55 */
56
57/*
58 * Miscellaneous printing.
59 */
60#include <task_swapper.h>
61
62#include <string.h> /* For strlen() */
63#include <mach/port.h>
64#include <kern/task.h>
65#include <kern/thread.h>
66#include <kern/thread_swap.h>
67#include <kern/queue.h>
68#include <kern/processor.h>
69#include <ipc/ipc_port.h>
70#include <ipc/ipc_space.h>
71#include <ipc/ipc_pset.h>
72#include <vm/vm_print.h> /* for db_vm() */
73
74#include <machine/db_machdep.h>
75#include <machine/thread.h>
76
77#include <ddb/db_lex.h>
78#include <ddb/db_variables.h>
79#include <ddb/db_sym.h>
80#include <ddb/db_task_thread.h>
81#include <ddb/db_command.h>
82#include <ddb/db_output.h> /* For db_printf() */
83#include <ddb/db_print.h>
84
1c79356b
A
85#if TASK_SWAPPER
86#include <kern/task_swap.h>
87#endif /* TASK_SWAPPER */
88
89/* Prototypes for functions local to this file. XXX -- should be static!
90 */
91
92char *db_act_stat(
93 register thread_act_t thr_act,
94 char *status);
95
96char *db_act_swap_stat(
97 register thread_act_t thr_act,
98 char *status);
99
100void db_print_task(
101 task_t task,
102 int task_id,
103 int flag);
104
105void db_reset_print_entry(
106 void);
107
108void db_print_one_entry(
109 ipc_entry_t entry,
110 int index,
111 mach_port_name_t name,
112 boolean_t is_pset,
113 ipc_space_t space);
114
115int db_port_iterate(
116 thread_act_t thr_act,
117 boolean_t is_pset,
118 boolean_t do_output);
119
120ipc_port_t db_lookup_port(
121 thread_act_t thr_act,
122 int id);
123
124static void db_print_port_id(
125 int id,
126 ipc_port_t port,
127 unsigned bits,
128 int n);
129
130void db_print_act(
131 thread_act_t thr_act,
132 int act_id,
133 int flag);
134
135void db_print_space(
136 task_t task,
137 int task_id,
138 int flag);
139
140void db_print_task_vm(
141 task_t task,
142 int task_id,
143 boolean_t title,
144 char *modif);
145
146void db_system_stats(void);
147
148
149void
150db_show_regs(
151 db_expr_t addr,
152 boolean_t have_addr,
153 db_expr_t count,
154 char *modif)
155{
156 register struct db_variable *regp;
157 db_expr_t value;
158 db_addr_t offset;
159 char * name;
160 register int i;
161 struct db_var_aux_param aux_param;
162 task_t task = TASK_NULL;
163
164 aux_param.modif = modif;
165 aux_param.thr_act = THR_ACT_NULL;
166 if (db_option(modif, 't')) {
167 if (have_addr) {
168 if (!db_check_act_address_valid((thread_act_t)addr))
169 return;
170 aux_param.thr_act = (thread_act_t)addr;
171 } else
172 aux_param.thr_act = db_default_act;
173 if (aux_param.thr_act != THR_ACT_NULL)
174 task = aux_param.thr_act->task;
175 }
176 for (regp = db_regs; regp < db_eregs; regp++) {
177 if (regp->max_level > 1) {
178 db_printf("bad multi-suffixed register %s\n", regp->name);
179 continue;
180 }
181 aux_param.level = regp->max_level;
182 for (i = regp->low; i <= regp->high; i++) {
183 aux_param.suffix[0] = i;
184 db_read_write_variable(regp, &value, DB_VAR_GET, &aux_param);
185 if (regp->max_level > 0)
186 db_printf("%s%d%*s", regp->name, i,
187 12-strlen(regp->name)-((i<10)?1:2), "");
188 else
189 db_printf("%-12s", regp->name);
de355530 190 db_printf("%#*N", 2+2*sizeof(vm_offset_t), value);
1c79356b
A
191 db_find_xtrn_task_sym_and_offset((db_addr_t)value, &name,
192 &offset, task);
193 if (name != 0 && offset <= db_maxoff && offset != value) {
194 db_printf("\t%s", name);
195 if (offset != 0)
196 db_printf("+%#r", offset);
197 }
198 db_printf("\n");
199 }
200 }
201}
202
203#define OPTION_LONG 0x001 /* long print option */
204#define OPTION_USER 0x002 /* print ps-like stuff */
205#define OPTION_INDENT 0x100 /* print with indent */
206#define OPTION_THREAD_TITLE 0x200 /* print thread title */
207#define OPTION_TASK_TITLE 0x400 /* print thread title */
208
209#ifndef DB_TASK_NAME
210#define DB_TASK_NAME(task) /* no task name */
211#define DB_TASK_NAME_TITLE "" /* no task name */
212#endif /* DB_TASK_NAME */
213
214#ifndef db_act_fp_used
215#define db_act_fp_used(thr_act) FALSE
216#endif
217
218char *
219db_act_stat(
220 register thread_act_t thr_act,
221 char *status)
222{
223 register char *p = status;
224
225 if (!thr_act->active) {
226 *p++ = 'D',
227 *p++ = 'y',
228 *p++ = 'i',
229 *p++ = 'n',
230 *p++ = 'g';
231 *p++ = ' ';
232 } else if (!thr_act->thread) {
233 *p++ = 'E',
234 *p++ = 'm',
235 *p++ = 'p',
236 *p++ = 't',
237 *p++ = 'y';
238 *p++ = ' ';
239 } else {
240 thread_t athread = thr_act->thread;
241
242 *p++ = (athread->state & TH_RUN) ? 'R' : '.';
243 *p++ = (athread->state & TH_WAIT) ? 'W' : '.';
244 *p++ = (athread->state & TH_SUSP) ? 'S' : '.';
0b4e3aa0 245 *p++ = (athread->state & TH_STACK_HANDOFF) ? 'O' : '.';
1c79356b
A
246 *p++ = (athread->state & TH_UNINT) ? 'N' : '.';
247 /* show if the FPU has been used */
248 *p++ = db_act_fp_used(thr_act) ? 'F' : '.';
249 }
250 *p++ = 0;
251 return(status);
252}
253
254char *
255db_act_swap_stat(
256 register thread_act_t thr_act,
257 char *status)
258{
259 register char *p = status;
260
261#if THREAD_SWAPPER
262 switch (thr_act->swap_state & TH_SW_STATE) {
263 case TH_SW_UNSWAPPABLE:
264 *p++ = 'U';
265 break;
266 case TH_SW_IN:
267 *p++ = 'I';
268 break;
269 case TH_SW_GOING_OUT:
270 *p++ = 'G';
271 break;
272 case TH_SW_WANT_IN:
273 *p++ = 'W';
274 break;
275 case TH_SW_OUT:
276 *p++ = 'O';
277 break;
278 case TH_SW_COMING_IN:
279 *p++ = 'C';
280 break;
281 default:
282 *p++ = '?';
283 break;
284 }
285 *p++ = (thr_act->swap_state & TH_SW_TASK_SWAPPING) ? 'T' : '.';
286#endif /* THREAD_SWAPPER */
287 *p++ = 0;
288
289 return status;
290}
291
292char *policy_list[] = { "TS", "RR", "??", "FF",
293 "??", "??", "??", "BE"};
294
295void
296db_print_act(
297 thread_act_t thr_act,
298 int act_id,
299 int flag)
300{
301 thread_t athread;
302 char status[8];
303 char swap_status[3];
304 char *indent = "";
305 int policy;
306
307 if (!thr_act) {
308 db_printf("db_print_act(NULL)!\n");
309 return;
310 }
311
312 athread = thr_act->thread;
313 if (flag & OPTION_USER) {
314
315 if (flag & OPTION_LONG) {
316 if (flag & OPTION_INDENT)
317 indent = " ";
318 if (flag & OPTION_THREAD_TITLE) {
319 db_printf("%s ID: ACT STAT SW STACK SHUTTLE", indent);
320 db_printf(" SUS PRI WAIT_FUNC\n");
321 }
0b4e3aa0 322 policy = ((athread && (athread->sched_mode&TH_MODE_TIMESHARE))? 1: 2);
1c79356b
A
323 db_printf("%s%3d%c %0*X %s %s %0*X %0*X %3d %3d/%s ",
324 indent, act_id,
325 (thr_act == current_act())? '#': ':',
326 2*sizeof(vm_offset_t), thr_act,
327 db_act_stat(thr_act, status),
328 db_act_swap_stat(thr_act, swap_status),
329 2*sizeof(vm_offset_t), (athread ?athread->kernel_stack:0),
330 2*sizeof(vm_offset_t), athread,
331 thr_act->suspend_count,
332 (athread ? athread->sched_pri : 999), /* XXX */
333 policy_list[policy-1]);
334 if (athread) {
335 /* no longer TH_SWAP, no continuation to print */
336 if (athread->state & TH_WAIT)
337 db_task_printsym((db_addr_t)athread->wait_event,
338 DB_STGY_ANY, kernel_task);
339 }
340 db_printf("\n");
341 } else {
342 if (act_id % 3 == 0) {
343 if (flag & OPTION_INDENT)
344 db_printf("\n ");
345 } else
346 db_printf(" ");
347 db_printf("%3d%c(%0*X,%s)", act_id,
348 (thr_act == current_act())? '#': ':',
349 2*sizeof(vm_offset_t), thr_act,
350 db_act_stat(thr_act, status));
351 }
352 } else {
353 if (flag & OPTION_INDENT)
354 db_printf(" %3d (%0*X) ", act_id,
355 2*sizeof(vm_offset_t), thr_act);
356 else
357 db_printf("(%0*X) ", 2*sizeof(vm_offset_t), thr_act);
358 if (athread) {
359 db_printf("%c%c%c%c%c",
360 (athread->state & TH_RUN) ? 'R' : ' ',
361 (athread->state & TH_WAIT) ? 'W' : ' ',
362 (athread->state & TH_SUSP) ? 'S' : ' ',
363 (athread->state & TH_UNINT)? 'N' : ' ',
364 db_act_fp_used(thr_act) ? 'F' : ' ');
365 /* Obsolete TH_STACK_HANDOFF code, left for now; might enhance
366 * to print out safe_points instead */
367 if (athread->state & TH_STACK_HANDOFF) {
368 if (athread->continuation) {
369 db_printf("(");
370 db_task_printsym((db_addr_t)athread->continuation,
371 DB_STGY_ANY, kernel_task);
372 db_printf(")");
373 } else {
374 db_printf("(handoff)");
375 }
376 }
377 if (athread->state & TH_WAIT) {
378 db_printf(" ");
379 db_task_printsym((db_addr_t)athread->wait_event,
380 DB_STGY_ANY, kernel_task);
381 }
382 } else
383 db_printf("Empty");
384 db_printf("\n");
385 }
386}
387
388void
389db_print_task(
390 task_t task,
391 int task_id,
392 int flag)
393{
394 thread_act_t thr_act;
395 int act_id;
396 char sstate;
397
398 if (flag & OPTION_USER) {
399 if (flag & OPTION_TASK_TITLE) {
400 db_printf(" ID: TASK MAP THD RES SUS PR SW %s",
401 DB_TASK_NAME_TITLE);
402 if ((flag & OPTION_LONG) == 0)
403 db_printf(" ACTS");
404 db_printf("\n");
405 }
406#if TASK_SWAPPER
407 switch ((int) task->swap_state) {
408 case TASK_SW_IN:
409 sstate = 'I';
410 break;
411 case TASK_SW_OUT:
412 sstate = 'O';
413 break;
414 case TASK_SW_GOING_OUT:
415 sstate = 'G';
416 break;
417 case TASK_SW_COMING_IN:
418 sstate = 'C';
419 break;
420 case TASK_SW_UNSWAPPABLE:
421 sstate = 'U';
422 break;
423 default:
424 sstate = '?';
425 break;
426 }
427#else /* TASK_SWAPPER */
428 sstate = 'I';
429#endif /* TASK_SWAPPER */
430 /*** ??? fix me ***/
431 db_printf("%3d: %0*X %0*X %3d %3d %3d %2d %c ",
432 task_id, 2*sizeof(vm_offset_t), task,
433 2*sizeof(vm_offset_t), task->map,
434 task->thr_act_count, task->res_act_count,
435 task->suspend_count,
436 task->priority,
437 sstate);
438 DB_TASK_NAME(task);
439 if (flag & OPTION_LONG) {
440 if (flag & OPTION_TASK_TITLE)
441 flag |= OPTION_THREAD_TITLE;
442 db_printf("\n");
443 } else if (task->thr_act_count <= 1)
444 flag &= ~OPTION_INDENT;
445 act_id = 0;
446 queue_iterate(&task->thr_acts, thr_act, thread_act_t, thr_acts) {
447 db_print_act(thr_act, act_id, flag);
448 flag &= ~OPTION_THREAD_TITLE;
449 act_id++;
450 }
451 if ((flag & OPTION_LONG) == 0)
452 db_printf("\n");
453 } else {
454 if (flag & OPTION_LONG) {
455 if (flag & OPTION_TASK_TITLE) {
456 db_printf(" TASK ACT\n");
457 if (task->thr_act_count > 1)
458 flag |= OPTION_THREAD_TITLE;
459 }
460 }
461 db_printf("%3d (%0*X): ", task_id, 2*sizeof(vm_offset_t), task);
462 if (task->thr_act_count == 0) {
463 db_printf("no threads\n");
464 } else {
465 if (task->thr_act_count > 1) {
466 db_printf("%d threads: \n", task->thr_act_count);
467 flag |= OPTION_INDENT;
468 } else
469 flag &= ~OPTION_INDENT;
470 act_id = 0;
471 queue_iterate(&task->thr_acts, thr_act,
472 thread_act_t, thr_acts) {
473 db_print_act(thr_act, act_id++, flag);
474 flag &= ~OPTION_THREAD_TITLE;
475 }
476 }
477 }
478}
479
480void
481db_print_space(
482 task_t task,
483 int task_id,
484 int flag)
485{
486 ipc_space_t space;
487 thread_act_t act = (thread_act_t)queue_first(&task->thr_acts);
488 int count;
489
490 count = 0;
491 space = task->itk_space;
492 if (act)
493 count = db_port_iterate(act, FALSE, FALSE);
494 db_printf("%3d: %08x %08x %08x %sactive %d\n",
495 task_id, task, space, task->map,
496 space->is_active? "":"!", count);
497}
498
499void
500db_print_task_vm(
501 task_t task,
502 int task_id,
503 boolean_t title,
504 char *modif)
505{
506 vm_map_t map;
507 pmap_t pmap;
508 vm_size_t size;
509 long resident;
510 long wired;
511
512 if (title) {
513 db_printf("id task map pmap virtual rss pg rss mem wir pg wir mem\n");
514 }
515
516 map = task->map;
517 pmap = vm_map_pmap(map);
518
519 size = db_vm_map_total_size(map);
520 resident = pmap->stats.resident_count;
521 wired = pmap->stats.wired_count;
522
523 db_printf("%2d %08x %08x %08x %7dK %6d %6dK %6d %6dK\n",
524 task_id,
525 task,
526 map,
527 pmap,
528 size / 1024,
529 resident, (resident * PAGE_SIZE) / 1024,
530 wired, (wired * PAGE_SIZE) / 1024);
531}
532
533
534void
535db_show_one_task_vm(
536 db_expr_t addr,
537 boolean_t have_addr,
538 db_expr_t count,
539 char *modif)
540{
541 thread_act_t thread;
542 task_t task;
543 int task_id;
544
545 if (have_addr == FALSE) {
546 if ((thread = db_default_act) == THR_ACT_NULL) {
547 if ((thread = current_act()) == THR_ACT_NULL) {
548 db_printf("no thread.\n");
549 return;
550 }
551 }
552 task = thread->task;
553 } else {
554 task = (task_t) addr;
555 }
556
557 task_id = db_lookup_task(task);
558 if (task_id < 0) {
559 db_printf("0x%x is not a task_t\n", addr);
560 return;
561 }
562
563 db_print_task_vm(task, task_id, TRUE, modif);
564}
565
566void
567db_show_all_task_vm(
568 db_expr_t addr,
569 boolean_t have_addr,
570 db_expr_t count,
571 char *modif)
572{
573 task_t task;
574 int task_id;
575 boolean_t title = TRUE;
576 processor_set_t pset = &default_pset;
577
578 task_id = 0;
579 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
580 db_print_task_vm(task, task_id, title, modif);
581 title = FALSE;
582 task_id++;
583 }
584}
585
586void
587db_show_all_acts(
588 db_expr_t addr,
589 boolean_t have_addr,
590 db_expr_t count,
591 char * modif)
592{
593 task_t task;
594 int task_id;
595 int flag;
596 processor_set_t pset = &default_pset;
597
598 flag = OPTION_TASK_TITLE|OPTION_INDENT;
599 if (db_option(modif, 'u'))
600 flag |= OPTION_USER;
601 if (db_option(modif, 'l'))
602 flag |= OPTION_LONG;
603
604 task_id = 0;
605 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
606 db_print_task(task, task_id, flag);
607 flag &= ~OPTION_TASK_TITLE;
608 task_id++;
609 if ((flag & (OPTION_LONG|OPTION_INDENT)) == OPTION_INDENT)
610 db_printf("\n");
611 }
612}
613
614void
615db_show_one_space(
616 db_expr_t addr,
617 boolean_t have_addr,
618 db_expr_t count,
619 char * modif)
620{
621 int flag;
622 int task_id;
623 task_t task;
624
625 flag = OPTION_TASK_TITLE;
626 if (db_option(modif, 'u'))
627 flag |= OPTION_USER;
628 if (db_option(modif, 'l'))
629 flag |= OPTION_LONG;
630
631 if (!have_addr) {
632 task = db_current_task();
633 if (task == TASK_NULL) {
634 db_error("No task\n");
635 /*NOTREACHED*/
636 }
637 } else
638 task = (task_t) addr;
639
640 if ((task_id = db_lookup_task(task)) < 0) {
641 db_printf("bad task address 0x%x\n", addr);
642 db_error(0);
643 /*NOTREACHED*/
644 }
645
646 db_printf(" ID: TASK SPACE MAP COUNT\n");
647 db_print_space(task, task_id, flag);
648}
649
650void
651db_show_all_spaces(
652 db_expr_t addr,
653 boolean_t have_addr,
654 db_expr_t count,
655 char * modif)
656{
657 task_t task;
658 int task_id = 0;
659 int flag;
660 processor_set_t pset = &default_pset;
661
662 flag = OPTION_TASK_TITLE|OPTION_INDENT;
663 if (db_option(modif, 'u'))
664 flag |= OPTION_USER;
665 if (db_option(modif, 'l'))
666 flag |= OPTION_LONG;
667
668 db_printf(" ID: TASK SPACE MAP COUNT\n");
669 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
670 db_print_space(task, task_id, flag);
671 task_id++;
672 }
673}
674
675db_addr_t
676db_task_from_space(
677 ipc_space_t space,
678 int *task_id)
679{
680 task_t task;
681 int tid = 0;
682 processor_set_t pset = &default_pset;
683
684 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
685 if (task->itk_space == space) {
686 *task_id = tid;
687 return (db_addr_t)task;
688 }
689 tid++;
690 }
691 *task_id = 0;
692 return (0);
693}
694
695void
696db_show_one_act(
697 db_expr_t addr,
698 boolean_t have_addr,
699 db_expr_t count,
700 char * modif)
701{
702 int flag;
703 int act_id;
704 thread_act_t thr_act;
705
706 flag = OPTION_THREAD_TITLE;
707 if (db_option(modif, 'u'))
708 flag |= OPTION_USER;
709 if (db_option(modif, 'l'))
710 flag |= OPTION_LONG;
711
712 if (!have_addr) {
713 thr_act = current_act();
714 if (thr_act == THR_ACT_NULL) {
715 db_error("No thr_act\n");
716 /*NOTREACHED*/
717 }
718 } else
719 thr_act = (thread_act_t) addr;
720
721 if ((act_id = db_lookup_act(thr_act)) < 0) {
de355530 722 db_printf("bad thr_act address %#x\n", addr);
1c79356b
A
723 db_error(0);
724 /*NOTREACHED*/
725 }
726
727 if (flag & OPTION_USER) {
728 db_printf("TASK%d(%0*X):\n",
729 db_lookup_task(thr_act->task),
730 2*sizeof(vm_offset_t), thr_act->task);
731 db_print_act(thr_act, act_id, flag);
732 } else {
733 db_printf("task %d(%0*Xx): thr_act %d",
734 db_lookup_task(thr_act->task),
735 2*sizeof(vm_offset_t), thr_act->task, act_id);
736 db_print_act(thr_act, act_id, flag);
737 }
738 if (db_option(modif, 'i') && thr_act->thread &&
739 (thr_act->thread->state & TH_WAIT) &&
740 thr_act->thread->kernel_stack == 0) {
741
742 db_printf("Wait State: option 0x%x\n",
743 thr_act->thread->ith_option);
744 }
745}
746
747void
748db_show_one_task(
749 db_expr_t addr,
750 boolean_t have_addr,
751 db_expr_t count,
752 char * modif)
753{
754 int flag;
755 int task_id;
756 task_t task;
757
758 flag = OPTION_TASK_TITLE|OPTION_INDENT;
759 if (db_option(modif, 'u'))
760 flag |= OPTION_USER;
761 if (db_option(modif, 'l'))
762 flag |= OPTION_LONG;
763
764 if (!have_addr) {
765 task = db_current_task();
766 if (task == TASK_NULL) {
767 db_error("No task\n");
768 /*NOTREACHED*/
769 }
770 } else
771 task = (task_t) addr;
772
773 if ((task_id = db_lookup_task(task)) < 0) {
de355530 774 db_printf("bad task address 0x%x\n", addr);
1c79356b
A
775 db_error(0);
776 /*NOTREACHED*/
777 }
778
779 db_print_task(task, task_id, flag);
780}
781
782void
783db_show_shuttle(
784 db_expr_t addr,
785 boolean_t have_addr,
786 db_expr_t count,
787 char * modif)
788{
789 thread_shuttle_t shuttle;
790 thread_act_t thr_act;
791
792 if (have_addr)
793 shuttle = (thread_shuttle_t) addr;
794 else {
795 thr_act = current_act();
796 if (thr_act == THR_ACT_NULL) {
797 db_error("No thr_act\n");
798 /*NOTREACHED*/
799 }
800 shuttle = thr_act->thread;
801 if (shuttle == THREAD_NULL) {
802 db_error("No shuttle associated with current thr_act\n");
803 /*NOTREACHED*/
804 }
805 }
806 db_printf("shuttle %x:\n", shuttle);
807 if (shuttle->top_act == THR_ACT_NULL)
808 db_printf(" no activations\n");
809 else {
810 db_printf(" activations:");
811 for (thr_act = shuttle->top_act; thr_act != THR_ACT_NULL;
812 thr_act = thr_act->lower) {
813 if (thr_act != shuttle->top_act)
814 printf(" from");
815 printf(" $task%d.%d(%x)", db_lookup_task(thr_act->task),
816 db_lookup_act(thr_act), thr_act);
817 }
818 db_printf("\n");
819 }
820}
821
822int
823db_port_kmsg_count(
824 ipc_port_t port)
825{
826 return (port->ip_messages.imq_msgcount);
827}
828
829static int db_print_ent_cnt = 0;
830
831void db_reset_print_entry(
832 void)
833{
834 db_print_ent_cnt = 0;
835}
836
837void
838db_print_one_entry(
839 ipc_entry_t entry,
840 int index,
841 mach_port_name_t name,
842 boolean_t is_pset,
843 ipc_space_t space)
844{
845 ipc_port_t aport = (ipc_port_t)entry->ie_object;
846 ipc_entry_bits_t bits;
847
848 bits = entry->ie_bits;
849 if (is_pset && !aport->ip_pset_count)
850 return;
851 if (db_print_ent_cnt && db_print_ent_cnt % 2 == 0)
852 db_printf("\n");
853 if (!name)
854 db_printf("\t%s%d[%x]",
855 !is_pset && aport->ip_pset_count ? "pset" : "port",
856 index,
857 MACH_PORT_MAKE(index, IE_BITS_GEN(bits)));
858 else
859 db_printf("\t%s[%x]",
860 !is_pset && aport->ip_pset_count ? "pset" : "port",
861 name);
862 if (!is_pset) {
863 db_printf("(%s,%x,%d)",
864 (bits & MACH_PORT_TYPE_RECEIVE)? "r":
865 (bits & MACH_PORT_TYPE_SEND)? "s": "S",
866 aport,
867 db_port_kmsg_count(aport));
868 db_print_ent_cnt++;
869 }
870 else {
871 db_printf("(%s,%x,set_count=%d,%d)",
872 (bits & MACH_PORT_TYPE_RECEIVE)? "r":
873 (bits & MACH_PORT_TYPE_SEND)? "s": "S",
874 aport,
875 aport->ip_pset_count,
876 db_port_kmsg_count(aport));
877 db_print_ent_cnt++;
878 }
879}
880
881int
882db_port_iterate(
883 thread_act_t thr_act,
884 boolean_t is_pset,
885 boolean_t do_output)
886{
887 ipc_entry_t entry;
888 ipc_tree_entry_t tentry;
889 int index;
890 int size;
891 int count;
892 ipc_space_t space;
893
894 count = 0;
895 space = thr_act->task->itk_space;
896 entry = space->is_table;
897 size = space->is_table_size;
898 db_reset_print_entry();
899 for (index = 0; index < size; ++index, ++entry) {
900 if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) {
901 if (do_output)
902 db_print_one_entry(entry,
903 index, MACH_PORT_NULL, is_pset, space);
904 ++count;
905 }
906 }
907 for (tentry = ipc_splay_traverse_start(&space->is_tree);
908 tentry != ITE_NULL;
909 tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) {
910 entry = &tentry->ite_entry;
911 if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) {
912 if (do_output)
913 db_print_one_entry(entry,
914 0, tentry->ite_name, is_pset, space);
915 ++count;
916 }
917 }
918 return (count);
919}
920
921ipc_port_t
922db_lookup_port(
923 thread_act_t thr_act,
924 int id)
925{
926 register ipc_space_t space;
927 register ipc_entry_t entry;
928
929 if (thr_act == THR_ACT_NULL)
930 return(0);
931 space = thr_act->task->itk_space;
932 if (id < 0 || id >= space->is_table_size)
933 return(0);
934 entry = &space->is_table[id];
935 if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS)
936 return((ipc_port_t)entry->ie_object);
937 return(0);
938}
939
940static void
941db_print_port_id(
942 int id,
943 ipc_port_t port,
944 unsigned bits,
945 int n)
946{
947 if (n != 0 && n % 3 == 0)
948 db_printf("\n");
949 db_printf("\tport%d(%s,%x)", id,
950 (bits & MACH_PORT_TYPE_RECEIVE)? "r":
951 (bits & MACH_PORT_TYPE_SEND)? "s": "S", port);
952}
953
954void
955db_show_port_id(
956 db_expr_t addr,
957 boolean_t have_addr,
958 db_expr_t count,
959 char * modif)
960{
961 thread_act_t thr_act;
962
963 if (!have_addr) {
964 thr_act = current_act();
965 if (thr_act == THR_ACT_NULL) {
966 db_error("No thr_act\n");
967 /*NOTREACHED*/
968 }
969 } else
970 thr_act = (thread_act_t) addr;
971 if (db_lookup_act(thr_act) < 0) {
de355530 972 db_printf("Bad thr_act address 0x%x\n", addr);
1c79356b
A
973 db_error(0);
974 /*NOTREACHED*/
975 }
976 if (db_port_iterate(thr_act, db_option(modif,'s'), TRUE))
977 db_printf("\n");
978}
979
980/*
981 * Useful system state when the world has hung.
982 */
983void
984db_system_stats()
985{
986 extern void db_sched(void);
987
988 db_sched();
989 iprintf("\n");
990 db_vm();
991 iprintf("\n");
992 iprintf("\n");
993 db_printf("current_{thread/task} 0x%x 0x%x\n",
994 current_thread(),current_task());
995}
996
997void db_show_one_runq(run_queue_t runq);
998
999void
1000db_show_runq(
1001 db_expr_t addr,
1002 boolean_t have_addr,
1003 db_expr_t count,
1004 char * modif)
1005{
1006 processor_set_t pset = &default_pset;
1007 processor_t proc;
1008 run_queue_t runq;
1009 boolean_t showedany = FALSE;
1010
1011#if NCPUS > 1 /* This code has not been tested. */
1012 queue_iterate(&pset->processors, proc, processor_t, processors) {
1013 runq = &proc->runq;
1014 if (runq->count > 0) {
1015 db_printf("PROCESSOR %x IN SET %x\n", proc, pset);
1016 db_show_one_runq(runq);
1017 showedany = TRUE;
1018 }
1019 }
1020#endif /* NCPUS > 1 */
1021#ifndef NCPUS
1022#error NCPUS undefined
1023#endif
1024 runq = &pset->runq;
1025 if (runq->count > 0) {
1026 db_printf("PROCESSOR SET %x\n", pset);
1027 db_show_one_runq(runq);
1028 showedany = TRUE;
1029 }
1030 if (!showedany)
1031 db_printf("No runnable threads\n");
1032}
1033
1034void
1035db_show_one_runq(
1036 run_queue_t runq)
1037{
1038 int i, task_id, thr_act_id;
1039 queue_t q;
1040 thread_act_t thr_act;
1041 thread_t thread;
1042 task_t task;
1043
1044 printf("PRI TASK.ACTIVATION\n");
1045 for (i = runq->highq, q = runq->queues + i; i >= 0; i--, q--) {
1046 if (!queue_empty(q)) {
1047 db_printf("%3d:", i);
1048 queue_iterate(q, thread, thread_t, links) {
1049 thr_act = thread->top_act;
1050 task = thr_act->task;
1051 task_id = db_lookup_task(task);
1052 thr_act_id = db_lookup_task_act(task, thr_act);
1053 db_printf(" %d.%d", task_id, thr_act_id);
1054 }
1055 db_printf("\n");
1056 }
1057 }
1058}