69,7 → 69,11 |
{ |
task_t *ta; |
ipl_t ipl; |
int rc; |
|
thread_t *t; |
link_t *cur; |
|
klog_printf("debug_begin()"); |
|
ipl = interrupts_disable(); |
89,17 → 93,29 |
if (ta->not_stoppable_count == 0) { |
ta->dt_state = UDEBUG_TS_ACTIVE; |
ta->debug_begin_call = NULL; |
spinlock_unlock(&ta->lock); |
interrupts_restore(ipl); |
klog_printf("debug_begin(): immediate backsend"); |
return 1; /* actually we need backsend with 0 retval */ |
rc = 1; /* actually we need backsend with 0 retval */ |
} else { |
rc = 0; /* no backsend */ |
} |
|
/* Set debug_active on all of the task's userspace threads */ |
|
for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
t = list_get_instance(cur, thread_t, th_link); |
|
spinlock_lock(&t->lock); |
if ((t->flags & THREAD_FLAG_USPACE) != 0) |
t->debug_active = true; |
spinlock_unlock(&t->lock); |
} |
|
spinlock_unlock(&ta->lock); |
interrupts_restore(ipl); |
|
klog_printf("debug_begin() done (wait for stoppability)"); |
return 0; |
klog_printf("debug_begin() done (%s)", |
rc ? "backsend" : "stoppability wait"); |
|
return rc; |
} |
|
static int udebug_rp_go(call_t *call, phone_t *phone) |
125,6 → 141,13 |
return ENOENT; |
} |
|
if ((t->debug_active != true) || (t->debug_stop != true)) { |
/* Not in debugging session or already has GO */ |
spinlock_unlock(&threads_lock); |
interrupts_restore(ipl); |
return EBUSY; |
} |
|
t->debug_go_call = call; |
t->debug_stop = false; |
waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
143,9 → 166,9 |
unative_t to_copy; |
int rc; |
ipl_t ipl; |
unative_t buffer[6]; |
|
klog_printf("debug_args_read()"); |
// FIXME: verify task/thread state |
|
ta = get_lock_callee_task(phone); |
klog_printf("task %llu", ta->taskid); |
156,21 → 179,34 |
ipl = interrupts_disable(); |
spinlock_lock(&threads_lock); |
|
if (!thread_exists(t)) { |
/* Verify that 't' exists and belongs to task 'ta' */ |
if (!thread_exists(t) || (t->task != ta)) { |
spinlock_unlock(&threads_lock); |
interrupts_restore(ipl); |
return ENOENT; |
} |
|
// FIXME: copy to a local buffer before releasing the lock |
//FIXME: additionally we need to verify that we are inside a syscall |
if ((t->debug_active != true) || (t->debug_stop != true)) { |
/* Not in debugging session or has GO */ |
spinlock_unlock(&threads_lock); |
interrupts_restore(ipl); |
return EBUSY; |
} |
|
/* Copy to a local buffer before releasing the lock */ |
memcpy(buffer, t->syscall_args, 6 * sizeof(unative_t)); |
|
spinlock_unlock(&threads_lock); |
interrupts_restore(ipl); |
|
/* Now copy to userspace */ |
|
uspace_buffer = (void *)IPC_GET_ARG3(call->data); |
to_copy = IPC_GET_ARG4(call->data); |
if (to_copy > 6 * sizeof(unative_t)) to_copy = 6 * sizeof(unative_t); |
|
rc = copy_to_uspace(uspace_buffer, t->syscall_args, to_copy); |
rc = copy_to_uspace(uspace_buffer, buffer, to_copy); |
if (rc != 0) { |
spinlock_unlock(&ta->lock); |
klog_printf("debug_args_read() - copy failed"); |
195,19 → 231,30 |
ipl_t ipl; |
|
klog_printf("debug_regs_read()"); |
// FIXME: verify task/thread state |
|
ta = get_lock_callee_task(phone); |
spinlock_unlock(&ta->lock); |
//FIXME: don't lock ta |
|
ipl = interrupts_disable(); |
spinlock_lock(&threads_lock); |
|
t = (thread_t *) IPC_GET_ARG2(call->data); |
if (!thread_exists(t)) { |
|
/* Verify that 't' exists and belongs to task 'ta' */ |
if (!thread_exists(t) || (t->task != ta)) { |
spinlock_unlock(&threads_lock); |
interrupts_restore(ipl); |
return ENOENT; |
} |
|
if ((t->debug_active != true) || (t->debug_stop != true)) { |
/* Not in debugging session or has GO */ |
spinlock_unlock(&threads_lock); |
interrupts_restore(ipl); |
return EBUSY; |
} |
|
state = t->uspace_state; |
if (state == NULL) { |
spinlock_unlock(&threads_lock); |
264,10 → 311,9 |
return rc; |
} |
|
// FIXME: verify task/thread state |
|
ta = get_lock_callee_task(phone); |
spinlock_unlock(&ta->lock); |
//FIXME: don't lock ta |
|
/* Now try to change the thread's uspace_state */ |
|
275,12 → 321,21 |
spinlock_lock(&threads_lock); |
|
t = (thread_t *) IPC_GET_ARG2(call->data); |
if (!thread_exists(t)) { |
|
/* Verify that 't' exists and belongs to task 'ta' */ |
if (!thread_exists(t) || (t->task != ta)) { |
spinlock_unlock(&threads_lock); |
interrupts_restore(ipl); |
return ENOENT; |
} |
|
if ((t->debug_active != true) || (t->debug_stop != true)) { |
/* Not in debugging session or has GO */ |
spinlock_unlock(&threads_lock); |
interrupts_restore(ipl); |
return EBUSY; |
} |
|
state = t->uspace_state; |
if (state == NULL) { |
spinlock_unlock(&threads_lock); |
320,11 → 375,17 |
int flags; |
|
klog_printf("debug_thread_read()"); |
// FIXME: verify task/thread state |
|
ipl = interrupts_disable(); |
ta = get_lock_callee_task(phone); |
|
/* Verify task state */ |
if (ta->dt_state != UDEBUG_TS_ACTIVE) { |
spinlock_unlock(&ta->lock); |
interrupts_restore(ipl); |
return EBUSY; |
} |
|
/* Count the threads first */ |
|
num_threads = 0; |
390,7 → 451,6 |
void *buffer; |
|
klog_printf("udebug_rp_mem_write()"); |
// FIXME: verify task/thread state |
|
uspace_data = (void *)IPC_GET_ARG2(call->data); |
to_copy = IPC_GET_ARG4(call->data); |
486,8 → 546,21 |
unsigned size; |
void *buffer; |
int rc; |
udebug_task_state_t dts; |
|
klog_printf("udebug_receive_mem_write()"); |
|
/* Verify task state */ |
spinlock_lock(&TASK->lock); |
dts = TASK->dt_state; |
spinlock_unlock(&TASK->lock); |
|
if (dts != UDEBUG_TS_ACTIVE) { |
IPC_SET_RETVAL(call->data, EBUSY); |
ipc_answer(&TASK->kernel_box, call); |
return; |
} |
|
uspace_dst = (void *)IPC_GET_ARG3(call->data); |
size = IPC_GET_ARG4(call->data); |
|
499,6 → 572,7 |
rc = copy_to_uspace(uspace_dst, buffer, size); |
if (rc) { |
IPC_SET_RETVAL(call->data, rc); |
ipc_answer(&TASK->kernel_box, call); |
return; |
} |
|