Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2869 → Rev 2870

/branches/tracing/kernel/generic/include/proc/task.h
99,6 → 99,7
udebug_task_state_t dt_state;
call_t *debug_begin_call;
int not_stoppable_count;
struct task *debugger;
 
/** Kernel answerbox */
answerbox_t kernel_box;
/branches/tracing/kernel/generic/include/udebug/udebug.h
137,6 → 137,9
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);
144,6 → 147,8
void udebug_stoppable_begin(void);
void udebug_stoppable_end(void);
 
int udebug_task_cleanup(struct task *ta);
 
#endif
 
#endif
/branches/tracing/kernel/generic/src/ipc/ipc.c
635,6 → 635,21
 
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/src/udebug/udebug_ipc.c
189,6 → 189,7
 
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;
222,76 → 223,24
{
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);
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);
klog_printf("udebug_rp_begin(): task not being debugged");
return EINVAL;
}
rc = udebug_task_cleanup(ta);
 
/* 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);
klog_printf("task %llu", ta->taskid);
 
spinlock_lock(&t->debug_lock);
spinlock_lock(&t->lock);
spinlock_unlock(&ta->lock);
interrupts_restore(ipl);
 
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);
if (rc < 0) {
return EINVAL;
}
 
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/udebug/udebug.c
10,6 → 10,7
#include <synch/waitq.h>
#include <console/klog.h>
#include <udebug/udebug.h>
#include <errno.h>
#include <arch.h>
 
void udebug_stoppable_begin(void)
169,6 → 170,79
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;
}
 
 
/** @}
*/