/branches/tracing/kernel/generic/include/proc/task.h |
---|
99,6 → 99,7 |
bool stop_request; |
call_t *debug_begin_call; |
call_t *debug_go_call; |
int not_stoppable_count; |
/** Architecture specific task data. */ |
task_arch_t arch; |
/branches/tracing/kernel/generic/include/udebug.h |
---|
8,7 → 8,8 |
#define KERN_UDEBUG_H_ |
void udebug_syscall_event(void); |
void udebug_stopping_point(void); |
void udebug_stoppable_begin(void); |
void udebug_stoppable_end(void); |
#endif |
/branches/tracing/kernel/generic/src/proc/task.c |
---|
175,6 → 175,7 |
ta->stop_request = false; |
ta->debug_begin_call = NULL; |
ta->debug_go_call = NULL; |
ta->not_stoppable_count = 0; |
ipc_answerbox_init(&ta->answerbox, ta); |
for (i = 0; i < IPC_MAX_PHONES; i++) |
/branches/tracing/kernel/generic/src/proc/thread.c |
---|
412,6 → 412,7 |
spinlock_lock(&task->lock); |
atomic_inc(&task->refcount); |
atomic_inc(&task->lifecount); |
++task->not_stoppable_count; |
list_append(&t->th_link, &task->th_head); |
spinlock_unlock(&task->lock); |
/branches/tracing/kernel/generic/src/syscall/syscall.c |
---|
98,9 → 98,10 |
{ |
unative_t rc; |
if (id < SYSCALL_END) |
if (id < SYSCALL_END) { |
udebug_stoppable_begin(); |
rc = syscall_table[id](a1, a2, a3, a4, a5, a6); |
else { |
} else { |
klog_printf("TASK %llu: Unknown syscall id %llx", TASK->taskid, |
id); |
task_kill(TASK->taskid); |
111,7 → 112,7 |
thread_exit(); |
udebug_syscall_event(); |
udebug_stopping_point(); |
udebug_stoppable_end(); |
return rc; |
} |
/branches/tracing/kernel/generic/src/ipc/sysipc.c |
---|
307,7 → 307,7 |
#include <console/klog.h> |
static void debug_begin(call_t *call, phone_t *phone) |
static int debug_begin(call_t *call, phone_t *phone) |
{ |
task_t *ta; |
314,22 → 314,30 |
klog_printf("debug_begin()"); |
ta = get_lock_callee_task(phone); |
klog_printf("debugging task %llu\n", ta->taskid); |
klog_printf("debugging task %llu", ta->taskid); |
if (ta->being_debugged != false) { |
IPC_SET_RETVAL(call->data, EBUSY); |
ipc_answer(&ta->answerbox, call); |
spinlock_unlock(&ta->lock); |
return; |
klog_printf("debug_begin(): busy error"); |
return EBUSY; |
} |
ta->being_debugged = true; |
ta->stop_request = true; |
ta->debug_begin_call = call; |
if (ta->not_stoppable_count == 0) { |
ta->debug_begin_call = NULL; |
ta->stop_request = false; |
spinlock_unlock(&ta->lock); |
klog_printf("debug_begin(): immediate backsend"); |
return 1; /* actually we need backsend with 0 retval */ |
} |
klog_printf("debug_begin() done"); |
spinlock_unlock(&ta->lock); |
klog_printf("debug_begin() done (wait for stoppability)"); |
return 0; |
} |
static void debug_go(call_t *call, phone_t *phone) |
341,13 → 349,15 |
klog_printf("debug_go()"); |
ta = get_lock_callee_task(phone); |
ta->debug_go_call = call; |
l = ta->th_head.next; |
if (l != &TASK->th_head) { |
t = list_get_instance(l, thread_t, th_link); |
klog_printf("debug_go(): waitq_wakeup"); |
waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
} |
ta->debug_go_call = call; |
spinlock_unlock(&ta->lock); |
} |
402,7 → 412,9 |
} |
break; |
case IPC_M_DEBUG_BEGIN: |
debug_begin(call, phone); |
/* actually need possibility of backsend with 0 result code */ |
rc = debug_begin(call, phone); |
if (rc != 0) return rc; |
break; |
case IPC_M_DEBUG_GO: |
debug_go(call, phone); |
/branches/tracing/kernel/generic/src/udebug/udebug.c |
---|
12,26 → 12,66 |
#include <udebug.h> |
#include <arch.h> |
void udebug_stopping_point(void) |
void udebug_stoppable_begin(void) |
{ |
if (TASK->stop_request) { /* locking! */ |
klog_printf("udebug_stopping_point"); |
IPC_SET_RETVAL(TASK->debug_begin_call->data, 0); |
ipc_answer(&TASK->answerbox, TASK->debug_begin_call); |
int nsc; |
call_t *db_call; |
spinlock_lock(&TASK->lock); |
nsc = --TASK->not_stoppable_count; |
db_call = TASK->debug_begin_call; |
if (TASK->stop_request == true) { |
klog_printf("udebug_stoppable_begin"); |
klog_printf(" - nsc := %d", nsc); |
} |
if (TASK->stop_request == true && nsc == 0) { |
TASK->stop_request = false; |
TASK->debug_begin_call = NULL; |
spinlock_unlock(&TASK->lock); |
IPC_SET_RETVAL(db_call->data, 0); |
klog_printf("udebug_stoppable_begin/ipc_answer"); |
ipc_answer(&TASK->answerbox, db_call); |
} else { |
spinlock_unlock(&TASK->lock); |
} |
} |
void udebug_stoppable_end(void) |
{ |
restart: |
spinlock_lock(&TASK->lock); |
if (TASK->stop_request) { |
TASK->debug_begin_call = NULL; |
spinlock_unlock(&TASK->lock); |
klog_printf("udebug_stoppable_end: waitq_sleep"); |
waitq_sleep(&THREAD->go_wq); |
goto restart; |
/* must try again - have to lose stoppability atomically */ |
} else { |
++TASK->not_stoppable_count; |
spinlock_unlock(&TASK->lock); |
} |
} |
void udebug_syscall_event(void) |
{ |
spinlock_lock(&TASK->lock); |
/* being debugged + have go */ |
if (TASK->being_debugged && !TASK->stop_request) { /* locking! */ |
klog_printf("udebug_syscall_event"); |
IPC_SET_RETVAL(TASK->debug_go_call->data, 0); |
klog_printf("udebug_syscall_event/ipc_answer"); |
ipc_answer(&TASK->answerbox, TASK->debug_go_call); |
spinlock_unlock(&TASK->lock); |
waitq_sleep(&THREAD->go_wq); |
} else { |
spinlock_unlock(&TASK->lock); |
} |
} |