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