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 | ||