Rev 3015 | Rev 3018 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3015 | Rev 3016 | ||
---|---|---|---|
Line 41... | Line 41... | ||
41 | #include <errno.h> |
41 | #include <errno.h> |
42 | #include <arch.h> |
42 | #include <arch.h> |
43 | 43 | ||
44 | void udebug_task_init(udebug_task_t *ut) |
44 | void udebug_task_init(udebug_task_t *ut) |
45 | { |
45 | { |
- | 46 | mutex_initialize(&ut->lock); |
|
46 | ut->dt_state = UDEBUG_TS_INACTIVE; |
47 | ut->dt_state = UDEBUG_TS_INACTIVE; |
47 | ut->begin_call = NULL; |
48 | ut->begin_call = NULL; |
48 | ut->not_stoppable_count = 0; |
49 | ut->not_stoppable_count = 0; |
49 | ut->evmask = 0; |
50 | ut->evmask = 0; |
50 | } |
51 | } |
Line 69... | Line 70... | ||
69 | ipl_t ipl; |
70 | ipl_t ipl; |
70 | 71 | ||
71 | ASSERT(THREAD); |
72 | ASSERT(THREAD); |
72 | ASSERT(TASK); |
73 | ASSERT(TASK); |
73 | 74 | ||
74 | ipl = interrupts_disable(); |
- | |
75 | spinlock_lock(&TASK->lock); |
75 | mutex_lock(&TASK->udebug.lock); |
76 | 76 | ||
77 | nsc = --TASK->udebug.not_stoppable_count; |
77 | nsc = --TASK->udebug.not_stoppable_count; |
78 | 78 | ||
79 | if (TASK->udebug.dt_state == UDEBUG_TS_BEGINNING) { |
79 | if (TASK->udebug.dt_state == UDEBUG_TS_BEGINNING) { |
80 | klog_printf("udebug_stoppable_begin"); |
80 | klog_printf("udebug_stoppable_begin"); |
Line 88... | Line 88... | ||
88 | */ |
88 | */ |
89 | 89 | ||
90 | db_call = TASK->udebug.begin_call; |
90 | db_call = TASK->udebug.begin_call; |
91 | ASSERT(db_call); |
91 | ASSERT(db_call); |
92 | 92 | ||
93 | /* Lock order OK, THREAD->debug_lock is after TASK->lock */ |
93 | /* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */ |
- | 94 | ipl = interrupts_disable(); |
|
94 | spinlock_lock(&THREAD->debug_lock); |
95 | spinlock_lock(&THREAD->debug_lock); |
95 | THREAD->debug_stoppable = true; |
96 | THREAD->debug_stoppable = true; |
96 | spinlock_unlock(&THREAD->debug_lock); |
97 | spinlock_unlock(&THREAD->debug_lock); |
- | 98 | interrupts_restore(ipl); |
|
97 | 99 | ||
98 | TASK->udebug.dt_state = UDEBUG_TS_ACTIVE; |
100 | TASK->udebug.dt_state = UDEBUG_TS_ACTIVE; |
99 | TASK->udebug.begin_call = NULL; |
101 | TASK->udebug.begin_call = NULL; |
100 | spinlock_unlock(&TASK->lock); |
102 | mutex_unlock(&TASK->udebug.lock); |
101 | interrupts_restore(ipl); |
- | |
102 | 103 | ||
103 | IPC_SET_RETVAL(db_call->data, 0); |
104 | IPC_SET_RETVAL(db_call->data, 0); |
104 | //klog_printf("udebug_stoppable_begin/ipc_answer"); |
105 | //klog_printf("udebug_stoppable_begin/ipc_answer"); |
105 | ipc_answer(&TASK->answerbox, db_call); |
106 | ipc_answer(&TASK->answerbox, db_call); |
106 | 107 | ||
107 | } else if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) { |
108 | } else if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) { |
108 | /* |
109 | /* |
109 | * Active debugging session |
110 | * Active debugging session |
110 | */ |
111 | */ |
111 | 112 | ||
112 | /* Lock order OK, THREAD->debug_lock is after TASK->lock */ |
113 | /* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */ |
- | 114 | ipl = interrupts_disable(); |
|
113 | spinlock_lock(&THREAD->debug_lock); |
115 | spinlock_lock(&THREAD->debug_lock); |
114 | THREAD->debug_stoppable = true; |
116 | THREAD->debug_stoppable = true; |
115 | 117 | ||
116 | if (THREAD->debug_active && THREAD->debug_stop) { |
118 | if (THREAD->debug_active && THREAD->debug_stop) { |
117 | /* |
119 | /* |
Line 126... | Line 128... | ||
126 | IPC_SET_RETVAL(go_call->data, 0); |
128 | IPC_SET_RETVAL(go_call->data, 0); |
127 | IPC_SET_ARG1(go_call->data, UDEBUG_EVENT_STOP); |
129 | IPC_SET_ARG1(go_call->data, UDEBUG_EVENT_STOP); |
128 | 130 | ||
129 | THREAD->cur_event = UDEBUG_EVENT_STOP; |
131 | THREAD->cur_event = UDEBUG_EVENT_STOP; |
130 | spinlock_unlock(&THREAD->debug_lock); |
132 | spinlock_unlock(&THREAD->debug_lock); |
- | 133 | interrupts_restore(ipl); |
|
131 | 134 | ||
132 | ipc_answer(&TASK->answerbox, go_call); |
135 | ipc_answer(&TASK->answerbox, go_call); |
133 | 136 | ||
134 | spinlock_unlock(&TASK->lock); |
137 | mutex_unlock(&TASK->udebug.lock); |
135 | interrupts_restore(ipl); |
- | |
136 | } else { |
138 | } else { |
137 | /* |
139 | /* |
138 | * No stop request - nothing happens. |
140 | * No stop request - nothing happens. |
139 | */ |
141 | */ |
140 | spinlock_unlock(&THREAD->debug_lock); |
142 | spinlock_unlock(&THREAD->debug_lock); |
141 | spinlock_unlock(&TASK->lock); |
- | |
142 | interrupts_restore(ipl); |
143 | interrupts_restore(ipl); |
- | 144 | mutex_unlock(&TASK->udebug.lock); |
|
143 | } |
145 | } |
144 | } else { |
146 | } else { |
145 | /* |
147 | /* |
146 | * All other cases - nothing special happens. |
148 | * All other cases - nothing special happens. |
147 | */ |
149 | */ |
148 | 150 | ||
149 | /* Lock order OK, THREAD->debug_lock is after TASK->lock */ |
151 | /* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */ |
- | 152 | ipl = interrupts_disable(); |
|
150 | spinlock_lock(&THREAD->debug_lock); |
153 | spinlock_lock(&THREAD->debug_lock); |
151 | THREAD->debug_stoppable = true; |
154 | THREAD->debug_stoppable = true; |
152 | spinlock_unlock(&THREAD->debug_lock); |
155 | spinlock_unlock(&THREAD->debug_lock); |
153 | - | ||
154 | spinlock_unlock(&TASK->lock); |
- | |
155 | interrupts_restore(ipl); |
156 | interrupts_restore(ipl); |
- | 157 | ||
- | 158 | mutex_unlock(&TASK->udebug.lock); |
|
156 | } |
159 | } |
157 | } |
160 | } |
158 | 161 | ||
159 | void udebug_stoppable_end(void) |
162 | void udebug_stoppable_end(void) |
160 | { |
163 | { |
161 | ipl_t ipl; |
164 | ipl_t ipl; |
162 | 165 | ||
163 | restart: |
166 | restart: |
164 | ipl = interrupts_disable(); |
- | |
165 | spinlock_lock(&TASK->lock); |
167 | mutex_lock(&TASK->udebug.lock); |
166 | 168 | ||
167 | /* Lock order OK, THREAD->debug_lock is after TASK->lock */ |
169 | /* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */ |
- | 170 | ipl = interrupts_disable(); |
|
168 | spinlock_lock(&THREAD->debug_lock); |
171 | spinlock_lock(&THREAD->debug_lock); |
169 | 172 | ||
170 | if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) { |
173 | if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) { |
171 | //klog_printf("udebug_stoppable_end"); |
174 | //klog_printf("udebug_stoppable_end"); |
172 | //klog_printf("debug_stop=%d", THREAD->debug_stop); |
175 | //klog_printf("debug_stop=%d", THREAD->debug_stop); |
Line 174... | Line 177... | ||
174 | 177 | ||
175 | if (THREAD->debug_active && |
178 | if (THREAD->debug_active && |
176 | THREAD->debug_stop == true) { |
179 | THREAD->debug_stop == true) { |
177 | TASK->udebug.begin_call = NULL; |
180 | TASK->udebug.begin_call = NULL; |
178 | spinlock_unlock(&THREAD->debug_lock); |
181 | spinlock_unlock(&THREAD->debug_lock); |
179 | spinlock_unlock(&TASK->lock); |
- | |
180 | interrupts_restore(ipl); |
182 | interrupts_restore(ipl); |
- | 183 | mutex_unlock(&TASK->udebug.lock); |
|
181 | 184 | ||
182 | udebug_wait_for_go(&THREAD->go_wq); |
185 | udebug_wait_for_go(&THREAD->go_wq); |
183 | 186 | ||
184 | goto restart; |
187 | goto restart; |
185 | /* must try again - have to lose stoppability atomically */ |
188 | /* must try again - have to lose stoppability atomically */ |
186 | } else { |
189 | } else { |
187 | ++TASK->udebug.not_stoppable_count; |
190 | ++TASK->udebug.not_stoppable_count; |
188 | THREAD->debug_stoppable = false; |
191 | THREAD->debug_stoppable = false; |
189 | 192 | ||
190 | spinlock_unlock(&THREAD->debug_lock); |
193 | spinlock_unlock(&THREAD->debug_lock); |
191 | spinlock_unlock(&TASK->lock); |
- | |
192 | interrupts_restore(ipl); |
194 | interrupts_restore(ipl); |
- | 195 | mutex_unlock(&TASK->udebug.lock); |
|
193 | } |
196 | } |
194 | } |
197 | } |
195 | 198 | ||
196 | /** Upon being scheduled to run, check if the current thread should stop. |
199 | /** Upon being scheduled to run, check if the current thread should stop. |
197 | * |
200 | * |
Line 209... | Line 212... | ||
209 | return; |
212 | return; |
210 | 213 | ||
211 | THREAD->debug_in_before_thread_runs = true; |
214 | THREAD->debug_in_before_thread_runs = true; |
212 | ipl = interrupts_enable(); |
215 | ipl = interrupts_enable(); |
213 | 216 | ||
214 | /* Now we're free to do whatever we need (lock mutexes, etc.) */ |
217 | /* Now we're free to do whatever we need (lock mutexes, sleep, etc.) */ |
215 | 218 | ||
216 | /* Check if we're supposed to stop */ |
219 | /* Check if we're supposed to stop */ |
217 | udebug_stoppable_begin(); |
220 | udebug_stoppable_begin(); |
218 | udebug_stoppable_end(); |
221 | udebug_stoppable_end(); |
219 | 222 | ||
Line 229... | Line 232... | ||
229 | ipl_t ipl; |
232 | ipl_t ipl; |
230 | udebug_event_t etype; |
233 | udebug_event_t etype; |
231 | 234 | ||
232 | etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B; |
235 | etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B; |
233 | 236 | ||
- | 237 | mutex_lock(&TASK->udebug.lock); |
|
- | 238 | ||
234 | ipl = interrupts_disable(); |
239 | ipl = interrupts_disable(); |
235 | spinlock_lock(&THREAD->debug_lock); |
240 | spinlock_lock(&THREAD->debug_lock); |
236 | 241 | ||
237 | /* Must only generate events when in debugging session and have go */ |
242 | /* Must only generate events when in debugging session and have go */ |
238 | if (THREAD->debug_active != true || |
243 | if (THREAD->debug_active != true || |
239 | THREAD->debug_stop == true || |
244 | THREAD->debug_stop == true || |
240 | (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) { |
245 | (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) { |
241 | spinlock_unlock(&THREAD->debug_lock); |
246 | spinlock_unlock(&THREAD->debug_lock); |
242 | interrupts_restore(ipl); |
247 | interrupts_restore(ipl); |
- | 248 | mutex_unlock(&TASK->udebug.lock); |
|
243 | return; |
249 | return; |
244 | } |
250 | } |
245 | 251 | ||
246 | //klog_printf("udebug_syscall_event"); |
252 | //klog_printf("udebug_syscall_event"); |
247 | call = THREAD->debug_go_call; |
253 | call = THREAD->debug_go_call; |
- | 254 | THREAD->debug_go_call = NULL; |
|
- | 255 | ||
248 | IPC_SET_RETVAL(call->data, 0); |
256 | IPC_SET_RETVAL(call->data, 0); |
249 | IPC_SET_ARG1(call->data, etype); |
257 | IPC_SET_ARG1(call->data, etype); |
250 | IPC_SET_ARG2(call->data, id); |
258 | IPC_SET_ARG2(call->data, id); |
251 | IPC_SET_ARG3(call->data, rc); |
259 | IPC_SET_ARG3(call->data, rc); |
252 | //klog_printf("udebug_syscall_event/ipc_answer"); |
260 | //klog_printf("udebug_syscall_event/ipc_answer"); |
Line 265... | Line 273... | ||
265 | */ |
273 | */ |
266 | THREAD->debug_stop = true; |
274 | THREAD->debug_stop = true; |
267 | 275 | ||
268 | THREAD->cur_event = etype; |
276 | THREAD->cur_event = etype; |
269 | spinlock_unlock(&THREAD->debug_lock); |
277 | spinlock_unlock(&THREAD->debug_lock); |
270 | - | ||
271 | spinlock_lock(&TASK->lock); |
- | |
272 | ipc_answer(&TASK->answerbox, THREAD->debug_go_call); |
- | |
273 | spinlock_unlock(&TASK->lock); |
- | |
274 | interrupts_restore(ipl); |
278 | interrupts_restore(ipl); |
275 | 279 | ||
- | 280 | ipc_answer(&TASK->answerbox, call); |
|
- | 281 | ||
- | 282 | mutex_unlock(&TASK->udebug.lock); |
|
- | 283 | ||
276 | udebug_wait_for_go(&THREAD->go_wq); |
284 | udebug_wait_for_go(&THREAD->go_wq); |
277 | } |
285 | } |
278 | 286 | ||
279 | void udebug_thread_b_event(struct thread *t) |
287 | void udebug_thread_b_event(struct thread *t) |
280 | { |
288 | { |
281 | call_t *call; |
289 | call_t *call; |
282 | ipl_t ipl; |
290 | ipl_t ipl; |
283 | 291 | ||
- | 292 | mutex_lock(&TASK->udebug.lock); |
|
- | 293 | ||
284 | ipl = interrupts_disable(); |
294 | ipl = interrupts_disable(); |
285 | spinlock_lock(&THREAD->debug_lock); |
295 | spinlock_lock(&THREAD->debug_lock); |
286 | 296 | ||
287 | klog_printf("udebug_thread_b_event"); |
297 | klog_printf("udebug_thread_b_event"); |
288 | klog_printf("- check state"); |
298 | klog_printf("- check state"); |
Line 292... | Line 302... | ||
292 | klog_printf("- debug_active: %s, debug_stop: %s", |
302 | klog_printf("- debug_active: %s, debug_stop: %s", |
293 | THREAD->debug_active ? "yes(+)" : "no(-)", |
303 | THREAD->debug_active ? "yes(+)" : "no(-)", |
294 | THREAD->debug_stop ? "yes(-)" : "no(+)"); |
304 | THREAD->debug_stop ? "yes(-)" : "no(+)"); |
295 | spinlock_unlock(&THREAD->debug_lock); |
305 | spinlock_unlock(&THREAD->debug_lock); |
296 | interrupts_restore(ipl); |
306 | interrupts_restore(ipl); |
- | 307 | mutex_unlock(&TASK->udebug.lock); |
|
297 | return; |
308 | return; |
298 | } |
309 | } |
299 | 310 | ||
300 | klog_printf("- trigger event"); |
311 | klog_printf("- trigger event"); |
301 | 312 | ||
302 | call = THREAD->debug_go_call; |
313 | call = THREAD->debug_go_call; |
- | 314 | THREAD->debug_go_call = NULL; |
|
303 | IPC_SET_RETVAL(call->data, 0); |
315 | IPC_SET_RETVAL(call->data, 0); |
304 | IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B); |
316 | IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B); |
305 | IPC_SET_ARG2(call->data, (unative_t)t); |
317 | IPC_SET_ARG2(call->data, (unative_t)t); |
306 | 318 | ||
307 | /* |
319 | /* |
Line 311... | Line 323... | ||
311 | */ |
323 | */ |
312 | THREAD->debug_stop = true; |
324 | THREAD->debug_stop = true; |
313 | 325 | ||
314 | THREAD->cur_event = UDEBUG_EVENT_THREAD_B; |
326 | THREAD->cur_event = UDEBUG_EVENT_THREAD_B; |
315 | spinlock_unlock(&THREAD->debug_lock); |
327 | spinlock_unlock(&THREAD->debug_lock); |
- | 328 | interrupts_restore(ipl); |
|
316 | 329 | ||
317 | spinlock_lock(&TASK->lock); |
- | |
318 | ipc_answer(&TASK->answerbox, THREAD->debug_go_call); |
330 | ipc_answer(&TASK->answerbox, call); |
- | 331 | ||
319 | spinlock_unlock(&TASK->lock); |
332 | mutex_unlock(&TASK->udebug.lock); |
320 | 333 | ||
321 | interrupts_restore(ipl); |
- | |
322 | klog_printf("- sleep"); |
334 | klog_printf("- sleep"); |
323 | udebug_wait_for_go(&THREAD->go_wq); |
335 | udebug_wait_for_go(&THREAD->go_wq); |
324 | } |
336 | } |
325 | 337 | ||
326 | void udebug_thread_e_event(void) |
338 | void udebug_thread_e_event(void) |
327 | { |
339 | { |
328 | call_t *call; |
340 | call_t *call; |
329 | ipl_t ipl; |
341 | ipl_t ipl; |
330 | 342 | ||
- | 343 | mutex_lock(&TASK->udebug.lock); |
|
- | 344 | ||
331 | ipl = interrupts_disable(); |
345 | ipl = interrupts_disable(); |
332 | spinlock_lock(&THREAD->debug_lock); |
346 | spinlock_lock(&THREAD->debug_lock); |
333 | 347 | ||
334 | klog_printf("udebug_thread_e_event"); |
348 | klog_printf("udebug_thread_e_event"); |
335 | klog_printf("- check state"); |
349 | klog_printf("- check state"); |
Line 339... | Line 353... | ||
339 | klog_printf("- debug_active: %s, debug_stop: %s", |
353 | klog_printf("- debug_active: %s, debug_stop: %s", |
340 | THREAD->debug_active ? "yes(+)" : "no(-)", |
354 | THREAD->debug_active ? "yes(+)" : "no(-)", |
341 | THREAD->debug_stop ? "yes(-)" : "no(+)"); |
355 | THREAD->debug_stop ? "yes(-)" : "no(+)"); |
342 | spinlock_unlock(&THREAD->debug_lock); |
356 | spinlock_unlock(&THREAD->debug_lock); |
343 | interrupts_restore(ipl); |
357 | interrupts_restore(ipl); |
- | 358 | mutex_unlock(&TASK->udebug.lock); |
|
344 | return; |
359 | return; |
345 | } |
360 | } |
346 | 361 | ||
347 | klog_printf("- trigger event"); |
362 | klog_printf("- trigger event"); |
348 | 363 | ||
349 | call = THREAD->debug_go_call; |
364 | call = THREAD->debug_go_call; |
- | 365 | THREAD->debug_go_call = NULL; |
|
350 | IPC_SET_RETVAL(call->data, 0); |
366 | IPC_SET_RETVAL(call->data, 0); |
351 | IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E); |
367 | IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E); |
352 | 368 | ||
353 | /* Prevent any further debug activity in thread */ |
369 | /* Prevent any further debug activity in thread */ |
354 | THREAD->debug_active = false; |
370 | THREAD->debug_active = false; |
355 | THREAD->cur_event = 0; /* none */ |
371 | THREAD->cur_event = 0; /* none */ |
356 | THREAD->debug_stop = true; /* set to initial value */ |
372 | THREAD->debug_stop = true; /* set to initial value */ |
- | 373 | ||
357 | spinlock_unlock(&THREAD->debug_lock); |
374 | spinlock_unlock(&THREAD->debug_lock); |
- | 375 | interrupts_restore(ipl); |
|
358 | 376 | ||
359 | spinlock_lock(&TASK->lock); |
- | |
360 | ipc_answer(&TASK->answerbox, THREAD->debug_go_call); |
377 | ipc_answer(&TASK->answerbox, call); |
361 | spinlock_unlock(&TASK->lock); |
- | |
362 | 378 | ||
363 | interrupts_restore(ipl); |
379 | mutex_unlock(&TASK->udebug.lock); |
364 | 380 | ||
365 | /* This event does not sleep - debugging has finished in this thread */ |
381 | /* This event does not sleep - debugging has finished in this thread */ |
366 | } |
382 | } |
367 | 383 | ||
368 | static void breakpoint_trap_event(uintptr_t addr, udebug_event_t etype) |
384 | static void breakpoint_trap_event(uintptr_t addr, udebug_event_t etype) |
369 | { |
385 | { |
370 | call_t *call; |
386 | call_t *call; |
371 | ipl_t ipl; |
387 | ipl_t ipl; |
372 | 388 | ||
- | 389 | mutex_lock(&TASK->udebug.lock); |
|
- | 390 | ||
373 | ipl = interrupts_disable(); |
391 | ipl = interrupts_disable(); |
374 | spinlock_lock(&THREAD->debug_lock); |
392 | spinlock_lock(&THREAD->debug_lock); |
375 | 393 | ||
376 | /* Must only generate events when in debugging session and have go */ |
394 | /* Must only generate events when in debugging session and have go */ |
377 | if (THREAD->debug_active != true || |
395 | if (THREAD->debug_active != true || |
378 | THREAD->debug_stop == true || |
396 | THREAD->debug_stop == true || |
379 | (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) { |
397 | (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) { |
380 | spinlock_unlock(&THREAD->debug_lock); |
398 | spinlock_unlock(&THREAD->debug_lock); |
381 | interrupts_restore(ipl); |
399 | interrupts_restore(ipl); |
- | 400 | mutex_unlock(&TASK->udebug.lock); |
|
382 | return; |
401 | return; |
383 | } |
402 | } |
384 | 403 | ||
385 | klog_printf("udebug_breakpoint/trap_event"); |
404 | klog_printf("udebug_breakpoint/trap_event"); |
386 | call = THREAD->debug_go_call; |
405 | call = THREAD->debug_go_call; |
- | 406 | THREAD->debug_go_call = NULL; |
|
- | 407 | ||
387 | IPC_SET_RETVAL(call->data, 0); |
408 | IPC_SET_RETVAL(call->data, 0); |
388 | IPC_SET_ARG1(call->data, etype); |
409 | IPC_SET_ARG1(call->data, etype); |
389 | IPC_SET_ARG2(call->data, addr); |
410 | IPC_SET_ARG2(call->data, addr); |
390 | 411 | ||
391 | /* |
412 | /* |
Line 395... | Line 416... | ||
395 | */ |
416 | */ |
396 | THREAD->debug_stop = true; |
417 | THREAD->debug_stop = true; |
397 | 418 | ||
398 | THREAD->cur_event = etype; |
419 | THREAD->cur_event = etype; |
399 | spinlock_unlock(&THREAD->debug_lock); |
420 | spinlock_unlock(&THREAD->debug_lock); |
- | 421 | interrupts_restore(ipl); |
|
400 | klog_printf("- send answer"); |
422 | klog_printf("- send answer"); |
401 | 423 | ||
402 | spinlock_lock(&TASK->lock); |
- | |
403 | ipc_answer(&TASK->answerbox, THREAD->debug_go_call); |
424 | ipc_answer(&TASK->answerbox, call); |
404 | spinlock_unlock(&TASK->lock); |
425 | mutex_unlock(&TASK->udebug.lock); |
405 | interrupts_restore(ipl); |
- | |
406 | 426 | ||
407 | udebug_wait_for_go(&THREAD->go_wq); |
427 | udebug_wait_for_go(&THREAD->go_wq); |
408 | } |
428 | } |
409 | 429 | ||
410 | void udebug_breakpoint_event(uintptr_t addr) |
430 | void udebug_breakpoint_event(uintptr_t addr) |
Line 418... | Line 438... | ||
418 | } |
438 | } |
419 | 439 | ||
420 | /** |
440 | /** |
421 | * Terminate task debugging session. |
441 | * Terminate task debugging session. |
422 | * |
442 | * |
423 | * \param ta Must be already locked and interrupts must be disabled. |
443 | * \param ta->udebug.lock must be already locked. |
424 | * \return Zero on success or negative error code. |
444 | * \return Zero on success or negative error code. |
425 | */ |
445 | */ |
426 | int udebug_task_cleanup(struct task *ta) |
446 | int udebug_task_cleanup(struct task *ta) |
427 | { |
447 | { |
428 | thread_t *t; |
448 | thread_t *t; |
429 | link_t *cur; |
449 | link_t *cur; |
430 | int flags; |
450 | int flags; |
- | 451 | ipl_t ipl; |
|
431 | 452 | ||
432 | klog_printf("udebug_task_cleanup()"); |
453 | klog_printf("udebug_task_cleanup()"); |
433 | klog_printf("task %llu", ta->taskid); |
454 | klog_printf("task %llu", ta->taskid); |
434 | 455 | ||
435 | if (ta->udebug.dt_state == UDEBUG_TS_BEGINNING && |
456 | if (ta->udebug.dt_state == UDEBUG_TS_BEGINNING && |
Line 440... | Line 461... | ||
440 | 461 | ||
441 | /* Finish debugging of all userspace threads */ |
462 | /* Finish debugging of all userspace threads */ |
442 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
463 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
443 | t = list_get_instance(cur, thread_t, th_link); |
464 | t = list_get_instance(cur, thread_t, th_link); |
444 | 465 | ||
- | 466 | ipl = interrupts_disable(); |
|
445 | spinlock_lock(&t->debug_lock); |
467 | spinlock_lock(&t->debug_lock); |
446 | spinlock_lock(&t->lock); |
468 | spinlock_lock(&t->lock); |
447 | 469 | ||
448 | flags = t->flags; |
470 | flags = t->flags; |
449 | 471 | ||
Line 465... | Line 487... | ||
465 | 487 | ||
466 | /* Answer GO call */ |
488 | /* Answer GO call */ |
467 | klog_printf("answer GO call with EVENT_FINISHED"); |
489 | klog_printf("answer GO call with EVENT_FINISHED"); |
468 | IPC_SET_RETVAL(t->debug_go_call->data, 0); |
490 | IPC_SET_RETVAL(t->debug_go_call->data, 0); |
469 | IPC_SET_ARG1(t->debug_go_call->data, UDEBUG_EVENT_FINISHED); |
491 | IPC_SET_ARG1(t->debug_go_call->data, UDEBUG_EVENT_FINISHED); |
- | 492 | /* FIXME: must not call with interrupts disabled!!*/ |
|
470 | ipc_answer(&ta->answerbox, t->debug_go_call); |
493 | ipc_answer(&ta->answerbox, t->debug_go_call); |
- | 494 | t->debug_go_call = NULL; |
|
471 | } else { |
495 | } else { |
472 | /* |
496 | /* |
473 | * Debug_stop is already at initial value. |
497 | * Debug_stop is already at initial value. |
474 | * Yet this means the thread needs waking up. |
498 | * Yet this means the thread needs waking up. |
475 | */ |
499 | */ |
Line 480... | Line 504... | ||
480 | */ |
504 | */ |
481 | waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
505 | waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
482 | } |
506 | } |
483 | } |
507 | } |
484 | spinlock_unlock(&t->debug_lock); |
508 | spinlock_unlock(&t->debug_lock); |
- | 509 | interrupts_restore(ipl); |
|
485 | } |
510 | } |
486 | 511 | ||
487 | ta->udebug.dt_state = UDEBUG_TS_INACTIVE; |
512 | ta->udebug.dt_state = UDEBUG_TS_INACTIVE; |
488 | ta->udebug.debugger = NULL; |
513 | ta->udebug.debugger = NULL; |
489 | 514 |