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