1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,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 Software.Distribution@CS.CMU.EDU
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 * HISTORY
28 * $Log: db_task_thread.c,v $
29 * Revision 2.6 93/11/17 16:25:42 dbg
30 * Added include of kern/processor.h.
31 * [93/04/10 dbg]
32 *
33 * Revision 2.5 93/01/14 17:25:54 danner
34 * Removed `static' from db_lookup_task_id so can be used elsewhere.
35 * [92/12/02 jfriedl]
36 * 64bit cleanup.
37 * [92/11/30 af]
38 *
39 * Revision 2.4 92/08/03 17:32:11 jfriedl
40 * removed silly prototypes
41 * [92/08/02 jfriedl]
42 *
43 * Revision 2.3 92/05/21 17:07:54 jfriedl
44 * tried prototypes.
45 * [92/05/20 jfriedl]
46 *
47 * Revision 2.2 91/10/09 16:03:04 af
48 * Created for task/thread handling.
49 * [91/08/29 tak]
50 *
51 */
52
53 #include <machine/db_machdep.h>
54 #include <ddb/db_command.h>
55 #include <ddb/db_lex.h>
56 #include <ddb/db_output.h>
57 #include <ddb/db_task_thread.h>
58 #include <ddb/db_variables.h>
59
60 #include <kern/processor.h>
61
62
63 /*
64 * Following constants are used to prevent infinite loop of task
65 * or thread search due to the incorrect list.
66 */
67 #define DB_MAX_TASKID 0x10000 /* max # of tasks */
68 #define DB_MAX_THREADID 0x10000 /* max # of threads in a task */
69 #define DB_MAX_PSETS 0x10000 /* max # of processor sets */
70
71 task_t db_default_task; /* default target task */
72 thread_t db_default_thread; /* default target thread */
73
74 /*
75 * search valid task queue, and return the queue position as the task id
76 */
77 int
78 db_lookup_task(
79 task_t target_task)
80 {
81 register task_t task;
82 register task_id;
83 register processor_set_t pset;
84 register int npset = 0;
85
86 task_id = 0;
87 if (queue_first(&all_psets) == 0)
88 return -1;
89 queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
90 if (npset++ >= DB_MAX_PSETS)
91 return -1;
92 if (queue_first(&pset->tasks) == 0)
93 continue;
94 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
95 if (target_task == task)
96 return task_id;
97 if (task_id++ >= DB_MAX_TASKID)
98 return -1;
99 }
100 }
101 return -1;
102 }
103
104 /*
105 * search thread queue of the task, and return the queue position
106 */
107 int
108 db_lookup_task_thread(
109 task_t task,
110 thread_t target_thread)
111 {
112 register thread_t thread;
113 register thread_id;
114
115 thread_id = 0;
116 if (queue_first(&task->thread_list) == 0)
117 return -1;
118 queue_iterate(&task->thread_list, thread, thread_t, thread_list) {
119 if (target_thread == thread)
120 return thread_id;
121 if (thread_id++ >= DB_MAX_THREADID)
122 return -1;
123 }
124 return -1;
125 }
126
127 /*
128 * search thread queue of every valid task, and return the queue position
129 * as the thread id.
130 */
131 int
132 db_lookup_thread(
133 thread_t target_thread)
134 {
135 register thread_id;
136 register task_t task;
137 register processor_set_t pset;
138 register ntask = 0;
139 register npset = 0;
140
141 if (queue_first(&all_psets) == 0)
142 return -1;
143 queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
144 if (npset++ >= DB_MAX_PSETS)
145 return -1;
146 if (queue_first(&pset->tasks) == 0)
147 continue;
148 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
149 if (ntask++ > DB_MAX_TASKID)
150 return -1;
151 if (task->thread_count == 0)
152 continue;
153 thread_id = db_lookup_task_thread(task, target_thread);
154 if (thread_id >= 0)
155 return thread_id;
156 }
157 }
158 return -1;
159 }
160
161 /*
162 * check the address is a valid thread address
163 */
164 boolean_t
165 db_check_thread_address_valid(
166 db_addr_t address)
167 {
168 if (db_lookup_thread((thread_t) address) < 0) {
169 db_printf("Bad thread address %#x\n", address);
170 db_flush_lex();
171 return FALSE;
172 } else
173 return TRUE;
174 }
175
176 /*
177 * convert task_id(queue postion) to task address
178 */
179 task_t
180 db_lookup_task_id(
181 register int task_id)
182 {
183 register task_t task;
184 register processor_set_t pset;
185 register int npset = 0;
186
187 if (task_id > DB_MAX_TASKID)
188 return TASK_NULL;
189 if (queue_first(&all_psets) == 0)
190 return TASK_NULL;
191 queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
192 if (npset++ >= DB_MAX_PSETS)
193 return TASK_NULL;
194 if (queue_first(&pset->tasks) == 0)
195 continue;
196 queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
197 if (task_id-- <= 0)
198 return task;
199 }
200 }
201 return TASK_NULL;
202 }
203
204 /*
205 * convert (task_id, thread_id) pair to thread address
206 */
207 static thread_t
208 db_lookup_thread_id(
209 task_t task,
210 register int thread_id)
211 {
212 register thread_t thread;
213
214
215 if (thread_id > DB_MAX_THREADID)
216 return THREAD_NULL;
217 if (queue_first(&task->thread_list) == 0)
218 return THREAD_NULL;
219 queue_iterate(&task->thread_list, thread, thread_t, thread_list) {
220 if (thread_id-- <= 0)
221 return thread;
222 }
223 return THREAD_NULL;
224 }
225
226 /*
227 * get next parameter from a command line, and check it as a valid
228 * thread address
229 */
230 boolean_t
231 db_get_next_thread(
232 thread_t *threadp,
233 int position)
234 {
235 db_expr_t value;
236 thread_t thread;
237
238 *threadp = THREAD_NULL;
239 if (db_expression(&value)) {
240 if (!db_check_thread_address_valid(value)) {
241 db_flush_lex();
242 return FALSE;
243 }
244 thread = (thread_t) value;
245 } else if (position <= 0) {
246 thread = db_default_thread;
247 } else
248 return FALSE;
249 *threadp = thread;
250 return TRUE;
251 }
252
253 /*
254 * check the default thread is still valid
255 * ( it is called in entering DDB session )
256 */
257 void
258 db_init_default_thread(void)
259 {
260 if (db_lookup_thread(db_default_thread) < 0) {
261 db_default_thread = THREAD_NULL;
262 db_default_task = TASK_NULL;
263 } else
264 db_default_task = db_default_thread->task;
265 }
266
267 /*
268 * set or get default thread which is used when /t or :t option is specified
269 * in the command line
270 */
271 /* ARGSUSED */
272 void
273 db_set_default_thread(
274 struct db_variable *vp,
275 db_expr_t *valuep,
276 int flag,
277 db_var_aux_param_t ap)
278 {
279 thread_t thread;
280
281 if (flag != DB_VAR_SET) {
282 *valuep = (db_expr_t) db_default_thread;
283 return;
284 }
285 thread = (thread_t) *valuep;
286 if (thread != THREAD_NULL &&
287 !db_check_thread_address_valid((db_expr_t)thread))
288 {
289 db_error(0);
290 /* NOTREACHED */
291 }
292 db_default_thread = thread;
293 if (thread)
294 db_default_task = thread->task;
295 }
296
297 /*
298 * convert $taskXXX[.YYY] type DDB variable to task or thread address
299 */
300 void
301 db_get_task_thread(
302 struct db_variable *vp,
303 db_expr_t *valuep,
304 int flag,
305 db_var_aux_param_t ap)
306 {
307 task_t task;
308 thread_t thread;
309
310 if (flag != DB_VAR_GET) {
311 db_error("Cannot set to $task variable\n");
312 /* NOTREACHED */
313 }
314 if ((task = db_lookup_task_id(ap->suffix[0])) == TASK_NULL) {
315 db_printf("no such task($task%d)\n", ap->suffix[0]);
316 db_error(0);
317 /* NOTREACHED */
318 }
319 if (ap->level <= 1) {
320 *valuep = (db_expr_t) task;
321 return;
322 }
323 if ((thread = db_lookup_thread_id(task, ap->suffix[1])) == THREAD_NULL){
324 db_printf("no such thread($task%d.%d)\n",
325 ap->suffix[0], ap->suffix[1]);
326 db_error(0);
327 /* NOTREACHED */
328 }
329 *valuep = (db_expr_t) thread;
330 }
Cache object: 20934ee66cbe4ae85cfb2a94730b0976
|