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