|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26:
27: #include "mach_kdb.h"
28: #if MACH_KDB
29:
30: #include <machine/db_machdep.h>
31: #include <ddb/db_task_thread.h>
32: #include <ddb/db_variables.h>
33:
34:
35:
36: /*
37: * Following constants are used to prevent infinite loop of task
38: * or thread search due to the incorrect list.
39: */
40: #define DB_MAX_TASKID 0x10000 /* max # of tasks */
41: #define DB_MAX_THREADID 0x10000 /* max # of threads in a task */
42: #define DB_MAX_PSETS 0x10000 /* max # of processor sets */
43:
44: task_t db_default_task; /* default target task */
45: thread_t db_default_thread; /* default target thread */
46:
47: /*
48: * search valid task queue, and return the queue position as the task id
49: */
50: int
51: db_lookup_task(target_task)
52: task_t target_task;
53: {
54: register task_t task;
55: register task_id;
56: register processor_set_t pset;
57: register npset = 0;
58:
59: task_id = 0;
60: if (queue_first(&all_psets) == 0)
61: return(-1);
62: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
63: if (npset++ >= DB_MAX_PSETS)
64: return(-1);
65: if (queue_first(&pset->tasks) == 0)
66: continue;
67: queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
68: if (target_task == task)
69: return(task_id);
70: if (task_id++ >= DB_MAX_TASKID)
71: return(-1);
72: }
73: }
74: return(-1);
75: }
76:
77: /*
78: * search thread queue of the task, and return the queue position
79: */
80: int
81: db_lookup_task_thread(task, target_thread)
82: task_t task;
83: thread_t target_thread;
84: {
85: register thread_t thread;
86: register thread_id;
87:
88: thread_id = 0;
89: if (queue_first(&task->thread_list) == 0)
90: return(-1);
91: queue_iterate(&task->thread_list, thread, thread_t, thread_list) {
92: if (target_thread == thread)
93: return(thread_id);
94: if (thread_id++ >= DB_MAX_THREADID)
95: return(-1);
96: }
97: return(-1);
98: }
99:
100: /*
101: * search thread queue of every valid task, and return the queue position
102: * as the thread id.
103: */
104: int
105: db_lookup_thread(target_thread)
106: thread_t target_thread;
107: {
108: register thread_id;
109: register task_t task;
110: register processor_set_t pset;
111: register ntask = 0;
112: register npset = 0;
113:
114: if (queue_first(&all_psets) == 0)
115: return(-1);
116: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
117: if (npset++ >= DB_MAX_PSETS)
118: return(-1);
119: if (queue_first(&pset->tasks) == 0)
120: continue;
121: queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
122: if (ntask++ > DB_MAX_TASKID)
123: return(-1);
124: if (task->thread_count == 0)
125: continue;
126: thread_id = db_lookup_task_thread(task, target_thread);
127: if (thread_id >= 0)
128: return(thread_id);
129: }
130: }
131: return(-1);
132: }
133:
134: /*
135: * check the address is a valid thread address
136: */
137: boolean_t
138: db_check_thread_address_valid(thread)
139: thread_t thread;
140: {
141: if (db_lookup_thread(thread) < 0) {
142: db_printf("Bad thread address 0x%x\n", thread);
143: db_flush_lex();
144: return(FALSE);
145: } else
146: return(TRUE);
147: }
148:
149: /*
150: * convert task_id(queue postion) to task address
151: */
152: task_t
153: db_lookup_task_id(task_id)
154: register task_id;
155: {
156: register task_t task;
157: register processor_set_t pset;
158: register npset = 0;
159:
160: if (task_id > DB_MAX_TASKID)
161: return(TASK_NULL);
162: if (queue_first(&all_psets) == 0)
163: return(TASK_NULL);
164: queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
165: if (npset++ >= DB_MAX_PSETS)
166: return(TASK_NULL);
167: if (queue_first(&pset->tasks) == 0)
168: continue;
169: queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
170: if (task_id-- <= 0)
171: return(task);
172: }
173: }
174: return(TASK_NULL);
175: }
176:
177: /*
178: * convert (task_id, thread_id) pair to thread address
179: */
180: static thread_t
181: db_lookup_thread_id(task, thread_id)
182: task_t task;
183: register thread_id;
184: {
185: register thread_t thread;
186:
187:
188: if (thread_id > DB_MAX_THREADID)
189: return(THREAD_NULL);
190: if (queue_first(&task->thread_list) == 0)
191: return(THREAD_NULL);
192: queue_iterate(&task->thread_list, thread, thread_t, thread_list) {
193: if (thread_id-- <= 0)
194: return(thread);
195: }
196: return(THREAD_NULL);
197: }
198:
199: /*
200: * get next parameter from a command line, and check it as a valid
201: * thread address
202: */
203: boolean_t
204: db_get_next_thread(threadp, position)
205: thread_t *threadp;
206: int position;
207: {
208: db_expr_t value;
209: thread_t thread;
210:
211: *threadp = THREAD_NULL;
212: if (db_expression(&value)) {
213: thread = (thread_t) value;
214: if (!db_check_thread_address_valid(thread)) {
215: db_flush_lex();
216: return(FALSE);
217: }
218: } else if (position <= 0) {
219: thread = db_default_thread;
220: } else
221: return(FALSE);
222: *threadp = thread;
223: return(TRUE);
224: }
225:
226: /*
227: * check the default thread is still valid
228: * ( it is called in entering DDB session )
229: */
230: void
231: db_init_default_thread()
232: {
233: if (db_lookup_thread(db_default_thread) < 0) {
234: db_default_thread = THREAD_NULL;
235: db_default_task = TASK_NULL;
236: } else
237: db_default_task = db_default_thread->task;
238: }
239:
240: /*
241: * set or get default thread which is used when /t or :t option is specified
242: * in the command line
243: */
244: /* ARGSUSED */
245: int
246: db_set_default_thread(vp, valuep, flag)
247: struct db_variable *vp;
248: db_expr_t *valuep;
249: int flag;
250: {
251: thread_t thread;
252:
253: if (flag != DB_VAR_SET) {
254: *valuep = (db_expr_t) db_default_thread;
255: return(0);
256: }
257: thread = (thread_t) *valuep;
258: if (thread != THREAD_NULL && !db_check_thread_address_valid(thread))
259: db_error(0);
260: /* NOTREACHED */
261: db_default_thread = thread;
262: if (thread)
263: db_default_task = thread->task;
264: return(0);
265: }
266:
267: /*
268: * convert $taskXXX[.YYY] type DDB variable to task or thread address
269: */
270: int
271: db_get_task_thread(vp, valuep, flag, ap)
272: struct db_variable *vp;
273: db_expr_t *valuep;
274: int flag;
275: db_var_aux_param_t ap;
276: {
277: task_t task;
278: thread_t thread;
279:
280: if (flag != DB_VAR_GET) {
281: db_error("Cannot set to $task variable\n");
282: /* NOTREACHED */
283: }
284: if ((task = db_lookup_task_id(ap->suffix[0])) == TASK_NULL) {
285: db_printf("no such task($task%d)\n", ap->suffix[0]);
286: db_error(0);
287: /* NOTREACHED */
288: }
289: if (ap->level <= 1) {
290: *valuep = (db_expr_t) task;
291: return(0);
292: }
293: if ((thread = db_lookup_thread_id(task, ap->suffix[1])) == THREAD_NULL){
294: db_printf("no such thread($task%d.%d)\n",
295: ap->suffix[0], ap->suffix[1]);
296: db_error(0);
297: /* NOTREACHED */
298: }
299: *valuep = (db_expr_t) thread;
300: return(0);
301: }
302:
303: #endif MACH_KDB
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.