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