]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ddb/db_print.c
xnu-1228.tar.gz
[apple/xnu.git] / osfmk / ddb / db_print.c
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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>
1c79356b
A
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
1c79356b
A
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
97char *db_act_stat(
91447636 98 register thread_t thr_act,
1c79356b
A
99 char *status);
100
101char *db_act_swap_stat(
91447636 102 register thread_t thr_act,
1c79356b
A
103 char *status);
104
105void db_print_task(
106 task_t task,
107 int task_id,
108 int flag);
109
110void db_reset_print_entry(
111 void);
112
113void 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
120int db_port_iterate(
91447636 121 thread_t thr_act,
1c79356b
A
122 boolean_t is_pset,
123 boolean_t do_output);
124
125ipc_port_t db_lookup_port(
91447636 126 thread_t thr_act,
1c79356b
A
127 int id);
128
1c79356b 129void db_print_act(
91447636 130 thread_t thr_act,
1c79356b
A
131 int act_id,
132 int flag);
133
134void db_print_space(
135 task_t task,
136 int task_id,
137 int flag);
138
139void db_print_task_vm(
140 task_t task,
141 int task_id,
142 boolean_t title,
143 char *modif);
144
145void db_system_stats(void);
146
147
148void
2d21ac55
A
149db_show_regs(db_expr_t addr, boolean_t have_addr, __unused db_expr_t count,
150 char *modif)
1c79356b
A
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;
91447636 161 aux_param.thr_act = THREAD_NULL;
1c79356b
A
162 if (db_option(modif, 't')) {
163 if (have_addr) {
2d21ac55 164 if (!db_check_act_address_valid((thread_t)(unsigned long)addr))
1c79356b 165 return;
2d21ac55 166 aux_param.thr_act = (thread_t)(unsigned long)addr;
1c79356b
A
167 } else
168 aux_param.thr_act = db_default_act;
91447636 169 if (aux_param.thr_act != THREAD_NULL)
1c79356b
A
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);
91447636 186 db_printf("%#*llN", 2+2*sizeof(db_expr_t), (unsigned long long)value);
1c79356b
A
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)
91447636 192 db_printf("+%#llr", (unsigned long long)offset);
1c79356b
A
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
214char *
215db_act_stat(
91447636 216 register thread_t thr_act,
1c79356b
A
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++ = ' ';
1c79356b 228 } else {
91447636 229 thread_t athread = thr_act;
1c79356b
A
230
231 *p++ = (athread->state & TH_RUN) ? 'R' : '.';
232 *p++ = (athread->state & TH_WAIT) ? 'W' : '.';
233 *p++ = (athread->state & TH_SUSP) ? 'S' : '.';
91447636 234 *p++ = (!athread->kernel_stack) ? 'O' : '.';
1c79356b
A
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
243char *
2d21ac55 244db_act_swap_stat(__unused thread_t thr_act, char *status)
1c79356b
A
245{
246 register char *p = status;
1c79356b
A
247 *p++ = 0;
248
249 return status;
250}
251
2d21ac55 252const char *policy_list[] = { "TS", "RR", "??", "FF", "??", "??", "??", "BE"};
1c79356b
A
253
254void
255db_print_act(
91447636 256 thread_t thr_act,
1c79356b
A
257 int act_id,
258 int flag)
259{
260 thread_t athread;
261 char status[8];
262 char swap_status[3];
2d21ac55 263 const char *indent = "";
1c79356b
A
264 int policy;
265
266 if (!thr_act) {
267 db_printf("db_print_act(NULL)!\n");
268 return;
269 }
270
91447636 271 athread = thr_act;
1c79356b
A
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 }
0b4e3aa0 281 policy = ((athread && (athread->sched_mode&TH_MODE_TIMESHARE))? 1: 2);
1c79356b
A
282 db_printf("%s%3d%c %0*X %s %s %0*X %0*X %3d %3d/%s ",
283 indent, act_id,
91447636 284 (thr_act == current_thread())? '#': ':',
1c79356b
A
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,
91447636 307 (thr_act == current_thread())? '#': ':',
1c79356b
A
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' : ' ');
91447636 324 if (!athread->kernel_stack) {
1c79356b
A
325 if (athread->continuation) {
326 db_printf("(");
2d21ac55 327 db_task_printsym((db_addr_t)(unsigned long)athread->continuation,
1c79356b
A
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
345void
346db_print_task(
347 task_t task,
348 int task_id,
349 int flag)
350{
91447636 351 thread_t thr_act;
1c79356b
A
352 int act_id;
353 char sstate;
354
355 if (flag & OPTION_USER) {
356 if (flag & OPTION_TASK_TITLE) {
91447636 357 db_printf(" ID: TASK MAP THD SUS PR SW %s",
1c79356b
A
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 ***/
91447636 388 db_printf("%3d: %0*X %0*X %3d %3d %2d %c ",
1c79356b
A
389 task_id, 2*sizeof(vm_offset_t), task,
390 2*sizeof(vm_offset_t), task->map,
91447636 391 task->thread_count,
1c79356b
A
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");
55e303ae 400 } else if (task->thread_count <= 1)
1c79356b
A
401 flag &= ~OPTION_INDENT;
402 act_id = 0;
91447636 403 queue_iterate(&task->threads, thr_act, thread_t, task_threads) {
1c79356b
A
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");
55e303ae 414 if (task->thread_count > 1)
1c79356b
A
415 flag |= OPTION_THREAD_TITLE;
416 }
417 }
418 db_printf("%3d (%0*X): ", task_id, 2*sizeof(vm_offset_t), task);
55e303ae 419 if (task->thread_count == 0) {
1c79356b
A
420 db_printf("no threads\n");
421 } else {
55e303ae
A
422 if (task->thread_count > 1) {
423 db_printf("%d threads: \n", task->thread_count);
1c79356b
A
424 flag |= OPTION_INDENT;
425 } else
426 flag &= ~OPTION_INDENT;
427 act_id = 0;
55e303ae 428 queue_iterate(&task->threads, thr_act,
91447636 429 thread_t, task_threads) {
1c79356b
A
430 db_print_act(thr_act, act_id++, flag);
431 flag &= ~OPTION_THREAD_TITLE;
432 }
433 }
434 }
435}
436
437void
2d21ac55 438db_print_space(task_t task, int task_id, __unused int flag)
1c79356b
A
439{
440 ipc_space_t space;
91447636 441 thread_t act = (thread_t)queue_first(&task->threads);
1c79356b
A
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
453void
2d21ac55
A
454db_print_task_vm(task_t task, int task_id, boolean_t title,
455 __unused char *modif)
1c79356b
A
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
2d21ac55 470 size = db_vm_map_total_size((unsigned long)map);
1c79356b
A
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
485void
2d21ac55
A
486db_show_one_task_vm(db_expr_t addr, boolean_t have_addr,
487 __unused db_expr_t count, char *modif)
1c79356b 488{
91447636 489 thread_t thread;
1c79356b
A
490 task_t task;
491 int task_id;
492
493 if (have_addr == FALSE) {
91447636
A
494 if ((thread = db_default_act) == THREAD_NULL) {
495 if ((thread = current_thread()) == THREAD_NULL) {
1c79356b
A
496 db_printf("no thread.\n");
497 return;
498 }
499 }
500 task = thread->task;
501 } else {
2d21ac55 502 task = (task_t)(unsigned long)addr;
1c79356b
A
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
514void
2d21ac55
A
515db_show_all_task_vm(__unused db_expr_t addr, __unused boolean_t have_addr,
516 __unused db_expr_t count, char *modif)
1c79356b
A
517{
518 task_t task;
519 int task_id;
520 boolean_t title = TRUE;
1c79356b
A
521
522 task_id = 0;
2d21ac55 523 queue_iterate(&tasks, task, task_t, tasks) {
1c79356b
A
524 db_print_task_vm(task, task_id, title, modif);
525 title = FALSE;
526 task_id++;
527 }
528}
529
530void
2d21ac55
A
531db_show_all_acts(__unused db_expr_t addr, __unused boolean_t have_addr,
532 __unused db_expr_t count, char *modif)
1c79356b
A
533{
534 task_t task;
535 int task_id;
536 int flag;
1c79356b
A
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;
2d21ac55 545 queue_iterate(&tasks, task, task_t, tasks) {
1c79356b
A
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
554void
2d21ac55
A
555db_show_one_space(db_expr_t addr, boolean_t have_addr,
556 __unused db_expr_t count, char *modif)
1c79356b
A
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
2d21ac55 575 task = (task_t)(unsigned long)addr;
1c79356b
A
576
577 if ((task_id = db_lookup_task(task)) < 0) {
91447636 578 db_printf("bad task address 0x%llx\n", (unsigned long long)addr);
1c79356b
A
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
587void
2d21ac55
A
588db_show_all_spaces(__unused db_expr_t addr, __unused boolean_t have_addr,
589 __unused db_expr_t count, char *modif)
1c79356b
A
590{
591 task_t task;
592 int task_id = 0;
593 int flag;
1c79356b
A
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");
2d21ac55 602 queue_iterate(&tasks, task, task_t, tasks) {
1c79356b
A
603 db_print_space(task, task_id, flag);
604 task_id++;
605 }
606}
607
608db_addr_t
609db_task_from_space(
610 ipc_space_t space,
611 int *task_id)
612{
613 task_t task;
614 int tid = 0;
1c79356b 615
2d21ac55 616 queue_iterate(&tasks, task, task_t, tasks) {
1c79356b
A
617 if (task->itk_space == space) {
618 *task_id = tid;
2d21ac55 619 return (db_addr_t)(unsigned long)task;
1c79356b
A
620 }
621 tid++;
622 }
623 *task_id = 0;
624 return (0);
625}
626
627void
2d21ac55
A
628db_show_one_act(db_expr_t addr, boolean_t have_addr, __unused db_expr_t count,
629 char *modif)
1c79356b
A
630{
631 int flag;
632 int act_id;
91447636 633 thread_t thr_act;
1c79356b
A
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) {
91447636
A
642 thr_act = current_thread();
643 if (thr_act == THREAD_NULL) {
1c79356b
A
644 db_error("No thr_act\n");
645 /*NOTREACHED*/
646 }
647 } else
2d21ac55 648 thr_act = (thread_t)(unsigned long)addr;
1c79356b
A
649
650 if ((act_id = db_lookup_act(thr_act)) < 0) {
91447636 651 db_printf("bad thr_act address %#llX\n", (unsigned long long)addr);
1c79356b
A
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 }
91447636
A
667 if (db_option(modif, 'i') &&
668 (thr_act->state & TH_WAIT) &&
669 thr_act->kernel_stack == 0) {
1c79356b
A
670
671 db_printf("Wait State: option 0x%x\n",
91447636 672 thr_act->ith_option);
1c79356b
A
673 }
674}
675
676void
2d21ac55
A
677db_show_one_task(db_expr_t addr, boolean_t have_addr,
678 __unused db_expr_t count, char *modif)
1c79356b
A
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
2d21ac55 697 task = (task_t)(unsigned long)addr;
1c79356b
A
698
699 if ((task_id = db_lookup_task(task)) < 0) {
91447636 700 db_printf("bad task address 0x%llX\n", (unsigned long long)addr);
1c79356b
A
701 db_error(0);
702 /*NOTREACHED*/
703 }
704
705 db_print_task(task, task_id, flag);
706}
707
708void
2d21ac55
A
709db_show_shuttle(db_expr_t addr, boolean_t have_addr, __unused db_expr_t count,
710 __unused char *modif)
1c79356b 711{
91447636 712 thread_t thread;
1c79356b
A
713
714 if (have_addr)
2d21ac55 715 thread = (thread_t)(unsigned long)addr;
1c79356b 716 else {
91447636
A
717 thread = current_thread();
718 if (thread == THREAD_NULL) {
719 db_error("No thread\n");
1c79356b
A
720 /*NOTREACHED*/
721 }
722 }
91447636
A
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");
1c79356b
A
727}
728
729int
730db_port_kmsg_count(
731 ipc_port_t port)
732{
733 return (port->ip_messages.imq_msgcount);
734}
735
736static int db_print_ent_cnt = 0;
737
738void db_reset_print_entry(
739 void)
740{
741 db_print_ent_cnt = 0;
742}
743
744void
2d21ac55
A
745db_print_one_entry(ipc_entry_t entry, int index, mach_port_name_t name,
746 boolean_t is_pset, __unused ipc_space_t space)
1c79356b
A
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
784int
785db_port_iterate(
91447636 786 thread_t thr_act,
1c79356b
A
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
824ipc_port_t
825db_lookup_port(
91447636 826 thread_t thr_act,
1c79356b
A
827 int id)
828{
829 register ipc_space_t space;
830 register ipc_entry_t entry;
831
91447636 832 if (thr_act == THREAD_NULL)
1c79356b
A
833 return(0);
834 space = thr_act->task->itk_space;
2d21ac55 835 if (id < 0 || (unsigned)id >= space->is_table_size)
1c79356b
A
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
1c79356b 843void
2d21ac55
A
844db_show_port_id(db_expr_t addr, boolean_t have_addr, __unused db_expr_t count,
845 char *modif)
1c79356b 846{
91447636 847 thread_t thr_act;
1c79356b
A
848
849 if (!have_addr) {
91447636
A
850 thr_act = current_thread();
851 if (thr_act == THREAD_NULL) {
1c79356b
A
852 db_error("No thr_act\n");
853 /*NOTREACHED*/
854 }
855 } else
2d21ac55 856 thr_act = (thread_t)(unsigned long)addr;
1c79356b 857 if (db_lookup_act(thr_act) < 0) {
55e303ae 858 db_printf("Bad thr_act address 0x%llX\n", addr);
1c79356b
A
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
2d21ac55 866extern void db_sched(void);
1c79356b
A
867/*
868 * Useful system state when the world has hung.
869 */
870void
2d21ac55 871db_system_stats(void)
1c79356b 872{
1c79356b
A
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
882void db_show_one_runq(run_queue_t runq);
883
884void
2d21ac55
A
885db_show_runq(__unused db_expr_t addr, __unused boolean_t have_addr,
886 __unused db_expr_t count, __unused char *modif)
1c79356b 887{
1c79356b
A
888 processor_t proc;
889 run_queue_t runq;
890 boolean_t showedany = FALSE;
891
2d21ac55 892 for (proc = processor_list; proc != PROCESSOR_NULL; proc = proc->processor_list) {
1c79356b
A
893 runq = &proc->runq;
894 if (runq->count > 0) {
2d21ac55 895 db_printf("PROCESSOR %x IN SET %x\n", proc, proc->processor_set);
1c79356b
A
896 db_show_one_runq(runq);
897 showedany = TRUE;
898 }
899 }
2d21ac55
A
900 if (rt_runq.count > 0) {
901 db_printf("REAL TIME\n");
1c79356b
A
902 db_show_one_runq(runq);
903 showedany = TRUE;
904 }
905 if (!showedany)
906 db_printf("No runnable threads\n");
907}
908
909void
910db_show_one_runq(
911 run_queue_t runq)
912{
91447636 913 int i, task_id, thread_id;
1c79356b 914 queue_t q;
1c79356b
A
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) {
91447636 923 task = thread->task;
1c79356b 924 task_id = db_lookup_task(task);
91447636
A
925 thread_id = db_lookup_task_act(task, thread);
926 db_printf(" %d.%d", task_id, thread_id);
1c79356b
A
927 }
928 db_printf("\n");
929 }
930 }
931}