2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
28 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
29 * Import of Mac OS X kernel (~semeria)
31 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
32 * Import of OSF Mach kernel (~mburg)
34 * Revision 1.1.16.3 1996/01/09 19:16:26 devrcs
35 * Make db_lookup_task_id() globally available (remove static).
36 * Changed declarations of 'register foo' to 'register int foo'.
37 * [1995/12/01 21:42:37 jfraser]
39 * Merged '64-bit safe' changes from DEC alpha port.
40 * [1995/11/21 18:03:48 jfraser]
42 * Revision 1.1.16.2 1994/09/23 01:21:59 ezf
43 * change marker to not FREE
44 * [1994/09/22 21:11:09 ezf]
46 * Revision 1.1.16.1 1994/06/11 21:12:29 bolinger
47 * Merge up to NMK17.2.
48 * [1994/06/11 20:02:43 bolinger]
50 * Revision 1.1.14.1 1994/02/08 10:59:02 bernadat
51 * Added support of DB_VAR_SHOW.
55 * Revision 1.1.12.3 1994/03/17 22:35:35 dwm
56 * The infamous name change: thread_activation + thread_shuttle = thread.
57 * [1994/03/17 21:25:50 dwm]
59 * Revision 1.1.12.2 1994/01/17 18:08:54 dwm
60 * Add patchable integer force_act_lookup to force successful
61 * lookup, to allow stack trace on orphaned act/thread pairs.
62 * [1994/01/17 16:06:50 dwm]
64 * Revision 1.1.12.1 1994/01/12 17:50:52 dwm
65 * Coloc: initial restructuring to follow Utah model.
66 * [1994/01/12 17:13:23 dwm]
68 * Revision 1.1.3.3 1993/07/27 18:28:15 elliston
69 * Add ANSI prototypes. CR #9523.
70 * [1993/07/27 18:13:06 elliston]
72 * Revision 1.1.3.2 1993/06/02 23:12:39 jeffc
73 * Added to OSF/1 R1.3 from NMK15.0.
74 * [1993/06/02 20:57:24 jeffc]
76 * Revision 1.1 1992/09/30 02:01:27 robert
83 * Revision 2.2 91/10/09 16:03:04 af
84 * Revision 2.1.3.1 91/10/05 13:07:50 jeffreyh
85 * Created for task/thread handling.
88 * Revision 2.1.3.1 91/10/05 13:07:50 jeffreyh
89 * Created for task/thread handling.
95 * Mach Operating System
96 * Copyright (c) 1991,1990 Carnegie Mellon University
97 * All Rights Reserved.
99 * Permission to use, copy, modify and distribute this software and its
100 * documentation is hereby granted, provided that both the copyright
101 * notice and this permission notice appear in all copies of the
102 * software, derivative works or modified versions, and any portions
103 * thereof, and that both notices appear in supporting documentation.
105 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
106 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
107 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
109 * Carnegie Mellon requests users of this software to return to
111 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
112 * School of Computer Science
113 * Carnegie Mellon University
114 * Pittsburgh PA 15213-3890
116 * any improvements or extensions that they make and grant Carnegie Mellon
117 * the rights to redistribute these changes.
122 #include <kern/kern_types.h>
123 #include <kern/processor.h>
124 #include <machine/db_machdep.h>
125 #include <ddb/db_task_thread.h>
126 #include <ddb/db_variables.h>
127 #include <ddb/db_command.h>
128 #include <ddb/db_expr.h>
129 #include <ddb/db_lex.h>
130 #include <ddb/db_output.h> /* For db_printf() */
131 #include <ddb/db_sym.h>
134 * Following constants are used to prevent infinite loop of task
135 * or thread search due to the incorrect list.
137 #define DB_MAX_TASKID 0x10000 /* max # of tasks */
138 #define DB_MAX_THREADID 0x10000 /* max # of threads in a task */
139 #define DB_MAX_PSETS 0x10000 /* max # of processor sets */
141 task_t db_default_task
; /* default target task */
142 thread_act_t db_default_act
; /* default target thr_act */
146 /* Prototypes for functions local to this file.
148 task_t
db_lookup_task_id(register int task_id
);
150 static thread_act_t
db_lookup_act_id(
152 register int thread_id
);
157 * search valid task queue, and return the queue position as the task id
160 db_lookup_task(task_t target_task
)
162 register task_t task
;
163 register int task_id
;
164 register processor_set_t pset
= &default_pset
;
165 register int npset
= 0;
168 if (npset
++ >= DB_MAX_PSETS
)
170 if (queue_first(&pset
->tasks
) == 0)
172 queue_iterate(&pset
->tasks
, task
, task_t
, pset_tasks
) {
173 if (target_task
== task
)
175 if (task_id
++ >= DB_MAX_TASKID
)
182 * search thread queue of the task, and return the queue position
187 thread_act_t target_act
)
189 register thread_act_t thr_act
;
193 if (queue_first(&task
->thr_acts
) == 0)
195 queue_iterate(&task
->thr_acts
, thr_act
, thread_act_t
, thr_acts
) {
196 if (target_act
== thr_act
)
198 if (act_id
++ >= DB_MAX_THREADID
)
205 * search thr_act queue of every valid task, and return the queue position
209 db_lookup_act(thread_act_t target_act
)
212 register task_t task
;
213 register processor_set_t pset
= &default_pset
;
214 register int ntask
= 0;
215 register int npset
= 0;
217 if (npset
++ >= DB_MAX_PSETS
)
219 if (queue_first(&pset
->tasks
) == 0)
221 queue_iterate(&pset
->tasks
, task
, task_t
, pset_tasks
) {
222 if (ntask
++ > DB_MAX_TASKID
)
224 if (task
->thr_act_count
== 0)
226 act_id
= db_lookup_task_act(task
, target_act
);
234 * check the address is a valid thread address
236 int force_act_lookup
= 0;
238 db_check_act_address_valid(thread_act_t thr_act
)
240 if (!force_act_lookup
&& db_lookup_act(thr_act
) < 0) {
241 db_printf("Bad thr_act address 0x%x\n", thr_act
);
249 * convert task_id(queue postion) to task address
252 db_lookup_task_id(register task_id
)
254 register task_t task
;
255 register processor_set_t pset
= &default_pset
;
256 register int npset
= 0;
258 if (task_id
> DB_MAX_TASKID
)
260 if (npset
++ >= DB_MAX_PSETS
)
262 if (queue_first(&pset
->tasks
) == 0)
264 queue_iterate(&pset
->tasks
, task
, task_t
, pset_tasks
) {
272 * convert (task_id, act_id) pair to thr_act address
279 register thread_act_t thr_act
;
282 if (act_id
> DB_MAX_THREADID
)
283 return(THR_ACT_NULL
);
284 if (queue_first(&task
->thr_acts
) == 0)
285 return(THR_ACT_NULL
);
286 queue_iterate(&task
->thr_acts
, thr_act
, thread_act_t
, thr_acts
) {
290 return(THR_ACT_NULL
);
294 * get next parameter from a command line, and check it as a valid
303 thread_act_t thr_act
;
305 *actp
= THR_ACT_NULL
;
306 if (db_expression(&value
)) {
307 thr_act
= (thread_act_t
) value
;
308 if (!db_check_act_address_valid(thr_act
)) {
312 } else if (position
<= 0) {
313 thr_act
= db_default_act
;
321 * check the default thread is still valid
322 * ( it is called in entering DDB session )
325 db_init_default_act(void)
327 if (db_lookup_act(db_default_act
) < 0) {
328 db_default_act
= THR_ACT_NULL
;
329 db_default_task
= TASK_NULL
;
331 db_default_task
= db_default_act
->task
;
335 * set or get default thread which is used when /t or :t option is specified
336 * in the command line
340 struct db_variable
*vp
,
343 db_var_aux_param_t ap
) /* unused */
345 thread_act_t thr_act
;
349 if (flag
== DB_VAR_SHOW
) {
350 db_printf("%#n", db_default_act
);
351 task_id
= db_lookup_task(db_default_task
);
353 act_id
= db_lookup_act(db_default_act
);
355 db_printf(" (task%d.%d)", task_id
, act_id
);
361 if (flag
!= DB_VAR_SET
) {
362 *valuep
= (db_expr_t
) db_default_act
;
365 thr_act
= (thread_act_t
) *valuep
;
366 if (thr_act
!= THR_ACT_NULL
&& !db_check_act_address_valid(thr_act
))
369 db_default_act
= thr_act
;
371 db_default_task
= thr_act
->task
;
376 * convert $taskXXX[.YYY] type DDB variable to task or thread address
380 struct db_variable
*vp
,
383 db_var_aux_param_t ap
)
386 thread_act_t thr_act
;
389 if (flag
== DB_VAR_SHOW
) {
390 db_printf("%#n", db_default_task
);
391 task_id
= db_lookup_task(db_default_task
);
393 db_printf(" (task%d)", task_id
);
397 if (flag
!= DB_VAR_GET
) {
398 db_error("Cannot set to $task variable\n");
401 if ((task
= db_lookup_task_id(ap
->suffix
[0])) == TASK_NULL
) {
402 db_printf("no such task($task%d)\n", ap
->suffix
[0]);
406 if (ap
->level
<= 1) {
407 *valuep
= (db_expr_t
) task
;
410 if ((thr_act
= db_lookup_act_id(task
, ap
->suffix
[1])) == THR_ACT_NULL
){
411 db_printf("no such thr_act($task%d.%d)\n",
412 ap
->suffix
[0], ap
->suffix
[1]);
416 *valuep
= (db_expr_t
) thr_act
;