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