Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3017 → Rev 3018

/branches/tracing/kernel/generic/src/udebug/udebug.c
50,6 → 50,17
ut->evmask = 0;
}
 
void udebug_thread_initialize(udebug_thread_t *ut)
{
waitq_initialize(&ut->go_wq);
ut->go_call = NULL;
ut->uspace_state = NULL;
ut->stop = true;
ut->stoppable = true;
ut->debug_active = false;
ut->cur_event = 0; /* none */
}
 
static void udebug_wait_for_go(waitq_t *wq)
{
int rc;
90,11 → 101,11
db_call = TASK->udebug.begin_call;
ASSERT(db_call);
 
/* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */
/* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */
ipl = interrupts_disable();
spinlock_lock(&THREAD->debug_lock);
THREAD->debug_stoppable = true;
spinlock_unlock(&THREAD->debug_lock);
spinlock_lock(&THREAD->udebug.lock);
THREAD->udebug.stoppable = true;
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
 
TASK->udebug.dt_state = UDEBUG_TS_ACTIVE;
110,26 → 121,26
* Active debugging session
*/
 
/* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */
/* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */
ipl = interrupts_disable();
spinlock_lock(&THREAD->debug_lock);
THREAD->debug_stoppable = true;
spinlock_lock(&THREAD->udebug.lock);
THREAD->udebug.stoppable = true;
 
if (THREAD->debug_active && THREAD->debug_stop) {
if (THREAD->udebug.debug_active && THREAD->udebug.stop) {
/*
* Thread was requested to stop - answer go call
*/
 
/* Make sure nobody takes this call away from us */
go_call = THREAD->debug_go_call;
THREAD->debug_go_call = NULL;
go_call = THREAD->udebug.go_call;
THREAD->udebug.go_call = NULL;
ASSERT(go_call);
 
IPC_SET_RETVAL(go_call->data, 0);
IPC_SET_ARG1(go_call->data, UDEBUG_EVENT_STOP);
 
THREAD->cur_event = UDEBUG_EVENT_STOP;
spinlock_unlock(&THREAD->debug_lock);
THREAD->udebug.cur_event = UDEBUG_EVENT_STOP;
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
 
ipc_answer(&TASK->answerbox, go_call);
139,7 → 150,7
/*
* No stop request - nothing happens.
*/
spinlock_unlock(&THREAD->debug_lock);
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
mutex_unlock(&TASK->udebug.lock);
}
148,11 → 159,11
* All other cases - nothing special happens.
*/
 
/* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */
/* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */
ipl = interrupts_disable();
spinlock_lock(&THREAD->debug_lock);
THREAD->debug_stoppable = true;
spinlock_unlock(&THREAD->debug_lock);
spinlock_lock(&THREAD->udebug.lock);
THREAD->udebug.stoppable = true;
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
 
mutex_unlock(&TASK->udebug.lock);
166,31 → 177,31
restart:
mutex_lock(&TASK->udebug.lock);
 
/* Lock order OK, THREAD->debug_lock is after TASK->udebug.lock */
/* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */
ipl = interrupts_disable();
spinlock_lock(&THREAD->debug_lock);
spinlock_lock(&THREAD->udebug.lock);
 
if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) {
//klog_printf("udebug_stoppable_end");
//klog_printf("debug_stop=%d", THREAD->debug_stop);
//klog_printf("udebug.stop=%d", THREAD->udebug.stop);
}
 
if (THREAD->debug_active &&
THREAD->debug_stop == true) {
if (THREAD->udebug.debug_active &&
THREAD->udebug.stop == true) {
TASK->udebug.begin_call = NULL;
spinlock_unlock(&THREAD->debug_lock);
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
mutex_unlock(&TASK->udebug.lock);
 
udebug_wait_for_go(&THREAD->go_wq);
udebug_wait_for_go(&THREAD->udebug.go_wq);
 
goto restart;
/* must try again - have to lose stoppability atomically */
} else {
++TASK->udebug.not_stoppable_count;
THREAD->debug_stoppable = false;
THREAD->udebug.stoppable = false;
 
spinlock_unlock(&THREAD->debug_lock);
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
mutex_unlock(&TASK->udebug.lock);
}
208,10 → 219,10
ipl_t ipl;
 
/* This will happen if we get preempted inside this function. */
if (THREAD->debug_in_before_thread_runs)
if (THREAD->udebug.in_before_thread_runs)
return;
 
THREAD->debug_in_before_thread_runs = true;
THREAD->udebug.in_before_thread_runs = true;
ipl = interrupts_enable();
 
/* Now we're free to do whatever we need (lock mutexes, sleep, etc.) */
221,7 → 232,7
udebug_stoppable_end();
 
interrupts_restore(ipl);
THREAD->debug_in_before_thread_runs = false;
THREAD->udebug.in_before_thread_runs = false;
}
 
void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3,
237,13 → 248,13
mutex_lock(&TASK->udebug.lock);
 
ipl = interrupts_disable();
spinlock_lock(&THREAD->debug_lock);
spinlock_lock(&THREAD->udebug.lock);
 
/* Must only generate events when in debugging session and have go */
if (THREAD->debug_active != true ||
THREAD->debug_stop == true ||
if (THREAD->udebug.debug_active != true ||
THREAD->udebug.stop == true ||
(TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) {
spinlock_unlock(&THREAD->debug_lock);
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
mutex_unlock(&TASK->udebug.lock);
return;
250,8 → 261,8
}
 
//klog_printf("udebug_syscall_event");
call = THREAD->debug_go_call;
THREAD->debug_go_call = NULL;
call = THREAD->udebug.go_call;
THREAD->udebug.go_call = NULL;
 
IPC_SET_RETVAL(call->data, 0);
IPC_SET_ARG1(call->data, etype);
259,22 → 270,22
IPC_SET_ARG3(call->data, rc);
//klog_printf("udebug_syscall_event/ipc_answer");
 
THREAD->syscall_args[0] = a1;
THREAD->syscall_args[1] = a2;
THREAD->syscall_args[2] = a3;
THREAD->syscall_args[3] = a4;
THREAD->syscall_args[4] = a5;
THREAD->syscall_args[5] = a6;
THREAD->udebug.syscall_args[0] = a1;
THREAD->udebug.syscall_args[1] = a2;
THREAD->udebug.syscall_args[2] = a3;
THREAD->udebug.syscall_args[3] = a4;
THREAD->udebug.syscall_args[4] = a5;
THREAD->udebug.syscall_args[5] = a6;
 
/*
* Make sure debug_stop is true when going to sleep
* Make sure udebug.stop is true when going to sleep
* in case we get woken up by DEBUG_END. (At which
* point it must be back to the initial true value).
*/
THREAD->debug_stop = true;
THREAD->udebug.stop = true;
 
THREAD->cur_event = etype;
spinlock_unlock(&THREAD->debug_lock);
THREAD->udebug.cur_event = etype;
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
 
ipc_answer(&TASK->answerbox, call);
281,7 → 292,7
 
mutex_unlock(&TASK->udebug.lock);
 
udebug_wait_for_go(&THREAD->go_wq);
udebug_wait_for_go(&THREAD->udebug.go_wq);
}
 
void udebug_thread_b_event(struct thread *t)
292,17 → 303,17
mutex_lock(&TASK->udebug.lock);
 
ipl = interrupts_disable();
spinlock_lock(&THREAD->debug_lock);
spinlock_lock(&THREAD->udebug.lock);
 
klog_printf("udebug_thread_b_event");
klog_printf("- check state");
 
/* Must only generate events when in debugging session */
if (THREAD->debug_active != true) {
klog_printf("- debug_active: %s, debug_stop: %s",
THREAD->debug_active ? "yes(+)" : "no(-)",
THREAD->debug_stop ? "yes(-)" : "no(+)");
spinlock_unlock(&THREAD->debug_lock);
if (THREAD->udebug.debug_active != true) {
klog_printf("- debug_active: %s, udebug.stop: %s",
THREAD->udebug.debug_active ? "yes(+)" : "no(-)",
THREAD->udebug.stop ? "yes(-)" : "no(+)");
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
mutex_unlock(&TASK->udebug.lock);
return;
310,21 → 321,21
 
klog_printf("- trigger event");
 
call = THREAD->debug_go_call;
THREAD->debug_go_call = NULL;
call = THREAD->udebug.go_call;
THREAD->udebug.go_call = NULL;
IPC_SET_RETVAL(call->data, 0);
IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B);
IPC_SET_ARG2(call->data, (unative_t)t);
 
/*
* Make sure debug_stop is true when going to sleep
* Make sure udebug.stop is true when going to sleep
* in case we get woken up by DEBUG_END. (At which
* point it must be back to the initial true value).
*/
THREAD->debug_stop = true;
THREAD->udebug.stop = true;
 
THREAD->cur_event = UDEBUG_EVENT_THREAD_B;
spinlock_unlock(&THREAD->debug_lock);
THREAD->udebug.cur_event = UDEBUG_EVENT_THREAD_B;
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
 
ipc_answer(&TASK->answerbox, call);
332,7 → 343,7
mutex_unlock(&TASK->udebug.lock);
 
klog_printf("- sleep");
udebug_wait_for_go(&THREAD->go_wq);
udebug_wait_for_go(&THREAD->udebug.go_wq);
}
 
void udebug_thread_e_event(void)
343,17 → 354,17
mutex_lock(&TASK->udebug.lock);
 
ipl = interrupts_disable();
spinlock_lock(&THREAD->debug_lock);
spinlock_lock(&THREAD->udebug.lock);
 
klog_printf("udebug_thread_e_event");
klog_printf("- check state");
 
/* Must only generate events when in debugging session */
if (THREAD->debug_active != true) {
klog_printf("- debug_active: %s, debug_stop: %s",
THREAD->debug_active ? "yes(+)" : "no(-)",
THREAD->debug_stop ? "yes(-)" : "no(+)");
spinlock_unlock(&THREAD->debug_lock);
if (THREAD->udebug.debug_active != true) {
klog_printf("- debug_active: %s, udebug.stop: %s",
THREAD->udebug.debug_active ? "yes(+)" : "no(-)",
THREAD->udebug.stop ? "yes(-)" : "no(+)");
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
mutex_unlock(&TASK->udebug.lock);
return;
361,17 → 372,17
 
klog_printf("- trigger event");
 
call = THREAD->debug_go_call;
THREAD->debug_go_call = NULL;
call = THREAD->udebug.go_call;
THREAD->udebug.go_call = NULL;
IPC_SET_RETVAL(call->data, 0);
IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E);
 
/* Prevent any further debug activity in thread */
THREAD->debug_active = false;
THREAD->cur_event = 0; /* none */
THREAD->debug_stop = true; /* set to initial value */
THREAD->udebug.debug_active = false;
THREAD->udebug.cur_event = 0; /* none */
THREAD->udebug.stop = true; /* set to initial value */
 
spinlock_unlock(&THREAD->debug_lock);
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
 
ipc_answer(&TASK->answerbox, call);
389,13 → 400,13
mutex_lock(&TASK->udebug.lock);
 
ipl = interrupts_disable();
spinlock_lock(&THREAD->debug_lock);
spinlock_lock(&THREAD->udebug.lock);
 
/* Must only generate events when in debugging session and have go */
if (THREAD->debug_active != true ||
THREAD->debug_stop == true ||
if (THREAD->udebug.debug_active != true ||
THREAD->udebug.stop == true ||
(TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) {
spinlock_unlock(&THREAD->debug_lock);
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
mutex_unlock(&TASK->udebug.lock);
return;
402,8 → 413,8
}
 
klog_printf("udebug_breakpoint/trap_event");
call = THREAD->debug_go_call;
THREAD->debug_go_call = NULL;
call = THREAD->udebug.go_call;
THREAD->udebug.go_call = NULL;
 
IPC_SET_RETVAL(call->data, 0);
IPC_SET_ARG1(call->data, etype);
410,14 → 421,14
IPC_SET_ARG2(call->data, addr);
 
/*
* Make sure debug_stop is true when going to sleep
* Make sure udebug.stop is true when going to sleep
* in case we get woken up by DEBUG_END. (At which
* point it must be back to the initial true value).
*/
THREAD->debug_stop = true;
THREAD->udebug.stop = true;
 
THREAD->cur_event = etype;
spinlock_unlock(&THREAD->debug_lock);
THREAD->udebug.cur_event = etype;
spinlock_unlock(&THREAD->udebug.lock);
interrupts_restore(ipl);
klog_printf("- send answer");
 
424,7 → 435,7
ipc_answer(&TASK->answerbox, call);
mutex_unlock(&TASK->udebug.lock);
 
udebug_wait_for_go(&THREAD->go_wq);
udebug_wait_for_go(&THREAD->udebug.go_wq);
}
 
void udebug_breakpoint_event(uintptr_t addr)
464,7 → 475,7
t = list_get_instance(cur, thread_t, th_link);
 
ipl = interrupts_disable();
spinlock_lock(&t->debug_lock);
spinlock_lock(&t->udebug.lock);
spinlock_lock(&t->lock);
 
flags = t->flags;
474,24 → 485,24
/* 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 */
t->udebug.debug_active = false;
t->udebug.cur_event = 0; /* none */
 
/* Still has go? */
if (t->debug_stop == false) {
if (t->udebug.stop == false) {
/*
* Yes, so clear go. As debug_active == false,
* this doesn't affect anything.
*/
t->debug_stop = true;
t->udebug.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_SET_RETVAL(t->udebug.go_call->data, 0);
IPC_SET_ARG1(t->udebug.go_call->data, UDEBUG_EVENT_FINISHED);
/* FIXME: must not call with interrupts disabled!!*/
ipc_answer(&ta->answerbox, t->debug_go_call);
t->debug_go_call = NULL;
ipc_answer(&ta->answerbox, t->udebug.go_call);
t->udebug.go_call = NULL;
} else {
/*
* Debug_stop is already at initial value.
502,10 → 513,10
* t's lock must not be held when calling
* waitq_wakeup.
*/
waitq_wakeup(&t->go_wq, WAKEUP_FIRST);
waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST);
}
}
spinlock_unlock(&t->debug_lock);
spinlock_unlock(&t->udebug.lock);
interrupts_restore(ipl);
}