/branches/sparc/kernel/generic/include/udebug/udebug.h |
---|
176,7 → 176,7 |
*/ |
atomic_t int_lock; |
/** Synchronize debug ops on this thread / access to this structure */ |
/** Synchronize debug ops on this thread / access to this structure. */ |
mutex_t lock; |
waitq_t go_wq; |
183,11 → 183,11 |
call_t *go_call; |
unative_t syscall_args[6]; |
/** What type of event are we stopped in or 0 if none */ |
udebug_event_t cur_event; |
bool stop; |
bool stoppable; |
bool debug_active; /**< In a debugging session */ |
/** What type of event are we stopped in or 0 if none. */ |
udebug_event_t cur_event; |
bool go; /**< thread is GO */ |
bool stoppable; /**< thread is stoppable */ |
bool debug_active; /**< thread is in a debugging session */ |
} udebug_thread_t; |
struct task; |
/branches/sparc/kernel/generic/src/udebug/udebug.c |
---|
95,7 → 95,7 |
atomic_set(&ut->int_lock, 1); |
ut->go_call = NULL; |
ut->stop = true; |
ut->go = false; |
ut->stoppable = true; |
ut->debug_active = false; |
ut->cur_event = 0; /* none */ |
198,7 → 198,8 |
* Active debugging session |
*/ |
if (THREAD->udebug.debug_active && THREAD->udebug.stop) { |
if (THREAD->udebug.debug_active == true && |
THREAD->udebug.go == false) { |
/* |
* Thread was requested to stop - answer go call |
*/ |
239,7 → 240,7 |
mutex_lock(&THREAD->udebug.lock); |
if (THREAD->udebug.debug_active && |
THREAD->udebug.stop == true) { |
THREAD->udebug.go == false) { |
TASK->udebug.begin_call = NULL; |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
247,7 → 248,7 |
udebug_wait_for_go(&THREAD->udebug.go_wq); |
goto restart; |
/* must try again - have to lose stoppability atomically */ |
/* Must try again - have to lose stoppability atomically. */ |
} else { |
++TASK->udebug.not_stoppable_count; |
ASSERT(THREAD->udebug.stoppable == true); |
321,9 → 322,9 |
mutex_lock(&TASK->udebug.lock); |
mutex_lock(&THREAD->udebug.lock); |
/* Must only generate events when in debugging session and have go */ |
/* Must only generate events when in debugging session and is go. */ |
if (THREAD->udebug.debug_active != true || |
THREAD->udebug.stop == true || |
THREAD->udebug.go == false || |
(TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) { |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
348,11 → 349,11 |
THREAD->udebug.syscall_args[5] = a6; |
/* |
* Make sure udebug.stop is true when going to sleep |
* Make sure udebug.go is false 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->udebug.stop = true; |
THREAD->udebug.go = false; |
THREAD->udebug.cur_event = etype; |
ipc_answer(&TASK->answerbox, call); |
387,9 → 388,9 |
/* Must only generate events when in debugging session */ |
if (THREAD->udebug.debug_active != true) { |
LOG("- debug_active: %s, udebug.stop: %s\n", |
LOG("- debug_active: %s, udebug.go: %s\n", |
THREAD->udebug.debug_active ? "yes(+)" : "no(-)", |
THREAD->udebug.stop ? "yes(-)" : "no(+)"); |
THREAD->udebug.go ? "yes(-)" : "no(+)"); |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
return; |
404,11 → 405,11 |
IPC_SET_ARG2(call->data, (unative_t)t); |
/* |
* Make sure udebug.stop is true when going to sleep |
* Make sure udebug.go is false 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->udebug.stop = true; |
THREAD->udebug.go = false; |
THREAD->udebug.cur_event = UDEBUG_EVENT_THREAD_B; |
ipc_answer(&TASK->answerbox, call); |
439,11 → 440,11 |
LOG("udebug_thread_e_event\n"); |
LOG("- check state\n"); |
/* Must only generate events when in debugging session */ |
/* Must only generate events when in debugging session. */ |
if (THREAD->udebug.debug_active != true) { |
/* printf("- debug_active: %s, udebug.stop: %s\n", |
/* printf("- debug_active: %s, udebug.go: %s\n", |
THREAD->udebug.debug_active ? "yes(+)" : "no(-)", |
THREAD->udebug.stop ? "yes(-)" : "no(+)");*/ |
THREAD->udebug.go ? "yes(-)" : "no(+)");*/ |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
return; |
456,10 → 457,10 |
IPC_SET_RETVAL(call->data, 0); |
IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E); |
/* Prevent any further debug activity in thread */ |
/* Prevent any further debug activity in thread. */ |
THREAD->udebug.debug_active = false; |
THREAD->udebug.cur_event = 0; /* none */ |
THREAD->udebug.stop = true; /* set to initial value */ |
THREAD->udebug.go = false; /* set to initial value */ |
ipc_answer(&TASK->answerbox, call); |
466,8 → 467,8 |
mutex_unlock(&THREAD->udebug.lock); |
mutex_unlock(&TASK->udebug.lock); |
/* Leave int_lock enabled */ |
/* This event does not sleep - debugging has finished in this thread */ |
/* Leave int_lock enabled. */ |
/* This event does not sleep - debugging has finished in this thread. */ |
} |
/** |
512,19 → 513,19 |
spinlock_unlock(&t->lock); |
interrupts_restore(ipl); |
/* Only process userspace threads */ |
/* Only process userspace threads. */ |
if ((flags & THREAD_FLAG_USPACE) != 0) { |
/* Prevent any further debug activity in thread */ |
/* Prevent any further debug activity in thread. */ |
t->udebug.debug_active = false; |
t->udebug.cur_event = 0; /* none */ |
/* Still has go? */ |
if (t->udebug.stop == false) { |
/* Is the thread still go? */ |
if (t->udebug.go == true) { |
/* |
* Yes, so clear go. As debug_active == false, |
* this doesn't affect anything. |
*/ |
t->udebug.stop = true; |
t->udebug.go = false; |
/* Answer GO call */ |
LOG("answer GO call with EVENT_FINISHED\n"); |
/branches/sparc/kernel/generic/src/udebug/udebug_ops.c |
---|
57,7 → 57,7 |
* |
* Specifically, verifies that thread t exists, is a userspace thread, |
* and belongs to the current task (TASK). Verifies, that the thread |
* has (or hasn't) go according to having_go (typically false). |
* is (or is not) go according to being_go (typically false). |
* It also locks t->udebug.lock, making sure that t->udebug.debug_active |
* is true - that the thread is in a valid debugging session. |
* |
70,11 → 70,11 |
* the t->lock spinlock to the t->udebug.lock mutex. |
* |
* @param t Pointer, need not at all be valid. |
* @param having_go Required thread state. |
* @param being_go Required thread state. |
* |
* Returns EOK if all went well, or an error code otherwise. |
*/ |
static int _thread_op_begin(thread_t *t, bool having_go) |
static int _thread_op_begin(thread_t *t, bool being_go) |
{ |
task_id_t taskid; |
ipl_t ipl; |
98,7 → 98,7 |
spinlock_lock(&t->lock); |
spinlock_unlock(&threads_lock); |
/* Verify that 't' is a userspace thread */ |
/* Verify that 't' is a userspace thread. */ |
if ((t->flags & THREAD_FLAG_USPACE) == 0) { |
/* It's not, deny its existence */ |
spinlock_unlock(&t->lock); |
107,7 → 107,7 |
return ENOENT; |
} |
/* Verify debugging state */ |
/* Verify debugging state. */ |
if (t->udebug.debug_active != true) { |
/* Not in debugging session or undesired GO state */ |
spinlock_unlock(&t->lock); |
124,9 → 124,9 |
spinlock_unlock(&t->lock); |
interrupts_restore(ipl); |
/* Only mutex TASK->udebug.lock left */ |
/* Only mutex TASK->udebug.lock left. */ |
/* Now verify that the thread belongs to the current task */ |
/* Now verify that the thread belongs to the current task. */ |
if (t->task != TASK) { |
/* No such thread belonging this task*/ |
mutex_unlock(&TASK->udebug.lock); |
139,18 → 139,18 |
*/ |
mutex_lock(&t->udebug.lock); |
/* The big task mutex is no longer needed */ |
/* The big task mutex is no longer needed. */ |
mutex_unlock(&TASK->udebug.lock); |
if (!t->udebug.stop != having_go) { |
/* Not in debugging session or undesired GO state */ |
if (t->udebug.go != being_go) { |
/* Not in debugging session or undesired GO state. */ |
mutex_unlock(&t->udebug.lock); |
return EINVAL; |
} |
/* Only t->udebug.lock left */ |
/* Only t->udebug.lock left. */ |
return EOK; /* All went well */ |
return EOK; /* All went well. */ |
} |
/** End debugging operation on a thread. */ |
204,7 → 204,7 |
reply = 0; /* no reply */ |
} |
/* Set udebug.debug_active on all of the task's userspace threads */ |
/* Set udebug.debug_active on all of the task's userspace threads. */ |
for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) { |
t = list_get_instance(cur, thread_t, th_link); |
273,7 → 273,7 |
/** Give thread GO. |
* |
* Upon recieving a go message, the thread is given GO. Having GO |
* Upon recieving a go message, the thread is given GO. Being GO |
* means the thread is allowed to execute userspace code (until |
* a debugging event or STOP occurs, at which point the thread loses GO. |
* |
284,7 → 284,7 |
{ |
int rc; |
/* On success, this will lock t->udebug.lock */ |
/* On success, this will lock t->udebug.lock. */ |
rc = _thread_op_begin(t, false); |
if (rc != EOK) { |
return rc; |
291,11 → 291,11 |
} |
t->udebug.go_call = call; |
t->udebug.stop = false; |
t->udebug.go = true; |
t->udebug.cur_event = 0; /* none */ |
/* |
* Neither t's lock nor threads_lock may be held during wakeup |
* Neither t's lock nor threads_lock may be held during wakeup. |
*/ |
waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST); |
328,21 → 328,21 |
return rc; |
} |
/* Take GO away from the thread */ |
t->udebug.stop = true; |
/* Take GO away from the thread. */ |
t->udebug.go = false; |
if (!t->udebug.stoppable) { |
/* Answer will be sent when the thread becomes stoppable */ |
if (t->udebug.stoppable != true) { |
/* Answer will be sent when the thread becomes stoppable. */ |
_thread_op_end(t); |
return 0; |
} |
/* |
* Answer GO call |
* Answer GO call. |
*/ |
LOG("udebug_stop - answering go call\n"); |
/* Make sure nobody takes this call away from us */ |
/* Make sure nobody takes this call away from us. */ |
call = t->udebug.go_call; |
t->udebug.go_call = NULL; |
422,7 → 422,7 |
flags = t->flags; |
spinlock_unlock(&t->lock); |
/* Not interested in kernel threads */ |
/* Not interested in kernel threads. */ |
if ((flags & THREAD_FLAG_USPACE) != 0) { |
/* Using thread struct pointer as identification hash */ |
tid = (unative_t) t; |
458,16 → 458,16 |
int rc; |
unative_t *arg_buffer; |
/* Prepare a buffer to hold the arguments */ |
/* Prepare a buffer to hold the arguments. */ |
arg_buffer = malloc(6 * sizeof(unative_t), 0); |
/* On success, this will lock t->udebug.lock */ |
/* On success, this will lock t->udebug.lock. */ |
rc = _thread_op_begin(t, false); |
if (rc != EOK) { |
return rc; |
} |
/* Additionally we need to verify that we are inside a syscall */ |
/* Additionally we need to verify that we are inside a syscall. */ |
if (t->udebug.cur_event != UDEBUG_EVENT_SYSCALL_B && |
t->udebug.cur_event != UDEBUG_EVENT_SYSCALL_E) { |
_thread_op_end(t); |
474,7 → 474,7 |
return EINVAL; |
} |
/* Copy to a local buffer before releasing the lock */ |
/* Copy to a local buffer before releasing the lock. */ |
memcpy(arg_buffer, t->udebug.syscall_args, 6 * sizeof(unative_t)); |
_thread_op_end(t); |