/branches/tracing/kernel/generic/src/udebug/udebug.c |
---|
10,7 → 10,6 |
#include <synch/waitq.h> |
#include <console/klog.h> |
#include <udebug/udebug.h> |
#include <errno.h> |
#include <arch.h> |
void udebug_stoppable_begin(void) |
170,79 → 169,6 |
waitq_sleep(&THREAD->go_wq); |
} |
/** |
* Terminate task debugging session. |
* |
* \param ta Must be already locked and interrupts must be disabled. |
* \return Zero on success or negative error code. |
*/ |
int udebug_task_cleanup(struct task *ta) |
{ |
thread_t *t; |
link_t *cur; |
int flags; |
klog_printf("udebug_task_cleanup()"); |
klog_printf("task %llu", ta->taskid); |
if (ta->dt_state == UDEBUG_TS_BEGINNING && |
ta->dt_state != UDEBUG_TS_ACTIVE) { |
klog_printf("udebug_task_cleanup(): task not being debugged"); |
return EINVAL; |
} |
/* Finish debugging of all 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->debug_lock); |
spinlock_lock(&t->lock); |
flags = t->flags; |
spinlock_unlock(&t->lock); |
/* Only process userspace threads */ |
if ((flags & THREAD_FLAG_USPACE) != 0) { |
/* Prevent any further debug activity in thread */ |
t->debug_active = false; |
t->cur_event = 0; /* none */ |
/* Still has go? */ |
if (t->debug_stop == false) { |
/* |
* Yes, so clear go. As debug_active == false, |
* this doesn't affect anything. |
*/ |
t->debug_stop = true; |
/* Answer GO call */ |
klog_printf("answer GO call with EVENT_FINISHED"); |
IPC_SET_RETVAL(t->debug_go_call->data, 0); |
IPC_SET_ARG1(t->debug_go_call->data, UDEBUG_EVENT_FINISHED); |
ipc_answer(&ta->answerbox, t->debug_go_call); |
} else { |
/* |
* Debug_stop is already at initial value. |
* Yet this means the thread needs waking up. |
*/ |
/* |
* t's lock must not be held when calling |
* waitq_wakeup. |
*/ |
waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
} |
} |
spinlock_unlock(&t->debug_lock); |
} |
ta->dt_state = UDEBUG_TS_INACTIVE; |
ta->debugger = NULL; |
return 0; |
} |
/** @} |
*/ |
/branches/tracing/kernel/generic/src/udebug/udebug_ipc.c |
---|
189,7 → 189,6 |
ta->dt_state = UDEBUG_TS_BEGINNING; |
ta->debug_begin_call = call; |
ta->debugger = call->sender; |
if (ta->not_stoppable_count == 0) { |
ta->dt_state = UDEBUG_TS_ACTIVE; |
223,24 → 222,76 |
{ |
task_t *ta; |
ipl_t ipl; |
int rc; |
thread_t *t; |
link_t *cur; |
int flags; |
klog_printf("udebug_rp_end()"); |
ipl = interrupts_disable(); |
ta = get_lock_callee_task(phone); |
rc = udebug_task_cleanup(ta); |
klog_printf("task %llu", ta->taskid); |
if (ta->dt_state == UDEBUG_TS_BEGINNING && |
ta->dt_state != UDEBUG_TS_ACTIVE) { |
spinlock_unlock(&ta->lock); |
interrupts_restore(ipl); |
if (rc < 0) { |
klog_printf("udebug_rp_begin(): task not being debugged"); |
return EINVAL; |
} |
/* Finish debugging of all 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->debug_lock); |
spinlock_lock(&t->lock); |
flags = t->flags; |
spinlock_unlock(&t->lock); |
/* Only process userspace threads */ |
if ((flags & THREAD_FLAG_USPACE) != 0) { |
/* Prevent any further debug activity in thread */ |
t->debug_active = false; |
t->cur_event = 0; /* none */ |
/* Still has go? */ |
if (t->debug_stop == false) { |
/* |
* Yes, so clear go. As debug_active == false, |
* this doesn't affect anything. |
*/ |
t->debug_stop = true; |
/* Answer GO call */ |
klog_printf("answer GO call with EVENT_FINISHED"); |
IPC_SET_RETVAL(t->debug_go_call->data, 0); |
IPC_SET_ARG1(t->debug_go_call->data, UDEBUG_EVENT_FINISHED); |
ipc_answer(&ta->answerbox, t->debug_go_call); |
} else { |
/* |
* Debug_stop is already at initial value. |
* Yet this means the thread needs waking up. |
*/ |
/* |
* t's lock must not be held when calling |
* waitq_wakeup. |
*/ |
waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
} |
} |
spinlock_unlock(&t->debug_lock); |
} |
ta->dt_state = UDEBUG_TS_INACTIVE; |
spinlock_unlock(&ta->lock); |
interrupts_restore(ipl); |
IPC_SET_RETVAL(call->data, 0); |
klog_printf("udebug_rp_end() done\n"); |
/branches/tracing/kernel/generic/src/ipc/ipc.c |
---|
635,21 → 635,6 |
if (method == IPC_M_PHONE_HUNGUP) { |
klog_printf("kbox: handle hangup message\n"); |
/* Was it our debugger, who hung up? */ |
if (call->sender == TASK->debugger) { |
/* Terminate debugging session (if any) */ |
klog_printf("kbox: terminate debug session\n"); |
ipl = interrupts_disable(); |
spinlock_lock(&TASK->lock); |
udebug_task_cleanup(TASK); |
spinlock_unlock(&TASK->lock); |
interrupts_restore(ipl); |
} else { |
klog_printf("kbox: was not debugger\n"); |
} |
klog_printf("kbox: continue with hangup message\n"); |
IPC_SET_RETVAL(call->data, 0); |
ipc_answer(&TASK->kernel_box, call); |
/branches/tracing/kernel/generic/include/udebug/udebug.h |
---|
137,9 → 137,6 |
UDEBUG_TS_SHUTDOWN |
} udebug_task_state_t; |
struct task; |
struct thread; |
void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3, |
unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc); |
void udebug_new_thread_event(struct thread *t); |
147,8 → 144,6 |
void udebug_stoppable_begin(void); |
void udebug_stoppable_end(void); |
int udebug_task_cleanup(struct task *ta); |
#endif |
#endif |
/branches/tracing/kernel/generic/include/proc/task.h |
---|
99,7 → 99,6 |
udebug_task_state_t dt_state; |
call_t *debug_begin_call; |
int not_stoppable_count; |
struct task *debugger; |
/** Kernel answerbox */ |
answerbox_t kernel_box; |