52,9 → 52,10 |
* but only if it verifies all conditions. |
* |
* Specifically, verifies that thread t exists, is a userspace thread, |
* and belongs to the current task (TASK). It also locks t->debug_lock, |
* making sure that t->debug_active is true - that the thread is |
* in a valid debugging session. |
* and belongs to the current task (TASK). Verifies, that the thread |
* has (or hasn't) go according to having_go (typically false). |
* It also locks t->debug_lock, making sure that t->debug_active is true |
* - that the thread is in a valid debugging session. |
* |
* Returns EOK if all went well, or an error code otherwise. |
* Interrupts must be already disabled when calling this function. |
61,7 → 62,7 |
* |
* Note: This function sports complicated locking. |
*/ |
static int _thread_op_begin(thread_t *t) |
static int _thread_op_begin(thread_t *t, bool having_go) |
{ |
int rc; |
task_id_t taskid; |
93,9 → 94,9 |
goto error_exit; |
} |
|
if ((t->debug_active != true) || (t->debug_stop != true)) { |
/* Not in debugging session or already has GO */ |
rc = ENOENT; |
if ((t->debug_active != true) || (!t->debug_stop != having_go)) { |
/* Not in debugging session or undesired GO state */ |
rc = EINVAL; |
goto error_exit; |
} |
|
213,7 → 214,7 |
ipl = interrupts_disable(); |
|
/* On success, this will lock t->debug_lock */ |
rc = _thread_op_begin(t); |
rc = _thread_op_begin(t, false); |
if (rc != EOK) { |
interrupts_restore(ipl); |
return rc; |
234,7 → 235,60 |
return 0; |
} |
|
int udebug_stop(thread_t *t, call_t *call) |
{ |
ipl_t ipl; |
int rc; |
|
klog_printf("udebug_stop()"); |
|
ipl = interrupts_disable(); |
|
/* |
* On success, this will lock t->debug_lock. Note that this makes sure |
* the thread is not stopped. |
*/ |
rc = _thread_op_begin(t, true); |
if (rc != EOK) { |
interrupts_restore(ipl); |
return rc; |
} |
|
/* Take GO away from the thread */ |
t->debug_stop = true; |
|
if (!t->debug_stoppable) { |
/* Answer will be sent when the thread becomes stoppable */ |
_thread_op_end(t); |
interrupts_restore(ipl); |
return 0; |
} |
|
/* |
* Answer GO call |
*/ |
klog_printf("udebug_stop - answering go call"); |
|
/* Make sure nobody takes this call away from us */ |
call = t->debug_go_call; |
t->debug_go_call = NULL; |
|
IPC_SET_RETVAL(call->data, 0); |
IPC_SET_ARG1(call->data, UDEBUG_EVENT_STOP); |
klog_printf("udebug_stop/ipc_answer"); |
|
THREAD->cur_event = UDEBUG_EVENT_STOP; |
_thread_op_end(t); |
|
spinlock_lock(&TASK->lock); |
ipc_answer(&TASK->answerbox, call); |
spinlock_unlock(&TASK->lock); |
|
interrupts_restore(ipl); |
klog_printf("udebog_stop/done"); |
return 0; |
} |
|
int udebug_thread_read(void **buffer, size_t buf_size, size_t *n) |
{ |
thread_t *t; |
310,7 → 364,7 |
ipl = interrupts_disable(); |
|
/* On success, this will lock t->debug_lock */ |
rc = _thread_op_begin(t); |
rc = _thread_op_begin(t, false); |
if (rc != EOK) { |
interrupts_restore(ipl); |
return rc; |
350,7 → 404,7 |
ipl = interrupts_disable(); |
|
/* On success, this will lock t->debug_lock */ |
rc = _thread_op_begin(t); |
rc = _thread_op_begin(t, false); |
if (rc != EOK) { |
interrupts_restore(ipl); |
return rc; |
389,7 → 443,7 |
ipl = interrupts_disable(); |
|
/* On success, this will lock t->debug_lock */ |
rc = _thread_op_begin(t); |
rc = _thread_op_begin(t, false); |
if (rc != EOK) { |
interrupts_restore(ipl); |
return rc; |