Rev 2897 | Rev 2899 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2897 | Rev 2898 | ||
---|---|---|---|
Line 50... | Line 50... | ||
50 | * |
50 | * |
51 | * Simply put, return thread t with t->debug_lock held, |
51 | * Simply put, return thread t with t->debug_lock held, |
52 | * but only if it verifies all conditions. |
52 | * but only if it verifies all conditions. |
53 | * |
53 | * |
54 | * Specifically, verifies that thread t exists, is a userspace thread, |
54 | * Specifically, verifies that thread t exists, is a userspace thread, |
55 | * and belongs to the current task (TASK). It also locks t->debug_lock, |
55 | * and belongs to the current task (TASK). Verifies, that the thread |
- | 56 | * has (or hasn't) go according to having_go (typically false). |
|
56 | * making sure that t->debug_active is true - that the thread is |
57 | * It also locks t->debug_lock, making sure that t->debug_active is true |
57 | * in a valid debugging session. |
58 | * - that the thread is in a valid debugging session. |
58 | * |
59 | * |
59 | * Returns EOK if all went well, or an error code otherwise. |
60 | * Returns EOK if all went well, or an error code otherwise. |
60 | * Interrupts must be already disabled when calling this function. |
61 | * Interrupts must be already disabled when calling this function. |
61 | * |
62 | * |
62 | * Note: This function sports complicated locking. |
63 | * Note: This function sports complicated locking. |
63 | */ |
64 | */ |
64 | static int _thread_op_begin(thread_t *t) |
65 | static int _thread_op_begin(thread_t *t, bool having_go) |
65 | { |
66 | { |
66 | int rc; |
67 | int rc; |
67 | task_id_t taskid; |
68 | task_id_t taskid; |
68 | 69 | ||
69 | taskid = TASK->taskid; |
70 | taskid = TASK->taskid; |
Line 91... | Line 92... | ||
91 | /* It's not, deny its existence */ |
92 | /* It's not, deny its existence */ |
92 | rc = ENOENT; |
93 | rc = ENOENT; |
93 | goto error_exit; |
94 | goto error_exit; |
94 | } |
95 | } |
95 | 96 | ||
96 | if ((t->debug_active != true) || (t->debug_stop != true)) { |
97 | if ((t->debug_active != true) || (!t->debug_stop != having_go)) { |
97 | /* Not in debugging session or already has GO */ |
98 | /* Not in debugging session or undesired GO state */ |
98 | rc = ENOENT; |
99 | rc = EINVAL; |
99 | goto error_exit; |
100 | goto error_exit; |
100 | } |
101 | } |
101 | 102 | ||
102 | spinlock_unlock(&threads_lock); |
103 | spinlock_unlock(&threads_lock); |
103 | spinlock_unlock(&t->lock); |
104 | spinlock_unlock(&t->lock); |
Line 211... | Line 212... | ||
211 | klog_printf("udebug_go()"); |
212 | klog_printf("udebug_go()"); |
212 | 213 | ||
213 | ipl = interrupts_disable(); |
214 | ipl = interrupts_disable(); |
214 | 215 | ||
215 | /* On success, this will lock t->debug_lock */ |
216 | /* On success, this will lock t->debug_lock */ |
216 | rc = _thread_op_begin(t); |
217 | rc = _thread_op_begin(t, false); |
217 | if (rc != EOK) { |
218 | if (rc != EOK) { |
218 | interrupts_restore(ipl); |
219 | interrupts_restore(ipl); |
219 | return rc; |
220 | return rc; |
220 | } |
221 | } |
221 | 222 | ||
Line 232... | Line 233... | ||
232 | interrupts_restore(ipl); |
233 | interrupts_restore(ipl); |
233 | 234 | ||
234 | return 0; |
235 | return 0; |
235 | } |
236 | } |
236 | 237 | ||
- | 238 | int udebug_stop(thread_t *t, call_t *call) |
|
- | 239 | { |
|
- | 240 | ipl_t ipl; |
|
- | 241 | int rc; |
|
- | 242 | ||
- | 243 | klog_printf("udebug_stop()"); |
|
- | 244 | ||
- | 245 | ipl = interrupts_disable(); |
|
- | 246 | ||
- | 247 | /* |
|
- | 248 | * On success, this will lock t->debug_lock. Note that this makes sure |
|
- | 249 | * the thread is not stopped. |
|
- | 250 | */ |
|
- | 251 | rc = _thread_op_begin(t, true); |
|
- | 252 | if (rc != EOK) { |
|
- | 253 | interrupts_restore(ipl); |
|
- | 254 | return rc; |
|
- | 255 | } |
|
- | 256 | ||
- | 257 | /* Take GO away from the thread */ |
|
- | 258 | t->debug_stop = true; |
|
- | 259 | ||
- | 260 | if (!t->debug_stoppable) { |
|
- | 261 | /* Answer will be sent when the thread becomes stoppable */ |
|
- | 262 | _thread_op_end(t); |
|
- | 263 | interrupts_restore(ipl); |
|
- | 264 | return 0; |
|
- | 265 | } |
|
- | 266 | ||
- | 267 | /* |
|
- | 268 | * Answer GO call |
|
- | 269 | */ |
|
- | 270 | klog_printf("udebug_stop - answering go call"); |
|
- | 271 | ||
- | 272 | /* Make sure nobody takes this call away from us */ |
|
- | 273 | call = t->debug_go_call; |
|
- | 274 | t->debug_go_call = NULL; |
|
- | 275 | ||
- | 276 | IPC_SET_RETVAL(call->data, 0); |
|
- | 277 | IPC_SET_ARG1(call->data, UDEBUG_EVENT_STOP); |
|
- | 278 | klog_printf("udebug_stop/ipc_answer"); |
|
- | 279 | ||
- | 280 | THREAD->cur_event = UDEBUG_EVENT_STOP; |
|
- | 281 | _thread_op_end(t); |
|
- | 282 | ||
- | 283 | spinlock_lock(&TASK->lock); |
|
- | 284 | ipc_answer(&TASK->answerbox, call); |
|
- | 285 | spinlock_unlock(&TASK->lock); |
|
- | 286 | ||
- | 287 | interrupts_restore(ipl); |
|
- | 288 | klog_printf("udebog_stop/done"); |
|
- | 289 | return 0; |
|
- | 290 | } |
|
237 | 291 | ||
238 | int udebug_thread_read(void **buffer, size_t buf_size, size_t *n) |
292 | int udebug_thread_read(void **buffer, size_t buf_size, size_t *n) |
239 | { |
293 | { |
240 | thread_t *t; |
294 | thread_t *t; |
241 | link_t *cur; |
295 | link_t *cur; |
Line 308... | Line 362... | ||
308 | if (!arg_buffer) return ENOMEM; |
362 | if (!arg_buffer) return ENOMEM; |
309 | 363 | ||
310 | ipl = interrupts_disable(); |
364 | ipl = interrupts_disable(); |
311 | 365 | ||
312 | /* On success, this will lock t->debug_lock */ |
366 | /* On success, this will lock t->debug_lock */ |
313 | rc = _thread_op_begin(t); |
367 | rc = _thread_op_begin(t, false); |
314 | if (rc != EOK) { |
368 | if (rc != EOK) { |
315 | interrupts_restore(ipl); |
369 | interrupts_restore(ipl); |
316 | return rc; |
370 | return rc; |
317 | } |
371 | } |
318 | 372 | ||
Line 348... | Line 402... | ||
348 | if (!regs_buffer) return ENOMEM; |
402 | if (!regs_buffer) return ENOMEM; |
349 | 403 | ||
350 | ipl = interrupts_disable(); |
404 | ipl = interrupts_disable(); |
351 | 405 | ||
352 | /* On success, this will lock t->debug_lock */ |
406 | /* On success, this will lock t->debug_lock */ |
353 | rc = _thread_op_begin(t); |
407 | rc = _thread_op_begin(t, false); |
354 | if (rc != EOK) { |
408 | if (rc != EOK) { |
355 | interrupts_restore(ipl); |
409 | interrupts_restore(ipl); |
356 | return rc; |
410 | return rc; |
357 | } |
411 | } |
358 | 412 | ||
Line 387... | Line 441... | ||
387 | /* Try to change the thread's uspace_state */ |
441 | /* Try to change the thread's uspace_state */ |
388 | 442 | ||
389 | ipl = interrupts_disable(); |
443 | ipl = interrupts_disable(); |
390 | 444 | ||
391 | /* On success, this will lock t->debug_lock */ |
445 | /* On success, this will lock t->debug_lock */ |
392 | rc = _thread_op_begin(t); |
446 | rc = _thread_op_begin(t, false); |
393 | if (rc != EOK) { |
447 | if (rc != EOK) { |
394 | interrupts_restore(ipl); |
448 | interrupts_restore(ipl); |
395 | return rc; |
449 | return rc; |
396 | } |
450 | } |
397 | 451 |