2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
23 * @APPLE_LICENSE_HEADER_END@
29 * Mach Operating System
30 * Copyright (c) 1991,1990 Carnegie Mellon University
31 * All Rights Reserved.
33 * Permission to use, copy, modify and distribute this software and its
34 * documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 * Carnegie Mellon requests users of this software to return to
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
50 * any improvements or extensions that they make and grant Carnegie Mellon
51 * the rights to redistribute these changes.
56 #include <kern/kern_types.h>
57 #include <kern/processor.h>
58 #include <machine/db_machdep.h>
59 #include <ddb/db_task_thread.h>
60 #include <ddb/db_variables.h>
61 #include <ddb/db_command.h>
62 #include <ddb/db_expr.h>
63 #include <ddb/db_lex.h>
64 #include <ddb/db_output.h> /* For db_printf() */
65 #include <ddb/db_sym.h>
68 * Following constants are used to prevent infinite loop of task
69 * or thread search due to the incorrect list.
71 #define DB_MAX_TASKID 0x10000 /* max # of tasks */
72 #define DB_MAX_THREADID 0x10000 /* max # of threads in a task */
73 #define DB_MAX_PSETS 0x10000 /* max # of processor sets */
75 task_t db_default_task
; /* default target task */
76 thread_act_t db_default_act
; /* default target thr_act */
80 /* Prototypes for functions local to this file.
82 task_t
db_lookup_task_id(register int task_id
);
84 static thread_act_t
db_lookup_act_id(
86 register int thread_id
);
91 * search valid task queue, and return the queue position as the task id
94 db_lookup_task(task_t target_task
)
98 register processor_set_t pset
= &default_pset
;
99 register int npset
= 0;
102 if (npset
++ >= DB_MAX_PSETS
)
104 if (queue_first(&pset
->tasks
) == 0)
106 queue_iterate(&pset
->tasks
, task
, task_t
, pset_tasks
) {
107 if (target_task
== task
)
109 if (task_id
++ >= DB_MAX_TASKID
)
116 * search thread queue of the task, and return the queue position
121 thread_act_t target_act
)
123 register thread_act_t thr_act
;
127 if (queue_first(&task
->threads
) == 0)
129 queue_iterate(&task
->threads
, thr_act
, thread_act_t
, task_threads
) {
130 if (target_act
== thr_act
)
132 if (act_id
++ >= DB_MAX_THREADID
)
139 * search thr_act queue of every valid task, and return the queue position
143 db_lookup_act(thread_act_t target_act
)
146 register task_t task
;
147 register processor_set_t pset
= &default_pset
;
148 register int ntask
= 0;
149 register int npset
= 0;
151 if (npset
++ >= DB_MAX_PSETS
)
153 if (queue_first(&pset
->tasks
) == 0)
155 queue_iterate(&pset
->tasks
, task
, task_t
, pset_tasks
) {
156 if (ntask
++ > DB_MAX_TASKID
)
158 if (task
->thread_count
== 0)
160 act_id
= db_lookup_task_act(task
, target_act
);
168 * check the address is a valid thread address
170 int force_act_lookup
= 0;
172 db_check_act_address_valid(thread_act_t thr_act
)
174 if (!force_act_lookup
&& db_lookup_act(thr_act
) < 0) {
175 db_printf("Bad thr_act address 0x%x\n", thr_act
);
183 * convert task_id(queue postion) to task address
186 db_lookup_task_id(register task_id
)
188 register task_t task
;
189 register processor_set_t pset
= &default_pset
;
190 register int npset
= 0;
192 if (task_id
> DB_MAX_TASKID
)
194 if (npset
++ >= DB_MAX_PSETS
)
196 if (queue_first(&pset
->tasks
) == 0)
198 queue_iterate(&pset
->tasks
, task
, task_t
, pset_tasks
) {
206 * convert (task_id, act_id) pair to thr_act address
213 register thread_act_t thr_act
;
216 if (act_id
> DB_MAX_THREADID
)
217 return(THR_ACT_NULL
);
218 if (queue_first(&task
->threads
) == 0)
219 return(THR_ACT_NULL
);
220 queue_iterate(&task
->threads
, thr_act
, thread_act_t
, task_threads
) {
224 return(THR_ACT_NULL
);
228 * get next parameter from a command line, and check it as a valid
237 thread_act_t thr_act
;
239 *actp
= THR_ACT_NULL
;
240 if (db_expression(&value
)) {
241 thr_act
= (thread_act_t
) value
;
242 if (!db_check_act_address_valid(thr_act
)) {
246 } else if (position
<= 0) {
247 thr_act
= db_default_act
;
255 * check the default thread is still valid
256 * ( it is called in entering DDB session )
259 db_init_default_act(void)
261 if (db_lookup_act(db_default_act
) < 0) {
262 db_default_act
= THR_ACT_NULL
;
263 db_default_task
= TASK_NULL
;
265 db_default_task
= db_default_act
->task
;
269 * set or get default thread which is used when /t or :t option is specified
270 * in the command line
274 struct db_variable
*vp
,
277 db_var_aux_param_t ap
) /* unused */
279 thread_act_t thr_act
;
283 if (flag
== DB_VAR_SHOW
) {
284 db_printf("%#n", db_default_act
);
285 task_id
= db_lookup_task(db_default_task
);
287 act_id
= db_lookup_act(db_default_act
);
289 db_printf(" (task%d.%d)", task_id
, act_id
);
295 if (flag
!= DB_VAR_SET
) {
296 *valuep
= (db_expr_t
) db_default_act
;
299 thr_act
= (thread_act_t
) *valuep
;
300 if (thr_act
!= THR_ACT_NULL
&& !db_check_act_address_valid(thr_act
))
303 db_default_act
= thr_act
;
305 db_default_task
= thr_act
->task
;
310 * convert $taskXXX[.YYY] type DDB variable to task or thread address
314 struct db_variable
*vp
,
317 db_var_aux_param_t ap
)
320 thread_act_t thr_act
;
323 if (flag
== DB_VAR_SHOW
) {
324 db_printf("%#n", db_default_task
);
325 task_id
= db_lookup_task(db_default_task
);
327 db_printf(" (task%d)", task_id
);
331 if (flag
!= DB_VAR_GET
) {
332 db_error("Cannot set to $task variable\n");
335 if ((task
= db_lookup_task_id(ap
->suffix
[0])) == TASK_NULL
) {
336 db_printf("no such task($task%d)\n", ap
->suffix
[0]);
340 if (ap
->level
<= 1) {
341 *valuep
= (db_expr_t
) task
;
344 if ((thr_act
= db_lookup_act_id(task
, ap
->suffix
[1])) == THR_ACT_NULL
){
345 db_printf("no such thr_act($task%d.%d)\n",
346 ap
->suffix
[0], ap
->suffix
[1]);
350 *valuep
= (db_expr_t
) thr_act
;