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