]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
de355530 A |
6 | * The contents of this file constitute Original Code as defined in and |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
1c79356b | 11 | * |
de355530 A |
12 | * This Original Code and all software distributed under the License are |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
de355530 A |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
1c79356b A |
19 | * |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* | |
23 | * @OSF_COPYRIGHT@ | |
24 | */ | |
25 | /* | |
26 | * HISTORY | |
27 | * | |
28 | * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez | |
29 | * Import of Mac OS X kernel (~semeria) | |
30 | * | |
31 | * Revision 1.2 1998/04/29 17:35:25 mburg | |
32 | * MK7.3 merger | |
33 | * | |
34 | * Revision 1.2.85.1 1998/02/03 09:24:09 gdt | |
35 | * Merge up to MK7.3 | |
36 | * [1998/02/03 09:10:24 gdt] | |
37 | * | |
38 | * Revision 1.2.81.1 1997/03/27 18:46:38 barbou | |
39 | * ri-osc CR1565 - clean up db_print_act, removing old !USER code | |
40 | * which had gotten stale (the option made little sense here anyway). | |
41 | * Added routine db_show_one_thread() to take either act/shuttle and | |
42 | * do something sensible. [dwm] Also rationalize plain, /u and /l | |
43 | * output for "show act", "show task" and "show all acts". | |
44 | * [1995/08/28 15:47:00 bolinger] | |
45 | * [97/02/25 barbou] | |
46 | * | |
47 | * Revision 1.2.31.13 1996/01/09 19:16:02 devrcs | |
48 | * Alpha kdebug Changes: | |
49 | * Correct various header spacing to account for 64-bit addresses. | |
50 | * Modify db_show_all_*() functions, so the can be called from kdebug. | |
51 | * ( There's no way to call with "char *modif", so added NULL check. ) | |
52 | * Changed db_error() calls to DB_ERROR() macro, so we return on error | |
53 | * on Alpha (we gotta return to kdebug). | |
54 | * Changed declarations of 'register foo' to 'register int foo'. | |
55 | * [1995/12/01 21:42:20 jfraser] | |
56 | * | |
57 | * Merged '64-bit safe' changes from DEC alpha port. | |
58 | * [1995/11/21 18:03:24 jfraser] | |
59 | * | |
60 | * Revision 1.2.31.12 1995/10/09 17:03:30 devrcs | |
61 | * Merge forward. | |
62 | * [1995/08/24 20:56:42 watkins] | |
63 | * | |
64 | * Revision 1.2.59.1 1995/08/04 17:03:17 watkins | |
65 | * Change to stack per shuttle model. | |
66 | * [1995/07/19 20:26:13 watkins] | |
67 | * | |
68 | * Revision 1.2.31.11 1995/09/18 19:08:49 devrcs | |
69 | * Merge forward. | |
70 | * [1995/08/24 20:56:42 watkins] | |
71 | * | |
72 | * Revision 1.2.59.1 1995/08/04 17:03:17 watkins | |
73 | * Change to stack per shuttle model. | |
74 | * [1995/07/19 20:26:13 watkins] | |
75 | * | |
76 | * Revision 1.2.31.10 1995/05/19 15:43:04 bernadat | |
77 | * Fixed db_print_act for empty activations. | |
78 | * Let thread swapping be configurable. | |
79 | * [95/05/19 bernadat] | |
80 | * | |
81 | * Revision 1.2.31.9 1995/05/14 18:10:25 dwm | |
82 | * ri-osc CR1304 - merge (nmk19_latest - nmk19b1) diffs into mainline. | |
83 | * mk6 CR938 - restore mach_msg hot path | |
84 | * remove use of now-defunct fields in thread [mmp,dwm] | |
85 | * [1995/05/14 17:25:05 dwm] | |
86 | * | |
87 | * Revision 1.2.31.8 1995/04/07 18:53:00 barbou | |
88 | * VM Merge - Task Swapper. | |
89 | * Renamed TH_SWAPPED to TH_STACK_HANDOFF and swap_func to continuation | |
90 | * to resolve name conflict. | |
91 | * From kernel/kdb/kdb_mach.c: | |
92 | * Put in changes for swapping. | |
93 | * [1991/11/21 20:32:15 mmp] | |
94 | * [94/07/27 barbou] | |
95 | * [95/03/08 barbou] | |
96 | * | |
97 | * Revision 1.2.31.7 1995/02/28 01:58:38 dwm | |
98 | * mk6 CR1120 - Merge mk6pro_shared into cnmk_shared | |
99 | * * Rev1.2.43.1 1995/01/27 22:01:26 bolinger | |
100 | * * Fix ri-osc CR977: Make "show space" and "show ipc_port" give | |
101 | * * accurate count of ports active in IPC space. Make "show ipc_port" | |
102 | * * output task-visible port name. | |
103 | * [1995/02/28 01:12:46 dwm] | |
104 | * | |
105 | * Revision 1.2.31.6 1995/02/23 21:43:34 alanl | |
106 | * Fix db_show_one_task_vm for thread_act_ts. | |
107 | * [95/01/09 rwd] | |
108 | * | |
109 | * Merged with DIPC2_SHARED. | |
110 | * [95/01/04 alanl] | |
111 | * | |
112 | * Revision 1.2.31.5 1995/01/10 04:49:52 devrcs | |
113 | * mk6 CR801 - merge up from nmk18b4 to nmk18b7 | |
114 | * Fix "sh thr/ul"; no cont. to print, fix pri/policy format. | |
115 | * * Rev 1.2.31.4 1994/10/11 16:35:58 emcmanus | |
116 | * Added "show runq" and "show shuttle". | |
117 | * [1994/12/09 20:36:49 dwm] | |
118 | * | |
119 | * mk6 CR668 - 1.3b26 merge | |
120 | * * Revision 1.2.8.6 1994/05/06 18:39:37 tmt | |
121 | * Merged osc1.3dec/shared with osc1.3b19 | |
122 | * Merge Alpha changes into osc1.312b source code. | |
123 | * 64bit cleanup. | |
124 | * * End1.3merge | |
125 | * [1994/11/04 08:49:52 dwm] | |
126 | * | |
127 | * Revision 1.2.31.3 1994/09/23 01:20:51 ezf | |
128 | * change marker to not FREE | |
129 | * [1994/09/22 21:10:41 ezf] | |
130 | * | |
131 | * Revision 1.2.31.2 1994/06/14 17:21:05 bolinger | |
132 | * Merge up to NMK17.2. | |
133 | * [1994/06/14 17:20:35 bolinger] | |
134 | * | |
135 | * Revision 1.2.23.4 1994/04/15 18:41:31 paire | |
136 | * Changed interface of db_task_from_space routine. | |
137 | * [94/03/31 paire] | |
138 | * | |
139 | * Revision 1.2.23.3 1994/03/07 16:37:48 paire | |
140 | * Merge with Intel R1_1 | |
141 | * Change from NMK14.10 [1993/11/15 16:06:21 rwd] | |
142 | * | |
143 | * Enhanced pretty print routine and added db_task_from_space. | |
144 | * Change from NMK14.10 [93/09/24 sjs] | |
145 | * [94/02/21 paire] | |
146 | * | |
147 | * Exported ANSI prototype of db_port_kmsg_count routine. | |
148 | * Added header file include for the declaration of db_norma_ipc routine. | |
149 | * [94/02/15 paire] | |
150 | * | |
151 | * Revision 1.2.23.2 1994/02/11 14:21:58 paire | |
152 | * Added new vm_print.h header file for db_vm declaration. | |
153 | * [94/02/09 paire] | |
154 | * | |
155 | * Revision 1.2.23.1 1994/02/08 10:58:19 bernadat | |
156 | * print out msgcount for each port in db_port_iterate | |
157 | * Change from NORMA_MK14.6(August 93) [1993/07/27 12:35:17 mmp] | |
158 | * | |
159 | * Removed defintion of db_maxoff (got from <ddb/db_sym.h>). | |
160 | * [93/08/12 paire] | |
161 | * | |
162 | * Show ipc_space_remote msg counts only if NORMA_IPC is on | |
163 | * [93/07/21 bernadat] | |
164 | * | |
165 | * Add /s option to "show ipc_port" to pick out port sets. | |
166 | * Change from NORMA_MK14.6 [1993/02/17 16:29:54 dwm] | |
167 | * [93/07/16 bernadat] | |
168 | * [94/02/07 bernadat] | |
169 | * | |
170 | * Revision 1.2.20.8 1994/06/08 19:11:15 dswartz | |
171 | * Preemption merge. | |
172 | * [1994/06/08 19:10:18 dswartz] | |
173 | * | |
174 | * Revision 1.2.20.7 1994/04/30 21:28:24 bolinger | |
175 | * Thread control ops synchronization: now that TH_SUSP is back, | |
176 | * enable ddb to show it when printing thread state. | |
177 | * [1994/04/28 21:55:42 bolinger] | |
178 | * | |
179 | * Revision 1.2.20.6 1994/03/17 22:35:31 dwm | |
180 | * The infamous name change: thread_activation + thread_shuttle = thread. | |
181 | * [1994/03/17 21:25:46 dwm] | |
182 | * | |
183 | * Revision 1.2.20.5 1994/01/26 15:43:37 bolinger | |
184 | * Move kernel_stack from thread to activation. | |
185 | * [1994/01/25 21:53:11 bolinger] | |
186 | * | |
187 | * Revision 1.2.20.4 1994/01/12 17:50:44 dwm | |
188 | * Coloc: initial restructuring to follow Utah model. | |
189 | * [1994/01/12 17:13:12 dwm] | |
190 | * | |
191 | * Revision 1.2.20.3 1993/11/18 18:11:47 dwm | |
192 | * Coloc: remove continuations entirely; they are incompatible | |
193 | * with migration, and their volume is obfuscatory. | |
194 | * [1993/11/18 18:06:27 dwm] | |
195 | * | |
196 | * Revision 1.2.20.2 1993/10/12 16:38:50 dwm | |
197 | * CoLoc: neuter continuations, ifdef USE_CONTINUATIONS. | |
198 | * [1993/10/12 16:14:46 dwm] | |
199 | * | |
200 | * Revision 1.2.8.4 1993/08/11 20:38:06 elliston | |
201 | * Add ANSI Prototypes. CR #9523. | |
202 | * [1993/08/11 03:33:51 elliston] | |
203 | * | |
204 | * Revision 1.2.8.3 1993/07/27 18:27:55 elliston | |
205 | * Add ANSI prototypes. CR #9523. | |
206 | * [1993/07/27 18:12:39 elliston] | |
207 | * | |
208 | * Revision 1.2.8.2 1993/06/09 02:20:35 gm | |
209 | * CR9176 - ANSI C violations: trailing tokens on CPP | |
210 | * directives, extra semicolons after decl_ ..., asm keywords | |
211 | * [1993/06/07 18:57:22 jeffc] | |
212 | * | |
213 | * Removed a '#if MACH_FIXPRI' which somehow survived the purge. CR #9131. | |
214 | * [1993/05/11 20:56:00 dswartz] | |
215 | * | |
216 | * Revision 1.2 1993/04/19 16:02:50 devrcs | |
217 | * Added printout of thread scheduling policy to long form | |
218 | * of thread display. | |
219 | * [93/01/28 jat] | |
220 | * | |
221 | * Changes from mk78: | |
222 | * Removed unused variable from db_show_regs(). | |
223 | * [92/05/16 jfriedl] | |
224 | * Converted some db_printsyms to db_task_printsyms. | |
225 | * [92/04/10 danner] | |
226 | * Changed db_print_thread so that both display formats | |
227 | * show the floating-point-used status of the thread. | |
228 | * [92/03/16 rpd] | |
229 | * [93/02/02 bruel] | |
230 | * | |
231 | * Revision 1.1 1992/09/30 02:01:18 robert | |
232 | * Initial revision | |
233 | * | |
234 | * $EndLog$ | |
235 | */ | |
236 | /* CMU_HIST */ | |
237 | /* | |
238 | * Revision 2.11.3.2 92/04/08 15:43:10 jeffreyh | |
239 | * Added i option to show thread. This gives wait state information. | |
240 | * [92/04/08 sjs] | |
241 | * | |
242 | * Revision 2.11.3.1 92/03/03 16:13:34 jeffreyh | |
243 | * Pick up changes from TRUNK | |
244 | * [92/02/26 11:00:01 jeffreyh] | |
245 | * | |
246 | * Revision 2.13 92/02/20 18:34:28 elf | |
247 | * Fixed typo. | |
248 | * [92/02/20 elf] | |
249 | * | |
250 | * Revision 2.12 92/02/19 15:07:47 elf | |
251 | * Added db_thread_fp_used, to avoid machine-dependent conditionals. | |
252 | * [92/02/19 rpd] | |
253 | * | |
254 | * Added 'F' flag to db_thread_stat showing if the thread has a valid | |
255 | * FPU context. Tested on i386 and pmax. | |
256 | * [92/02/17 kivinen] | |
257 | * | |
258 | * Revision 2.11 91/11/12 11:50:32 rvb | |
259 | * Added OPTION_USER ("/u") to db_show_all_threads, db_show_one_thread, | |
260 | * db_show_one_task. Without it, we display old-style information. | |
261 | * [91/10/31 rpd] | |
262 | * | |
263 | * Revision 2.10 91/10/09 16:01:48 af | |
264 | * Supported "show registers" for non current thread. | |
265 | * Changed display format of thread and task information. | |
266 | * Changed "show thread" to print current thread information | |
267 | * if no thread is specified. | |
268 | * Added "show_one_task" for "show task" command. | |
269 | * Added IPC port print routines for "show ipc_port" command. | |
270 | * [91/08/29 tak] | |
271 | * | |
272 | * Revision 2.9 91/08/03 18:17:19 jsb | |
273 | * In db_print_thread, if the thread is swapped and there is a | |
274 | * continuation function, print the function name in parentheses | |
275 | * instead of '(swapped)'. | |
276 | * [91/07/04 09:59:27 jsb] | |
277 | * | |
278 | * Revision 2.8 91/07/31 17:30:43 dbg | |
279 | * Revise scheduling state machine. | |
280 | * [91/07/30 16:43:42 dbg] | |
281 | * | |
282 | * Revision 2.7 91/07/09 23:15:57 danner | |
283 | * Fixed a few printf that should be db_printfs. | |
284 | * [91/07/08 danner] | |
285 | * | |
286 | * Revision 2.6 91/05/14 15:35:25 mrt | |
287 | * Correcting copyright | |
288 | * | |
289 | * Revision 2.5 91/02/05 17:06:53 mrt | |
290 | * Changed to new Mach copyright | |
291 | * [91/01/31 16:18:56 mrt] | |
292 | * | |
293 | * Revision 2.4 90/10/25 14:43:54 rwd | |
294 | * Changed db_show_regs to print unsigned. | |
295 | * [90/10/19 rpd] | |
296 | * Generalized the watchpoint support. | |
297 | * [90/10/16 rwd] | |
298 | * | |
299 | * Revision 2.3 90/09/09 23:19:52 rpd | |
300 | * Avoid totally incorrect guesses of symbol names for small values. | |
301 | * [90/08/30 17:39:08 af] | |
302 | * | |
303 | * Revision 2.2 90/08/27 21:51:49 dbg | |
304 | * Insist that 'show thread' be called with an explicit address. | |
305 | * [90/08/22 dbg] | |
306 | * | |
307 | * Fix type for db_maxoff. | |
308 | * [90/08/20 dbg] | |
309 | * | |
310 | * Do not dereference the "valuep" field of a variable directly, | |
311 | * call the new db_read/write_variable functions instead. | |
312 | * Reflected changes in symbol lookup functions. | |
313 | * [90/08/20 af] | |
314 | * Reduce lint. | |
315 | * [90/08/10 14:33:44 dbg] | |
316 | * | |
317 | * Created. | |
318 | * [90/07/25 dbg] | |
319 | * | |
320 | */ | |
321 | /* CMU_ENDHIST */ | |
322 | /* | |
323 | * Mach Operating System | |
324 | * Copyright (c) 1991,1990 Carnegie Mellon University | |
325 | * All Rights Reserved. | |
326 | * | |
327 | * Permission to use, copy, modify and distribute this software and its | |
328 | * documentation is hereby granted, provided that both the copyright | |
329 | * notice and this permission notice appear in all copies of the | |
330 | * software, derivative works or modified versions, and any portions | |
331 | * thereof, and that both notices appear in supporting documentation. | |
332 | * | |
333 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
334 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
335 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
336 | * | |
337 | * Carnegie Mellon requests users of this software to return to | |
338 | * | |
339 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
340 | * School of Computer Science | |
341 | * Carnegie Mellon University | |
342 | * Pittsburgh PA 15213-3890 | |
343 | * | |
344 | * any improvements or extensions that they make and grant Carnegie Mellon | |
345 | * the rights to redistribute these changes. | |
346 | */ | |
347 | /* | |
348 | */ | |
349 | /* | |
350 | * Author: David B. Golub, Carnegie Mellon University | |
351 | * Date: 7/90 | |
352 | */ | |
353 | ||
354 | /* | |
355 | * Miscellaneous printing. | |
356 | */ | |
357 | #include <dipc.h> | |
358 | #include <task_swapper.h> | |
359 | ||
360 | #include <string.h> /* For strlen() */ | |
361 | #include <mach/port.h> | |
362 | #include <kern/task.h> | |
363 | #include <kern/thread.h> | |
364 | #include <kern/thread_swap.h> | |
365 | #include <kern/queue.h> | |
366 | #include <ipc/ipc_port.h> | |
367 | #include <ipc/ipc_space.h> | |
368 | #include <ipc/ipc_pset.h> | |
369 | #include <vm/vm_print.h> /* for db_vm() */ | |
370 | ||
371 | #include <machine/db_machdep.h> | |
372 | #include <machine/thread.h> | |
373 | ||
374 | #include <ddb/db_lex.h> | |
375 | #include <ddb/db_variables.h> | |
376 | #include <ddb/db_sym.h> | |
377 | #include <ddb/db_task_thread.h> | |
378 | #include <ddb/db_command.h> | |
379 | #include <ddb/db_output.h> /* For db_printf() */ | |
380 | #include <ddb/db_print.h> | |
381 | ||
382 | #include <kern/sf.h> | |
383 | #include <kern/sp_mk.h> /*** ??? fix so this can be removed ***/ | |
384 | ||
385 | #if TASK_SWAPPER | |
386 | #include <kern/task_swap.h> | |
387 | #endif /* TASK_SWAPPER */ | |
388 | ||
389 | /* Prototypes for functions local to this file. XXX -- should be static! | |
390 | */ | |
391 | ||
392 | char *db_act_stat( | |
393 | register thread_act_t thr_act, | |
394 | char *status); | |
395 | ||
396 | char *db_act_swap_stat( | |
397 | register thread_act_t thr_act, | |
398 | char *status); | |
399 | ||
400 | void db_print_task( | |
401 | task_t task, | |
402 | int task_id, | |
403 | int flag); | |
404 | ||
405 | void db_reset_print_entry( | |
406 | void); | |
407 | ||
408 | void db_print_one_entry( | |
409 | ipc_entry_t entry, | |
410 | int index, | |
411 | mach_port_name_t name, | |
412 | boolean_t is_pset); | |
413 | ||
414 | int db_port_iterate( | |
415 | thread_act_t thr_act, | |
416 | boolean_t is_pset, | |
417 | boolean_t do_output); | |
418 | ||
419 | ipc_port_t db_lookup_port( | |
420 | thread_act_t thr_act, | |
421 | int id); | |
422 | ||
423 | static void db_print_port_id( | |
424 | int id, | |
425 | ipc_port_t port, | |
426 | unsigned bits, | |
427 | int n); | |
428 | ||
429 | void db_print_act( | |
430 | thread_act_t thr_act, | |
431 | int act_id, | |
432 | int flag); | |
433 | ||
434 | void db_print_space( | |
435 | task_t task, | |
436 | int task_id, | |
437 | int flag); | |
438 | ||
439 | void db_print_task_vm( | |
440 | task_t task, | |
441 | int task_id, | |
442 | boolean_t title, | |
443 | char *modif); | |
444 | ||
445 | void db_system_stats(void); | |
446 | ||
447 | ||
448 | void | |
449 | db_show_regs( | |
450 | db_expr_t addr, | |
451 | boolean_t have_addr, | |
452 | db_expr_t count, | |
453 | char *modif) | |
454 | { | |
455 | register struct db_variable *regp; | |
456 | db_expr_t value; | |
457 | db_addr_t offset; | |
458 | char * name; | |
459 | register int i; | |
460 | struct db_var_aux_param aux_param; | |
461 | task_t task = TASK_NULL; | |
462 | ||
463 | aux_param.modif = modif; | |
464 | aux_param.thr_act = THR_ACT_NULL; | |
465 | if (db_option(modif, 't')) { | |
466 | if (have_addr) { | |
467 | if (!db_check_act_address_valid((thread_act_t)addr)) | |
468 | return; | |
469 | aux_param.thr_act = (thread_act_t)addr; | |
470 | } else | |
471 | aux_param.thr_act = db_default_act; | |
472 | if (aux_param.thr_act != THR_ACT_NULL) | |
473 | task = aux_param.thr_act->task; | |
474 | } | |
475 | for (regp = db_regs; regp < db_eregs; regp++) { | |
476 | if (regp->max_level > 1) { | |
477 | db_printf("bad multi-suffixed register %s\n", regp->name); | |
478 | continue; | |
479 | } | |
480 | aux_param.level = regp->max_level; | |
481 | for (i = regp->low; i <= regp->high; i++) { | |
482 | aux_param.suffix[0] = i; | |
483 | db_read_write_variable(regp, &value, DB_VAR_GET, &aux_param); | |
484 | if (regp->max_level > 0) | |
485 | db_printf("%s%d%*s", regp->name, i, | |
486 | 12-strlen(regp->name)-((i<10)?1:2), ""); | |
487 | else | |
488 | db_printf("%-12s", regp->name); | |
489 | db_printf("%#*N", 2+2*sizeof(vm_offset_t), value); | |
490 | db_find_xtrn_task_sym_and_offset((db_addr_t)value, &name, | |
491 | &offset, task); | |
492 | if (name != 0 && offset <= db_maxoff && offset != value) { | |
493 | db_printf("\t%s", name); | |
494 | if (offset != 0) | |
495 | db_printf("+%#r", offset); | |
496 | } | |
497 | db_printf("\n"); | |
498 | } | |
499 | } | |
500 | } | |
501 | ||
502 | #define OPTION_LONG 0x001 /* long print option */ | |
503 | #define OPTION_USER 0x002 /* print ps-like stuff */ | |
504 | #define OPTION_INDENT 0x100 /* print with indent */ | |
505 | #define OPTION_THREAD_TITLE 0x200 /* print thread title */ | |
506 | #define OPTION_TASK_TITLE 0x400 /* print thread title */ | |
507 | ||
508 | #ifndef DB_TASK_NAME | |
509 | #define DB_TASK_NAME(task) /* no task name */ | |
510 | #define DB_TASK_NAME_TITLE "" /* no task name */ | |
511 | #endif /* DB_TASK_NAME */ | |
512 | ||
513 | #ifndef db_act_fp_used | |
514 | #define db_act_fp_used(thr_act) FALSE | |
515 | #endif | |
516 | ||
517 | char * | |
518 | db_act_stat( | |
519 | register thread_act_t thr_act, | |
520 | char *status) | |
521 | { | |
522 | register char *p = status; | |
523 | ||
524 | if (!thr_act->active) { | |
525 | *p++ = 'D', | |
526 | *p++ = 'y', | |
527 | *p++ = 'i', | |
528 | *p++ = 'n', | |
529 | *p++ = 'g'; | |
530 | *p++ = ' '; | |
531 | } else if (!thr_act->thread) { | |
532 | *p++ = 'E', | |
533 | *p++ = 'm', | |
534 | *p++ = 'p', | |
535 | *p++ = 't', | |
536 | *p++ = 'y'; | |
537 | *p++ = ' '; | |
538 | } else { | |
539 | thread_t athread = thr_act->thread; | |
540 | ||
541 | *p++ = (athread->state & TH_RUN) ? 'R' : '.'; | |
542 | *p++ = (athread->state & TH_WAIT) ? 'W' : '.'; | |
543 | *p++ = (athread->state & TH_SUSP) ? 'S' : '.'; | |
544 | *p++ = (athread->state & TH_SWAPPED_OUT) ? 'O' : '.'; | |
545 | *p++ = (athread->state & TH_UNINT) ? 'N' : '.'; | |
546 | /* show if the FPU has been used */ | |
547 | *p++ = db_act_fp_used(thr_act) ? 'F' : '.'; | |
548 | } | |
549 | *p++ = 0; | |
550 | return(status); | |
551 | } | |
552 | ||
553 | char * | |
554 | db_act_swap_stat( | |
555 | register thread_act_t thr_act, | |
556 | char *status) | |
557 | { | |
558 | register char *p = status; | |
559 | ||
560 | #if THREAD_SWAPPER | |
561 | switch (thr_act->swap_state & TH_SW_STATE) { | |
562 | case TH_SW_UNSWAPPABLE: | |
563 | *p++ = 'U'; | |
564 | break; | |
565 | case TH_SW_IN: | |
566 | *p++ = 'I'; | |
567 | break; | |
568 | case TH_SW_GOING_OUT: | |
569 | *p++ = 'G'; | |
570 | break; | |
571 | case TH_SW_WANT_IN: | |
572 | *p++ = 'W'; | |
573 | break; | |
574 | case TH_SW_OUT: | |
575 | *p++ = 'O'; | |
576 | break; | |
577 | case TH_SW_COMING_IN: | |
578 | *p++ = 'C'; | |
579 | break; | |
580 | default: | |
581 | *p++ = '?'; | |
582 | break; | |
583 | } | |
584 | *p++ = (thr_act->swap_state & TH_SW_TASK_SWAPPING) ? 'T' : '.'; | |
585 | #endif /* THREAD_SWAPPER */ | |
586 | *p++ = 0; | |
587 | ||
588 | return status; | |
589 | } | |
590 | ||
591 | char *policy_list[] = { "TS", "RR", "??", "FF", | |
592 | "??", "??", "??", "BE"}; | |
593 | ||
594 | void | |
595 | db_print_act( | |
596 | thread_act_t thr_act, | |
597 | int act_id, | |
598 | int flag) | |
599 | { | |
600 | thread_t athread; | |
601 | char status[8]; | |
602 | char swap_status[3]; | |
603 | char *indent = ""; | |
604 | int policy; | |
605 | ||
606 | if (!thr_act) { | |
607 | db_printf("db_print_act(NULL)!\n"); | |
608 | return; | |
609 | } | |
610 | ||
611 | athread = thr_act->thread; | |
612 | if (flag & OPTION_USER) { | |
613 | ||
614 | if (flag & OPTION_LONG) { | |
615 | if (flag & OPTION_INDENT) | |
616 | indent = " "; | |
617 | if (flag & OPTION_THREAD_TITLE) { | |
618 | db_printf("%s ID: ACT STAT SW STACK SHUTTLE", indent); | |
619 | db_printf(" SUS PRI WAIT_FUNC\n"); | |
620 | } | |
621 | policy = (athread ? athread->policy : 2); | |
622 | db_printf("%s%3d%c %0*X %s %s %0*X %0*X %3d %3d/%s ", | |
623 | indent, act_id, | |
624 | (thr_act == current_act())? '#': ':', | |
625 | 2*sizeof(vm_offset_t), thr_act, | |
626 | db_act_stat(thr_act, status), | |
627 | db_act_swap_stat(thr_act, swap_status), | |
628 | 2*sizeof(vm_offset_t), (athread ?athread->kernel_stack:0), | |
629 | 2*sizeof(vm_offset_t), athread, | |
630 | thr_act->suspend_count, | |
631 | (athread ? athread->sched_pri : 999), /* XXX */ | |
632 | policy_list[policy-1]); | |
633 | if (athread) { | |
634 | /* no longer TH_SWAP, no continuation to print */ | |
635 | if (athread->state & TH_WAIT) | |
636 | db_task_printsym((db_addr_t)athread->wait_event, | |
637 | DB_STGY_ANY, kernel_task); | |
638 | } | |
639 | db_printf("\n"); | |
640 | } else { | |
641 | if (act_id % 3 == 0) { | |
642 | if (flag & OPTION_INDENT) | |
643 | db_printf("\n "); | |
644 | } else | |
645 | db_printf(" "); | |
646 | db_printf("%3d%c(%0*X,%s)", act_id, | |
647 | (thr_act == current_act())? '#': ':', | |
648 | 2*sizeof(vm_offset_t), thr_act, | |
649 | db_act_stat(thr_act, status)); | |
650 | } | |
651 | } else { | |
652 | if (flag & OPTION_INDENT) | |
653 | db_printf(" %3d (%0*X) ", act_id, | |
654 | 2*sizeof(vm_offset_t), thr_act); | |
655 | else | |
656 | db_printf("(%0*X) ", 2*sizeof(vm_offset_t), thr_act); | |
657 | if (athread) { | |
658 | db_printf("%c%c%c%c%c", | |
659 | (athread->state & TH_RUN) ? 'R' : ' ', | |
660 | (athread->state & TH_WAIT) ? 'W' : ' ', | |
661 | (athread->state & TH_SUSP) ? 'S' : ' ', | |
662 | (athread->state & TH_UNINT)? 'N' : ' ', | |
663 | db_act_fp_used(thr_act) ? 'F' : ' '); | |
664 | /* Obsolete TH_STACK_HANDOFF code, left for now; might enhance | |
665 | * to print out safe_points instead */ | |
666 | if (athread->state & TH_STACK_HANDOFF) { | |
667 | if (athread->continuation) { | |
668 | db_printf("("); | |
669 | db_task_printsym((db_addr_t)athread->continuation, | |
670 | DB_STGY_ANY, kernel_task); | |
671 | db_printf(")"); | |
672 | } else { | |
673 | db_printf("(handoff)"); | |
674 | } | |
675 | } | |
676 | if (athread->state & TH_WAIT) { | |
677 | db_printf(" "); | |
678 | db_task_printsym((db_addr_t)athread->wait_event, | |
679 | DB_STGY_ANY, kernel_task); | |
680 | } | |
681 | } else | |
682 | db_printf("Empty"); | |
683 | db_printf("\n"); | |
684 | } | |
685 | } | |
686 | ||
687 | void | |
688 | db_print_task( | |
689 | task_t task, | |
690 | int task_id, | |
691 | int flag) | |
692 | { | |
693 | thread_act_t thr_act; | |
694 | int act_id; | |
695 | char sstate; | |
696 | ||
697 | if (flag & OPTION_USER) { | |
698 | if (flag & OPTION_TASK_TITLE) { | |
699 | db_printf(" ID: TASK MAP THD RES SUS PR SW %s", | |
700 | DB_TASK_NAME_TITLE); | |
701 | if ((flag & OPTION_LONG) == 0) | |
702 | db_printf(" ACTS"); | |
703 | db_printf("\n"); | |
704 | } | |
705 | #if TASK_SWAPPER | |
706 | switch ((int) task->swap_state) { | |
707 | case TASK_SW_IN: | |
708 | sstate = 'I'; | |
709 | break; | |
710 | case TASK_SW_OUT: | |
711 | sstate = 'O'; | |
712 | break; | |
713 | case TASK_SW_GOING_OUT: | |
714 | sstate = 'G'; | |
715 | break; | |
716 | case TASK_SW_COMING_IN: | |
717 | sstate = 'C'; | |
718 | break; | |
719 | case TASK_SW_UNSWAPPABLE: | |
720 | sstate = 'U'; | |
721 | break; | |
722 | default: | |
723 | sstate = '?'; | |
724 | break; | |
725 | } | |
726 | #else /* TASK_SWAPPER */ | |
727 | sstate = 'I'; | |
728 | #endif /* TASK_SWAPPER */ | |
729 | /*** ??? fix me ***/ | |
730 | db_printf("%3d: %0*X %0*X %3d %3d %3d %2d %c ", | |
731 | task_id, 2*sizeof(vm_offset_t), task, | |
732 | 2*sizeof(vm_offset_t), task->map, | |
733 | task->thr_act_count, task->res_act_count, | |
734 | task->suspend_count, | |
735 | ((mk_sp_attributes_t)(task->sp_attributes))->priority, | |
736 | sstate); | |
737 | DB_TASK_NAME(task); | |
738 | if (flag & OPTION_LONG) { | |
739 | if (flag & OPTION_TASK_TITLE) | |
740 | flag |= OPTION_THREAD_TITLE; | |
741 | db_printf("\n"); | |
742 | } else if (task->thr_act_count <= 1) | |
743 | flag &= ~OPTION_INDENT; | |
744 | act_id = 0; | |
745 | queue_iterate(&task->thr_acts, thr_act, thread_act_t, thr_acts) { | |
746 | db_print_act(thr_act, act_id, flag); | |
747 | flag &= ~OPTION_THREAD_TITLE; | |
748 | act_id++; | |
749 | } | |
750 | if ((flag & OPTION_LONG) == 0) | |
751 | db_printf("\n"); | |
752 | } else { | |
753 | if (flag & OPTION_LONG) { | |
754 | if (flag & OPTION_TASK_TITLE) { | |
755 | db_printf(" TASK ACT\n"); | |
756 | if (task->thr_act_count > 1) | |
757 | flag |= OPTION_THREAD_TITLE; | |
758 | } | |
759 | } | |
760 | db_printf("%3d (%0*X): ", task_id, 2*sizeof(vm_offset_t), task); | |
761 | if (task->thr_act_count == 0) { | |
762 | db_printf("no threads\n"); | |
763 | } else { | |
764 | if (task->thr_act_count > 1) { | |
765 | db_printf("%d threads: \n", task->thr_act_count); | |
766 | flag |= OPTION_INDENT; | |
767 | } else | |
768 | flag &= ~OPTION_INDENT; | |
769 | act_id = 0; | |
770 | queue_iterate(&task->thr_acts, thr_act, | |
771 | thread_act_t, thr_acts) { | |
772 | db_print_act(thr_act, act_id++, flag); | |
773 | flag &= ~OPTION_THREAD_TITLE; | |
774 | } | |
775 | } | |
776 | } | |
777 | } | |
778 | ||
779 | void | |
780 | db_print_space( | |
781 | task_t task, | |
782 | int task_id, | |
783 | int flag) | |
784 | { | |
785 | ipc_space_t space; | |
786 | thread_act_t act = (thread_act_t)queue_first(&task->thr_acts); | |
787 | int count; | |
788 | ||
789 | count = 0; | |
790 | space = task->itk_space; | |
791 | if (act) | |
792 | count = db_port_iterate(act, FALSE, FALSE); | |
793 | db_printf("%3d: %08x %08x %08x %sactive %d\n", | |
794 | task_id, task, space, task->map, | |
795 | space->is_active? "":"!", count); | |
796 | } | |
797 | ||
798 | void | |
799 | db_print_task_vm( | |
800 | task_t task, | |
801 | int task_id, | |
802 | boolean_t title, | |
803 | char *modif) | |
804 | { | |
805 | vm_map_t map; | |
806 | pmap_t pmap; | |
807 | vm_size_t size; | |
808 | long resident; | |
809 | long wired; | |
810 | ||
811 | if (title) { | |
812 | db_printf("id task map pmap virtual rss pg rss mem wir pg wir mem\n"); | |
813 | } | |
814 | ||
815 | map = task->map; | |
816 | pmap = vm_map_pmap(map); | |
817 | ||
818 | size = db_vm_map_total_size(map); | |
819 | resident = pmap->stats.resident_count; | |
820 | wired = pmap->stats.wired_count; | |
821 | ||
822 | db_printf("%2d %08x %08x %08x %7dK %6d %6dK %6d %6dK\n", | |
823 | task_id, | |
824 | task, | |
825 | map, | |
826 | pmap, | |
827 | size / 1024, | |
828 | resident, (resident * PAGE_SIZE) / 1024, | |
829 | wired, (wired * PAGE_SIZE) / 1024); | |
830 | } | |
831 | ||
832 | ||
833 | void | |
834 | db_show_one_task_vm( | |
835 | db_expr_t addr, | |
836 | boolean_t have_addr, | |
837 | db_expr_t count, | |
838 | char *modif) | |
839 | { | |
840 | thread_act_t thread; | |
841 | task_t task; | |
842 | int task_id; | |
843 | ||
844 | if (have_addr == FALSE) { | |
845 | if ((thread = db_default_act) == THR_ACT_NULL) { | |
846 | if ((thread = current_act()) == THR_ACT_NULL) { | |
847 | db_printf("no thread.\n"); | |
848 | return; | |
849 | } | |
850 | } | |
851 | task = thread->task; | |
852 | } else { | |
853 | task = (task_t) addr; | |
854 | } | |
855 | ||
856 | task_id = db_lookup_task(task); | |
857 | if (task_id < 0) { | |
858 | db_printf("0x%x is not a task_t\n", addr); | |
859 | return; | |
860 | } | |
861 | ||
862 | db_print_task_vm(task, task_id, TRUE, modif); | |
863 | } | |
864 | ||
865 | void | |
866 | db_show_all_task_vm( | |
867 | db_expr_t addr, | |
868 | boolean_t have_addr, | |
869 | db_expr_t count, | |
870 | char *modif) | |
871 | { | |
872 | task_t task; | |
873 | int task_id; | |
874 | boolean_t title = TRUE; | |
875 | processor_set_t pset; | |
876 | ||
877 | task_id = 0; | |
878 | queue_iterate(&all_psets, pset, processor_set_t, all_psets) { | |
879 | queue_iterate(&pset->tasks, task, task_t, pset_tasks) { | |
880 | db_print_task_vm(task, task_id, title, modif); | |
881 | title = FALSE; | |
882 | task_id++; | |
883 | } | |
884 | } | |
885 | } | |
886 | ||
887 | void | |
888 | db_show_all_acts( | |
889 | db_expr_t addr, | |
890 | boolean_t have_addr, | |
891 | db_expr_t count, | |
892 | char * modif) | |
893 | { | |
894 | task_t task; | |
895 | int task_id; | |
896 | int flag; | |
897 | processor_set_t pset; | |
898 | ||
899 | flag = OPTION_TASK_TITLE|OPTION_INDENT; | |
900 | if (db_option(modif, 'u')) | |
901 | flag |= OPTION_USER; | |
902 | if (db_option(modif, 'l')) | |
903 | flag |= OPTION_LONG; | |
904 | ||
905 | task_id = 0; | |
906 | queue_iterate(&all_psets, pset, processor_set_t, all_psets) { | |
907 | queue_iterate(&pset->tasks, task, task_t, pset_tasks) { | |
908 | db_print_task(task, task_id, flag); | |
909 | flag &= ~OPTION_TASK_TITLE; | |
910 | task_id++; | |
911 | if ((flag & (OPTION_LONG|OPTION_INDENT)) == OPTION_INDENT) | |
912 | db_printf("\n"); | |
913 | } | |
914 | } | |
915 | } | |
916 | ||
917 | void | |
918 | db_show_one_space( | |
919 | db_expr_t addr, | |
920 | boolean_t have_addr, | |
921 | db_expr_t count, | |
922 | char * modif) | |
923 | { | |
924 | int flag; | |
925 | int task_id; | |
926 | task_t task; | |
927 | ||
928 | flag = OPTION_TASK_TITLE; | |
929 | if (db_option(modif, 'u')) | |
930 | flag |= OPTION_USER; | |
931 | if (db_option(modif, 'l')) | |
932 | flag |= OPTION_LONG; | |
933 | ||
934 | if (!have_addr) { | |
935 | task = db_current_task(); | |
936 | if (task == TASK_NULL) { | |
937 | db_error("No task\n"); | |
938 | /*NOTREACHED*/ | |
939 | } | |
940 | } else | |
941 | task = (task_t) addr; | |
942 | ||
943 | if ((task_id = db_lookup_task(task)) < 0) { | |
944 | db_printf("bad task address 0x%x\n", addr); | |
945 | db_error(0); | |
946 | /*NOTREACHED*/ | |
947 | } | |
948 | ||
949 | db_printf(" ID: TASK SPACE MAP COUNT\n"); | |
950 | db_print_space(task, task_id, flag); | |
951 | } | |
952 | ||
953 | void | |
954 | db_show_all_spaces( | |
955 | db_expr_t addr, | |
956 | boolean_t have_addr, | |
957 | db_expr_t count, | |
958 | char * modif) | |
959 | { | |
960 | task_t task; | |
961 | int task_id = 0; | |
962 | int flag; | |
963 | processor_set_t pset; | |
964 | ||
965 | flag = OPTION_TASK_TITLE|OPTION_INDENT; | |
966 | if (db_option(modif, 'u')) | |
967 | flag |= OPTION_USER; | |
968 | if (db_option(modif, 'l')) | |
969 | flag |= OPTION_LONG; | |
970 | ||
971 | db_printf(" ID: TASK SPACE MAP COUNT\n"); | |
972 | queue_iterate(&all_psets, pset, processor_set_t, all_psets) { | |
973 | queue_iterate(&pset->tasks, task, task_t, pset_tasks) { | |
974 | db_print_space(task, task_id, flag); | |
975 | task_id++; | |
976 | } | |
977 | } | |
978 | } | |
979 | ||
980 | db_addr_t | |
981 | db_task_from_space( | |
982 | ipc_space_t space, | |
983 | int *task_id) | |
984 | { | |
985 | task_t task; | |
986 | int tid = 0; | |
987 | processor_set_t pset; | |
988 | ||
989 | queue_iterate(&all_psets, pset, processor_set_t, all_psets) { | |
990 | queue_iterate(&pset->tasks, task, task_t, pset_tasks) { | |
991 | if (task->itk_space == space) { | |
992 | *task_id = tid; | |
993 | return (db_addr_t)task; | |
994 | } | |
995 | tid++; | |
996 | } | |
997 | } | |
998 | *task_id = 0; | |
999 | return (0); | |
1000 | } | |
1001 | ||
1002 | void | |
1003 | db_show_one_act( | |
1004 | db_expr_t addr, | |
1005 | boolean_t have_addr, | |
1006 | db_expr_t count, | |
1007 | char * modif) | |
1008 | { | |
1009 | int flag; | |
1010 | int act_id; | |
1011 | thread_act_t thr_act; | |
1012 | ||
1013 | flag = OPTION_THREAD_TITLE; | |
1014 | if (db_option(modif, 'u')) | |
1015 | flag |= OPTION_USER; | |
1016 | if (db_option(modif, 'l')) | |
1017 | flag |= OPTION_LONG; | |
1018 | ||
1019 | if (!have_addr) { | |
1020 | thr_act = current_act(); | |
1021 | if (thr_act == THR_ACT_NULL) { | |
1022 | db_error("No thr_act\n"); | |
1023 | /*NOTREACHED*/ | |
1024 | } | |
1025 | } else | |
1026 | thr_act = (thread_act_t) addr; | |
1027 | ||
1028 | if ((act_id = db_lookup_act(thr_act)) < 0) { | |
1029 | db_printf("bad thr_act address %#x\n", addr); | |
1030 | db_error(0); | |
1031 | /*NOTREACHED*/ | |
1032 | } | |
1033 | ||
1034 | if (flag & OPTION_USER) { | |
1035 | db_printf("TASK%d(%0*X):\n", | |
1036 | db_lookup_task(thr_act->task), | |
1037 | 2*sizeof(vm_offset_t), thr_act->task); | |
1038 | db_print_act(thr_act, act_id, flag); | |
1039 | } else { | |
1040 | db_printf("task %d(%0*Xx): thr_act %d", | |
1041 | db_lookup_task(thr_act->task), | |
1042 | 2*sizeof(vm_offset_t), thr_act->task, act_id); | |
1043 | db_print_act(thr_act, act_id, flag); | |
1044 | } | |
1045 | if (db_option(modif, 'i') && thr_act->thread && | |
1046 | (thr_act->thread->state & TH_WAIT) && | |
1047 | thr_act->thread->kernel_stack == 0) { | |
1048 | ||
1049 | db_printf("Wait State: option 0x%x\n", | |
1050 | thr_act->thread->ith_option); | |
1051 | } | |
1052 | } | |
1053 | ||
1054 | void | |
1055 | db_show_one_task( | |
1056 | db_expr_t addr, | |
1057 | boolean_t have_addr, | |
1058 | db_expr_t count, | |
1059 | char * modif) | |
1060 | { | |
1061 | int flag; | |
1062 | int task_id; | |
1063 | task_t task; | |
1064 | ||
1065 | flag = OPTION_TASK_TITLE|OPTION_INDENT; | |
1066 | if (db_option(modif, 'u')) | |
1067 | flag |= OPTION_USER; | |
1068 | if (db_option(modif, 'l')) | |
1069 | flag |= OPTION_LONG; | |
1070 | ||
1071 | if (!have_addr) { | |
1072 | task = db_current_task(); | |
1073 | if (task == TASK_NULL) { | |
1074 | db_error("No task\n"); | |
1075 | /*NOTREACHED*/ | |
1076 | } | |
1077 | } else | |
1078 | task = (task_t) addr; | |
1079 | ||
1080 | if ((task_id = db_lookup_task(task)) < 0) { | |
1081 | db_printf("bad task address 0x%x\n", addr); | |
1082 | db_error(0); | |
1083 | /*NOTREACHED*/ | |
1084 | } | |
1085 | ||
1086 | db_print_task(task, task_id, flag); | |
1087 | } | |
1088 | ||
1089 | void | |
1090 | db_show_shuttle( | |
1091 | db_expr_t addr, | |
1092 | boolean_t have_addr, | |
1093 | db_expr_t count, | |
1094 | char * modif) | |
1095 | { | |
1096 | thread_shuttle_t shuttle; | |
1097 | thread_act_t thr_act; | |
1098 | ||
1099 | if (have_addr) | |
1100 | shuttle = (thread_shuttle_t) addr; | |
1101 | else { | |
1102 | thr_act = current_act(); | |
1103 | if (thr_act == THR_ACT_NULL) { | |
1104 | db_error("No thr_act\n"); | |
1105 | /*NOTREACHED*/ | |
1106 | } | |
1107 | shuttle = thr_act->thread; | |
1108 | if (shuttle == THREAD_NULL) { | |
1109 | db_error("No shuttle associated with current thr_act\n"); | |
1110 | /*NOTREACHED*/ | |
1111 | } | |
1112 | } | |
1113 | db_printf("shuttle %x:\n", shuttle); | |
1114 | if (shuttle->top_act == THR_ACT_NULL) | |
1115 | db_printf(" no activations\n"); | |
1116 | else { | |
1117 | db_printf(" activations:"); | |
1118 | for (thr_act = shuttle->top_act; thr_act != THR_ACT_NULL; | |
1119 | thr_act = thr_act->lower) { | |
1120 | if (thr_act != shuttle->top_act) | |
1121 | printf(" from"); | |
1122 | printf(" $task%d.%d(%x)", db_lookup_task(thr_act->task), | |
1123 | db_lookup_act(thr_act), thr_act); | |
1124 | } | |
1125 | db_printf("\n"); | |
1126 | } | |
1127 | } | |
1128 | ||
1129 | #define db_pset_kmsg_count(port) \ | |
1130 | (ipc_list_count((port)->ip_pset->ips_messages.imq_messages.ikmq_base)) | |
1131 | ||
1132 | int | |
1133 | db_port_kmsg_count( | |
1134 | ipc_port_t port) | |
1135 | { | |
1136 | return (port->ip_pset ? db_pset_kmsg_count(port) : port->ip_msgcount); | |
1137 | } | |
1138 | ||
1139 | static int db_print_ent_cnt = 0; | |
1140 | ||
1141 | void db_reset_print_entry( | |
1142 | void) | |
1143 | { | |
1144 | db_print_ent_cnt = 0; | |
1145 | } | |
1146 | ||
1147 | void | |
1148 | db_print_one_entry( | |
1149 | ipc_entry_t entry, | |
1150 | int index, | |
1151 | mach_port_t name, | |
1152 | boolean_t is_pset) | |
1153 | { | |
1154 | ipc_port_t aport = (ipc_port_t)entry->ie_object; | |
1155 | unsigned bits = entry->ie_bits; | |
1156 | ||
1157 | if (is_pset && !aport->ip_pset) | |
1158 | return; | |
1159 | if (db_print_ent_cnt && db_print_ent_cnt % 2 == 0) | |
1160 | db_printf("\n"); | |
1161 | if (!name) | |
1162 | db_printf("\t%s%d[%x]", | |
1163 | !is_pset && aport->ip_pset ? "pset" : "port", | |
1164 | index, | |
1165 | MACH_PORT_MAKE(index, IE_BITS_GEN(bits))); | |
1166 | else | |
1167 | db_printf("\t%s[%x]", | |
1168 | !is_pset && aport->ip_pset ? "pset" : "port", | |
1169 | name); | |
1170 | if (!is_pset) { | |
1171 | db_printf("(%s,%x,%d)", | |
1172 | (bits & MACH_PORT_TYPE_RECEIVE)? "r": | |
1173 | (bits & MACH_PORT_TYPE_SEND)? "s": "S", | |
1174 | aport, | |
1175 | db_port_kmsg_count(aport)); | |
1176 | db_print_ent_cnt++; | |
1177 | } | |
1178 | else { | |
1179 | db_printf("(%s,%x,set=%x,%d)", | |
1180 | (bits & MACH_PORT_TYPE_RECEIVE)? "r": | |
1181 | (bits & MACH_PORT_TYPE_SEND)? "s": "S", | |
1182 | aport, | |
1183 | aport->ip_pset, | |
1184 | db_pset_kmsg_count(aport)); | |
1185 | db_print_ent_cnt++; | |
1186 | } | |
1187 | } | |
1188 | ||
1189 | int | |
1190 | db_port_iterate( | |
1191 | thread_act_t thr_act, | |
1192 | boolean_t is_pset, | |
1193 | boolean_t do_output) | |
1194 | { | |
1195 | ipc_entry_t entry; | |
1196 | ipc_tree_entry_t tentry; | |
1197 | int index; | |
1198 | int size; | |
1199 | int count; | |
1200 | ipc_space_t space; | |
1201 | ||
1202 | count = 0; | |
1203 | space = thr_act->task->itk_space; | |
1204 | entry = space->is_table; | |
1205 | size = space->is_table_size; | |
1206 | db_reset_print_entry(); | |
1207 | for (index = 0; index < size; ++index, ++entry) { | |
1208 | if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) { | |
1209 | if (do_output) | |
1210 | db_print_one_entry(entry, | |
1211 | index, (mach_port_t)0, is_pset); | |
1212 | ++count; | |
1213 | } | |
1214 | } | |
1215 | for (tentry = ipc_splay_traverse_start(&space->is_tree); | |
1216 | tentry != ITE_NULL; | |
1217 | tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) { | |
1218 | entry = &tentry->ite_entry; | |
1219 | if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) { | |
1220 | if (do_output) | |
1221 | db_print_one_entry(entry, | |
1222 | 0, tentry->ite_name, is_pset); | |
1223 | ++count; | |
1224 | } | |
1225 | } | |
1226 | return (count); | |
1227 | } | |
1228 | ||
1229 | ipc_port_t | |
1230 | db_lookup_port( | |
1231 | thread_act_t thr_act, | |
1232 | int id) | |
1233 | { | |
1234 | register ipc_space_t space; | |
1235 | register ipc_entry_t entry; | |
1236 | ||
1237 | if (thr_act == THR_ACT_NULL) | |
1238 | return(0); | |
1239 | space = thr_act->task->itk_space; | |
1240 | if (id < 0 || id >= space->is_table_size) | |
1241 | return(0); | |
1242 | entry = &space->is_table[id]; | |
1243 | if (entry->ie_bits & MACH_PORT_TYPE_PORT_RIGHTS) | |
1244 | return((ipc_port_t)entry->ie_object); | |
1245 | return(0); | |
1246 | } | |
1247 | ||
1248 | static void | |
1249 | db_print_port_id( | |
1250 | int id, | |
1251 | ipc_port_t port, | |
1252 | unsigned bits, | |
1253 | int n) | |
1254 | { | |
1255 | if (n != 0 && n % 3 == 0) | |
1256 | db_printf("\n"); | |
1257 | db_printf("\tport%d(%s,%x)", id, | |
1258 | (bits & MACH_PORT_TYPE_RECEIVE)? "r": | |
1259 | (bits & MACH_PORT_TYPE_SEND)? "s": "S", port); | |
1260 | } | |
1261 | ||
1262 | void | |
1263 | db_show_port_id( | |
1264 | db_expr_t addr, | |
1265 | boolean_t have_addr, | |
1266 | db_expr_t count, | |
1267 | char * modif) | |
1268 | { | |
1269 | thread_act_t thr_act; | |
1270 | ||
1271 | if (!have_addr) { | |
1272 | thr_act = current_act(); | |
1273 | if (thr_act == THR_ACT_NULL) { | |
1274 | db_error("No thr_act\n"); | |
1275 | /*NOTREACHED*/ | |
1276 | } | |
1277 | } else | |
1278 | thr_act = (thread_act_t) addr; | |
1279 | if (db_lookup_act(thr_act) < 0) { | |
1280 | db_printf("Bad thr_act address 0x%x\n", addr); | |
1281 | db_error(0); | |
1282 | /*NOTREACHED*/ | |
1283 | } | |
1284 | if (db_port_iterate(thr_act, db_option(modif,'s'), TRUE)) | |
1285 | db_printf("\n"); | |
1286 | } | |
1287 | ||
1288 | /* | |
1289 | * Useful system state when the world has hung. | |
1290 | */ | |
1291 | void | |
1292 | db_system_stats() | |
1293 | { | |
1294 | extern void db_device(void); | |
1295 | extern void db_sched(void); | |
1296 | #if DIPC | |
1297 | extern void db_dipc_stats(void); | |
1298 | extern void db_show_kkt(void); | |
1299 | #endif /* DIPC */ | |
1300 | ||
1301 | db_sched(); | |
1302 | iprintf("\n"); | |
1303 | db_vm(); | |
1304 | iprintf("\n"); | |
1305 | db_device(); | |
1306 | #if DIPC | |
1307 | iprintf("\n"); | |
1308 | db_dipc_stats(); | |
1309 | iprintf("\n"); | |
1310 | db_show_kkt(); | |
1311 | #endif /* DIPC */ | |
1312 | iprintf("\n"); | |
1313 | db_printf("current_{thread/task} 0x%x 0x%x\n", | |
1314 | current_thread(),current_task()); | |
1315 | } | |
1316 | ||
1317 | void db_show_one_runq(run_queue_t runq); | |
1318 | ||
1319 | void | |
1320 | db_show_runq( | |
1321 | db_expr_t addr, | |
1322 | boolean_t have_addr, | |
1323 | db_expr_t count, | |
1324 | char * modif) | |
1325 | { | |
1326 | processor_set_t pset; | |
1327 | processor_t proc; | |
1328 | run_queue_t runq; | |
1329 | boolean_t showedany = FALSE; | |
1330 | ||
1331 | queue_iterate(&all_psets, pset, processor_set_t, all_psets) { | |
1332 | #if NCPUS > 1 /* This code has not been tested. */ | |
1333 | queue_iterate(&pset->processors, proc, processor_t, processors) { | |
1334 | runq = &proc->runq; | |
1335 | if (runq->count > 0) { | |
1336 | db_printf("PROCESSOR %x IN SET %x\n", proc, pset); | |
1337 | db_show_one_runq(runq); | |
1338 | showedany = TRUE; | |
1339 | } | |
1340 | } | |
1341 | #endif /* NCPUS > 1 */ | |
1342 | #ifndef NCPUS | |
1343 | #error NCPUS undefined | |
1344 | #endif | |
1345 | runq = &pset->runq; | |
1346 | if (runq->count > 0) { | |
1347 | db_printf("PROCESSOR SET %x\n", pset); | |
1348 | db_show_one_runq(runq); | |
1349 | showedany = TRUE; | |
1350 | } | |
1351 | } | |
1352 | if (!showedany) | |
1353 | db_printf("No runnable threads\n"); | |
1354 | } | |
1355 | ||
1356 | void | |
1357 | db_show_one_runq( | |
1358 | run_queue_t runq) | |
1359 | { | |
1360 | int i, task_id, thr_act_id; | |
1361 | queue_t q; | |
1362 | thread_act_t thr_act; | |
1363 | thread_t thread; | |
1364 | task_t task; | |
1365 | ||
1366 | printf("PRI TASK.ACTIVATION\n"); | |
1367 | for (i = runq->low, q = runq->runq + i; i < NRQS; i++, q++) { | |
1368 | if (!queue_empty(q)) { | |
1369 | db_printf("%3d:", i); | |
1370 | queue_iterate(q, thread, thread_t, links) { | |
1371 | thr_act = thread->top_act; | |
1372 | task = thr_act->task; | |
1373 | task_id = db_lookup_task(task); | |
1374 | thr_act_id = db_lookup_task_act(task, thr_act); | |
1375 | db_printf(" %d.%d", task_id, thr_act_id); | |
1376 | } | |
1377 | db_printf("\n"); | |
1378 | } | |
1379 | } | |
1380 | } |