|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
18: * under the License.
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.1.1.1 1998/03/07 02:26:09 wsanchez
32: * Import of OSF Mach kernel (~mburg)
33: *
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]
38: *
39: * Merged '64-bit safe' changes from DEC alpha port.
40: * [1995/11/21 18:03:48 jfraser]
41: *
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]
45: *
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]
49: *
50: * Revision 1.1.14.1 1994/02/08 10:59:02 bernadat
51: * Added support of DB_VAR_SHOW.
52: * [93/08/12 paire]
53: * [94/02/08 bernadat]
54: *
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]
58: *
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]
63: *
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]
67: *
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]
71: *
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]
75: *
76: * Revision 1.1 1992/09/30 02:01:27 robert
77: * Initial revision
78: *
79: * $EndLog$
80: */
81: /* CMU_HIST */
82: /*
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.
86: * [91/08/29 tak]
87: *
88: * Revision 2.1.3.1 91/10/05 13:07:50 jeffreyh
89: * Created for task/thread handling.
90: * [91/08/29 tak]
91: *
92: */
93: /* CMU_ENDHIST */
94: /*
95: * Mach Operating System
96: * Copyright (c) 1991,1990 Carnegie Mellon University
97: * All Rights Reserved.
98: *
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.
104: *
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.
108: *
109: * Carnegie Mellon requests users of this software to return to
110: *
111: * Software Distribution Coordinator or [email protected]
112: * School of Computer Science
113: * Carnegie Mellon University
114: * Pittsburgh PA 15213-3890
115: *
116: * any improvements or extensions that they make and grant Carnegie Mellon
117: * the rights to redistribute these changes.
118: */
119: /*
120: */
121:
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>
132:
133: /*
134: * Following constants are used to prevent infinite loop of task
135: * or thread search due to the incorrect list.
136: */
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 */
140:
141: task_t db_default_task; /* default target task */
142: thread_act_t db_default_act; /* default target thr_act */
143:
144:
145:
146: /* Prototypes for functions local to this file.
147: */
148: task_t db_lookup_task_id(register int task_id);
149:
150: static thread_act_t db_lookup_act_id(
151: task_t task,
152: register int thread_id);
153:
154:
155:
156: /*
157: * search valid task queue, and return the queue position as the task id
158: */
159: int
160: db_lookup_task(task_t target_task)
161: {
162: register task_t task;
163: register int task_id;
164: register processor_set_t pset;
165: register int npset = 0;
166:
167: task_id = 0;
168: if (queue_first(&all_psets) == 0)
169: return(-1);
170: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
171: if (npset++ >= DB_MAX_PSETS)
172: return(-1);
173: if (queue_first(&pset->tasks) == 0)
174: continue;
175: queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
176: if (target_task == task)
177: return(task_id);
178: if (task_id++ >= DB_MAX_TASKID)
179: return(-1);
180: }
181: }
182: return(-1);
183: }
184:
185: /*
186: * search thread queue of the task, and return the queue position
187: */
188: int
189: db_lookup_task_act(
190: task_t task,
191: thread_act_t target_act)
192: {
193: register thread_act_t thr_act;
194: register int act_id;
195:
196: act_id = 0;
197: if (queue_first(&task->thr_acts) == 0)
198: return(-1);
199: queue_iterate(&task->thr_acts, thr_act, thread_act_t, thr_acts) {
200: if (target_act == thr_act)
201: return(act_id);
202: if (act_id++ >= DB_MAX_THREADID)
203: return(-1);
204: }
205: return(-1);
206: }
207:
208: /*
209: * search thr_act queue of every valid task, and return the queue position
210: * as the thread id.
211: */
212: int
213: db_lookup_act(thread_act_t target_act)
214: {
215: register int act_id;
216: register task_t task;
217: register processor_set_t pset;
218: register int ntask = 0;
219: register int npset = 0;
220:
221: if (queue_first(&all_psets) == 0)
222: return(-1);
223: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
224: if (npset++ >= DB_MAX_PSETS)
225: return(-1);
226: if (queue_first(&pset->tasks) == 0)
227: continue;
228: queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
229: if (ntask++ > DB_MAX_TASKID)
230: return(-1);
231: if (task->thr_act_count == 0)
232: continue;
233: act_id = db_lookup_task_act(task, target_act);
234: if (act_id >= 0)
235: return(act_id);
236: }
237: }
238: return(-1);
239: }
240:
241: /*
242: * check the address is a valid thread address
243: */
244: int force_act_lookup = 0;
245: boolean_t
246: db_check_act_address_valid(thread_act_t thr_act)
247: {
248: if (!force_act_lookup && db_lookup_act(thr_act) < 0) {
249: db_printf("Bad thr_act address 0x%x\n", thr_act);
250: db_flush_lex();
251: return(FALSE);
252: } else
253: return(TRUE);
254: }
255:
256: /*
257: * convert task_id(queue postion) to task address
258: */
259: task_t
260: db_lookup_task_id(register task_id)
261: {
262: register task_t task;
263: register processor_set_t pset;
264: register int npset = 0;
265:
266: if (task_id > DB_MAX_TASKID)
267: return(TASK_NULL);
268: if (queue_first(&all_psets) == 0)
269: return(TASK_NULL);
270: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
271: if (npset++ >= DB_MAX_PSETS)
272: return(TASK_NULL);
273: if (queue_first(&pset->tasks) == 0)
274: continue;
275: queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
276: if (task_id-- <= 0)
277: return(task);
278: }
279: }
280: return(TASK_NULL);
281: }
282:
283: /*
284: * convert (task_id, act_id) pair to thr_act address
285: */
286: static thread_act_t
287: db_lookup_act_id(
288: task_t task,
289: register int act_id)
290: {
291: register thread_act_t thr_act;
292:
293:
294: if (act_id > DB_MAX_THREADID)
295: return(THR_ACT_NULL);
296: if (queue_first(&task->thr_acts) == 0)
297: return(THR_ACT_NULL);
298: queue_iterate(&task->thr_acts, thr_act, thread_act_t, thr_acts) {
299: if (act_id-- <= 0)
300: return(thr_act);
301: }
302: return(THR_ACT_NULL);
303: }
304:
305: /*
306: * get next parameter from a command line, and check it as a valid
307: * thread address
308: */
309: boolean_t
310: db_get_next_act(
311: thread_act_t *actp,
312: int position)
313: {
314: db_expr_t value;
315: thread_act_t thr_act;
316:
317: *actp = THR_ACT_NULL;
318: if (db_expression(&value)) {
319: thr_act = (thread_act_t) value;
320: if (!db_check_act_address_valid(thr_act)) {
321: db_flush_lex();
322: return(FALSE);
323: }
324: } else if (position <= 0) {
325: thr_act = db_default_act;
326: } else
327: return(FALSE);
328: *actp = thr_act;
329: return(TRUE);
330: }
331:
332: /*
333: * check the default thread is still valid
334: * ( it is called in entering DDB session )
335: */
336: void
337: db_init_default_act(void)
338: {
339: if (db_lookup_act(db_default_act) < 0) {
340: db_default_act = THR_ACT_NULL;
341: db_default_task = TASK_NULL;
342: } else
343: db_default_task = db_default_act->task;
344: }
345:
346: /*
347: * set or get default thread which is used when /t or :t option is specified
348: * in the command line
349: */
350: int
351: db_set_default_act(
352: struct db_variable *vp,
353: db_expr_t *valuep,
354: int flag,
355: db_var_aux_param_t ap) /* unused */
356: {
357: thread_act_t thr_act;
358: int task_id;
359: int act_id;
360:
361: if (flag == DB_VAR_SHOW) {
362: db_printf("%#n", db_default_act);
363: task_id = db_lookup_task(db_default_task);
364: if (task_id != -1) {
365: act_id = db_lookup_act(db_default_act);
366: if (act_id != -1) {
367: db_printf(" (task%d.%d)", task_id, act_id);
368: }
369: }
370: return(0);
371: }
372:
373: if (flag != DB_VAR_SET) {
374: *valuep = (db_expr_t) db_default_act;
375: return(0);
376: }
377: thr_act = (thread_act_t) *valuep;
378: if (thr_act != THR_ACT_NULL && !db_check_act_address_valid(thr_act))
379: db_error(0);
380: /* NOTREACHED */
381: db_default_act = thr_act;
382: if (thr_act)
383: db_default_task = thr_act->task;
384: return(0);
385: }
386:
387: /*
388: * convert $taskXXX[.YYY] type DDB variable to task or thread address
389: */
390: int
391: db_get_task_act(
392: struct db_variable *vp,
393: db_expr_t *valuep,
394: int flag,
395: db_var_aux_param_t ap)
396: {
397: task_t task;
398: thread_act_t thr_act;
399: int task_id;
400:
401: if (flag == DB_VAR_SHOW) {
402: db_printf("%#n", db_default_task);
403: task_id = db_lookup_task(db_default_task);
404: if (task_id != -1)
405: db_printf(" (task%d)", task_id);
406: return(0);
407: }
408:
409: if (flag != DB_VAR_GET) {
410: db_error("Cannot set to $task variable\n");
411: /* NOTREACHED */
412: }
413: if ((task = db_lookup_task_id(ap->suffix[0])) == TASK_NULL) {
414: db_printf("no such task($task%d)\n", ap->suffix[0]);
415: db_error(0);
416: /* NOTREACHED */
417: }
418: if (ap->level <= 1) {
419: *valuep = (db_expr_t) task;
420: return(0);
421: }
422: if ((thr_act = db_lookup_act_id(task, ap->suffix[1])) == THR_ACT_NULL){
423: db_printf("no such thr_act($task%d.%d)\n",
424: ap->suffix[0], ap->suffix[1]);
425: db_error(0);
426: /* NOTREACHED */
427: }
428: *valuep = (db_expr_t) thr_act;
429: return(0);
430: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.