]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ddb/db_task_thread.c
xnu-792.13.8.tar.gz
[apple/xnu.git] / osfmk / ddb / db_task_thread.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
1c79356b
A
29 */
30/*
31 * @OSF_COPYRIGHT@
32 */
1c79356b
A
33/*
34 * Mach Operating System
35 * Copyright (c) 1991,1990 Carnegie Mellon University
36 * All Rights Reserved.
37 *
38 * Permission to use, copy, modify and distribute this software and its
39 * documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
43 *
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
46 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
47 *
48 * Carnegie Mellon requests users of this software to return to
49 *
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
54 *
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
57 */
58/*
59 */
60
61#include <kern/kern_types.h>
62#include <kern/processor.h>
63#include <machine/db_machdep.h>
64#include <ddb/db_task_thread.h>
65#include <ddb/db_variables.h>
66#include <ddb/db_command.h>
67#include <ddb/db_expr.h>
68#include <ddb/db_lex.h>
69#include <ddb/db_output.h> /* For db_printf() */
70#include <ddb/db_sym.h>
71
72/*
73 * Following constants are used to prevent infinite loop of task
74 * or thread search due to the incorrect list.
75 */
76#define DB_MAX_TASKID 0x10000 /* max # of tasks */
77#define DB_MAX_THREADID 0x10000 /* max # of threads in a task */
78#define DB_MAX_PSETS 0x10000 /* max # of processor sets */
79
5d5c5d0d
A
80task_t db_default_task = TASK_NULL; /* default target task */
81thread_t db_default_act = THREAD_NULL; /* default target thr_act */
1c79356b
A
82
83
84
85/* Prototypes for functions local to this file.
86 */
87task_t db_lookup_task_id(register int task_id);
88
91447636 89static thread_t db_lookup_act_id(
1c79356b
A
90 task_t task,
91 register int thread_id);
92
93
94
95/*
96 * search valid task queue, and return the queue position as the task id
97 */
98int
99db_lookup_task(task_t target_task)
100{
101 register task_t task;
102 register int task_id;
103 register processor_set_t pset = &default_pset;
104 register int npset = 0;
105
106 task_id = 0;
107 if (npset++ >= DB_MAX_PSETS)
108 return(-1);
109 if (queue_first(&pset->tasks) == 0)
110 return(-1);
111 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
112 if (target_task == task)
113 return(task_id);
114 if (task_id++ >= DB_MAX_TASKID)
115 return(-1);
116 }
117 return(-1);
118}
119
120/*
121 * search thread queue of the task, and return the queue position
122 */
123int
124db_lookup_task_act(
125 task_t task,
91447636 126 thread_t target_act)
1c79356b 127{
91447636 128 register thread_t thr_act;
1c79356b
A
129 register int act_id;
130
131 act_id = 0;
55e303ae 132 if (queue_first(&task->threads) == 0)
1c79356b 133 return(-1);
91447636 134 queue_iterate(&task->threads, thr_act, thread_t, task_threads) {
1c79356b
A
135 if (target_act == thr_act)
136 return(act_id);
137 if (act_id++ >= DB_MAX_THREADID)
138 return(-1);
139 }
140 return(-1);
141}
142
143/*
144 * search thr_act queue of every valid task, and return the queue position
145 * as the thread id.
146 */
147int
91447636 148db_lookup_act(thread_t target_act)
1c79356b
A
149{
150 register int act_id;
151 register task_t task;
152 register processor_set_t pset = &default_pset;
153 register int ntask = 0;
154 register int npset = 0;
155
156 if (npset++ >= DB_MAX_PSETS)
157 return(-1);
158 if (queue_first(&pset->tasks) == 0)
159 return(-1);
160 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
161 if (ntask++ > DB_MAX_TASKID)
162 return(-1);
55e303ae 163 if (task->thread_count == 0)
1c79356b
A
164 continue;
165 act_id = db_lookup_task_act(task, target_act);
166 if (act_id >= 0)
167 return(act_id);
168 }
169 return(-1);
170}
171
172/*
173 * check the address is a valid thread address
174 */
175int force_act_lookup = 0;
176boolean_t
91447636 177db_check_act_address_valid(thread_t thr_act)
1c79356b
A
178{
179 if (!force_act_lookup && db_lookup_act(thr_act) < 0) {
180 db_printf("Bad thr_act address 0x%x\n", thr_act);
181 db_flush_lex();
182 return(FALSE);
183 } else
184 return(TRUE);
185}
186
187/*
188 * convert task_id(queue postion) to task address
189 */
190task_t
191db_lookup_task_id(register task_id)
192{
193 register task_t task;
194 register processor_set_t pset = &default_pset;
195 register int npset = 0;
196
197 if (task_id > DB_MAX_TASKID)
198 return(TASK_NULL);
199 if (npset++ >= DB_MAX_PSETS)
200 return(TASK_NULL);
201 if (queue_first(&pset->tasks) == 0)
202 return(TASK_NULL);
203 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
204 if (task_id-- <= 0)
205 return(task);
206 }
207 return(TASK_NULL);
208}
209
210/*
211 * convert (task_id, act_id) pair to thr_act address
212 */
91447636 213static thread_t
1c79356b
A
214db_lookup_act_id(
215 task_t task,
216 register int act_id)
217{
91447636 218 register thread_t thr_act;
1c79356b
A
219
220
221 if (act_id > DB_MAX_THREADID)
91447636 222 return(THREAD_NULL);
55e303ae 223 if (queue_first(&task->threads) == 0)
91447636
A
224 return(THREAD_NULL);
225 queue_iterate(&task->threads, thr_act, thread_t, task_threads) {
1c79356b
A
226 if (act_id-- <= 0)
227 return(thr_act);
228 }
91447636 229 return(THREAD_NULL);
1c79356b
A
230}
231
232/*
233 * get next parameter from a command line, and check it as a valid
234 * thread address
235 */
236boolean_t
237db_get_next_act(
91447636 238 thread_t *actp,
1c79356b
A
239 int position)
240{
241 db_expr_t value;
91447636 242 thread_t thr_act;
1c79356b 243
91447636 244 *actp = THREAD_NULL;
1c79356b 245 if (db_expression(&value)) {
91447636 246 thr_act = (thread_t) value;
1c79356b
A
247 if (!db_check_act_address_valid(thr_act)) {
248 db_flush_lex();
249 return(FALSE);
250 }
251 } else if (position <= 0) {
252 thr_act = db_default_act;
253 } else
254 return(FALSE);
255 *actp = thr_act;
256 return(TRUE);
257}
258
259/*
260 * check the default thread is still valid
261 * ( it is called in entering DDB session )
262 */
263void
264db_init_default_act(void)
265{
266 if (db_lookup_act(db_default_act) < 0) {
91447636 267 db_default_act = THREAD_NULL;
1c79356b
A
268 db_default_task = TASK_NULL;
269 } else
270 db_default_task = db_default_act->task;
271}
272
273/*
274 * set or get default thread which is used when /t or :t option is specified
275 * in the command line
276 */
277int
278db_set_default_act(
279 struct db_variable *vp,
280 db_expr_t *valuep,
281 int flag,
282 db_var_aux_param_t ap) /* unused */
283{
91447636 284 thread_t thr_act;
1c79356b
A
285 int task_id;
286 int act_id;
287
288 if (flag == DB_VAR_SHOW) {
289 db_printf("%#n", db_default_act);
290 task_id = db_lookup_task(db_default_task);
291 if (task_id != -1) {
292 act_id = db_lookup_act(db_default_act);
293 if (act_id != -1) {
294 db_printf(" (task%d.%d)", task_id, act_id);
295 }
296 }
297 return(0);
298 }
299
300 if (flag != DB_VAR_SET) {
301 *valuep = (db_expr_t) db_default_act;
302 return(0);
303 }
91447636
A
304 thr_act = (thread_t) *valuep;
305 if (thr_act != THREAD_NULL && !db_check_act_address_valid(thr_act))
1c79356b
A
306 db_error(0);
307 /* NOTREACHED */
308 db_default_act = thr_act;
309 if (thr_act)
310 db_default_task = thr_act->task;
311 return(0);
312}
313
314/*
315 * convert $taskXXX[.YYY] type DDB variable to task or thread address
316 */
317int
318db_get_task_act(
319 struct db_variable *vp,
320 db_expr_t *valuep,
321 int flag,
322 db_var_aux_param_t ap)
323{
324 task_t task;
91447636 325 thread_t thr_act;
1c79356b
A
326 int task_id;
327
328 if (flag == DB_VAR_SHOW) {
329 db_printf("%#n", db_default_task);
330 task_id = db_lookup_task(db_default_task);
331 if (task_id != -1)
332 db_printf(" (task%d)", task_id);
333 return(0);
334 }
335
336 if (flag != DB_VAR_GET) {
337 db_error("Cannot set to $task variable\n");
338 /* NOTREACHED */
339 }
340 if ((task = db_lookup_task_id(ap->suffix[0])) == TASK_NULL) {
341 db_printf("no such task($task%d)\n", ap->suffix[0]);
342 db_error(0);
343 /* NOTREACHED */
344 }
345 if (ap->level <= 1) {
346 *valuep = (db_expr_t) task;
347 return(0);
348 }
91447636 349 if ((thr_act = db_lookup_act_id(task, ap->suffix[1])) == THREAD_NULL){
1c79356b
A
350 db_printf("no such thr_act($task%d.%d)\n",
351 ap->suffix[0], ap->suffix[1]);
352 db_error(0);
353 /* NOTREACHED */
354 }
355 *valuep = (db_expr_t) thr_act;
356 return(0);
357}