Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2897 → Rev 2898

/branches/tracing/kernel/generic/include/proc/thread.h
214,6 → 214,7
/** What type of event are we stopped in or 0 if none */
udebug_event_t cur_event;
bool debug_stop;
bool debug_stoppable;
bool debug_active; /**< In a debugging session */
} thread_t;
 
/branches/tracing/kernel/generic/include/udebug/udebug.h
148,6 → 148,7
typedef enum {
UDEBUG_EVENT_FINISHED = 1, /**< Debuging session has finished */
UDEBUG_EVENT_STOP, /**< Stopped on DEBUG_STOP request */
UDEBUG_EVENT_SYSCALL, /**< A syscall has been executed */
UDEBUG_EVENT_NEW_THREAD /**< The task created a new thread */
} udebug_event_t;
/branches/tracing/kernel/generic/include/udebug/udebug_ops.h
41,6 → 41,7
int udebug_end(void);
 
int udebug_go(thread_t *t, call_t *call);
int udebug_stop(thread_t *t, call_t *call);
 
int udebug_thread_read(void **buffer, size_t buf_size, size_t *n);
int udebug_args_read(thread_t *t, void **buffer);
/branches/tracing/kernel/generic/src/proc/thread.c
349,6 → 349,7
t->debug_go_call = NULL;
t->uspace_state = NULL;
t->debug_stop = true;
t->debug_stoppable = true;
t->debug_active = false;
t->cur_event = 0; /* none */
 
/branches/tracing/kernel/generic/src/udebug/udebug_ipc.c
164,7 → 164,20
}
}
 
static void udebug_receive_stop(call_t *call)
{
thread_t *t;
int rc;
 
klog_printf("debug_stop()");
 
t = (thread_t *)IPC_GET_ARG2(call->data);
 
rc = udebug_stop(t, call);
IPC_SET_RETVAL(call->data, rc);
ipc_answer(&TASK->kernel_box, call);
}
 
static void udebug_receive_thread_read(call_t *call)
{
unative_t uspace_addr;
421,6 → 434,9
case UDEBUG_M_GO:
udebug_receive_go(call);
break;
case UDEBUG_M_STOP:
udebug_receive_stop(call);
break;
case UDEBUG_M_THREAD_READ:
udebug_receive_thread_read(call);
break;
/branches/tracing/kernel/generic/src/udebug/udebug.c
44,7 → 44,7
void udebug_stoppable_begin(void)
{
int nsc;
call_t *db_call;
call_t *db_call, *go_call;
ipl_t ipl;
 
ipl = interrupts_disable();
59,6 → 59,16
}
 
if (TASK->dt_state == UDEBUG_TS_BEGINNING && nsc == 0) {
/*
* This was the last non-stoppable thread. Reply to
* DEBUG_BEGIN call.
*/
 
/* Lock order OK, THREAD->debug_lock is after TASK->lock */
spinlock_lock(&THREAD->debug_lock);
THREAD->debug_stoppable = true;
spinlock_unlock(&THREAD->debug_lock);
 
TASK->dt_state = UDEBUG_TS_ACTIVE;
TASK->debug_begin_call = NULL;
spinlock_unlock(&TASK->lock);
67,7 → 77,53
IPC_SET_RETVAL(db_call->data, 0);
klog_printf("udebug_stoppable_begin/ipc_answer");
ipc_answer(&TASK->answerbox, db_call);
 
} else if (TASK->dt_state == UDEBUG_TS_ACTIVE) {
/*
* Active debugging session
*/
 
/* Lock order OK, THREAD->debug_lock is after TASK->lock */
spinlock_lock(&THREAD->debug_lock);
THREAD->debug_stoppable = true;
 
if (THREAD->debug_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;
 
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);
 
ipc_answer(&TASK->answerbox, go_call);
 
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
} else {
/*
* No stop request - nothing happens.
*/
spinlock_unlock(&THREAD->debug_lock);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
}
} else {
/*
* All other cases - nothing special happens.
*/
 
/* Lock order OK, THREAD->debug_lock is after TASK->lock */
spinlock_lock(&THREAD->debug_lock);
THREAD->debug_stoppable = true;
spinlock_unlock(&THREAD->debug_lock);
 
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
}
81,10 → 137,19
ipl = interrupts_disable();
spinlock_lock(&TASK->lock);
 
/* Lock order OK, THREAD->debug_lock is after TASK->lock */
spinlock_lock(&THREAD->debug_lock);
 
if (TASK->dt_state == UDEBUG_TS_ACTIVE) {
klog_printf("udebug_stoppable_end");
klog_printf("debug_stop=%d", THREAD->debug_stop);
}
 
if ((TASK->dt_state == UDEBUG_TS_BEGINNING ||
TASK->dt_state == UDEBUG_TS_ACTIVE) &&
THREAD->debug_stop == true) {
TASK->debug_begin_call = NULL;
spinlock_unlock(&THREAD->debug_lock);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
 
94,6 → 159,9
/* must try again - have to lose stoppability atomically */
} else {
++TASK->not_stoppable_count;
THREAD->debug_stoppable = false;
 
spinlock_unlock(&THREAD->debug_lock);
spinlock_unlock(&TASK->lock);
interrupts_restore(ipl);
}
/branches/tracing/kernel/generic/src/udebug/udebug_ops.c
52,9 → 52,10
* but only if it verifies all conditions.
*
* Specifically, verifies that thread t exists, is a userspace thread,
* and belongs to the current task (TASK). It also locks t->debug_lock,
* making sure that t->debug_active is true - that the thread is
* in a valid debugging session.
* and belongs to the current task (TASK). Verifies, that the thread
* has (or hasn't) go according to having_go (typically false).
* It also locks t->debug_lock, making sure that t->debug_active is true
* - that the thread is in a valid debugging session.
*
* Returns EOK if all went well, or an error code otherwise.
* Interrupts must be already disabled when calling this function.
61,7 → 62,7
*
* Note: This function sports complicated locking.
*/
static int _thread_op_begin(thread_t *t)
static int _thread_op_begin(thread_t *t, bool having_go)
{
int rc;
task_id_t taskid;
93,9 → 94,9
goto error_exit;
}
 
if ((t->debug_active != true) || (t->debug_stop != true)) {
/* Not in debugging session or already has GO */
rc = ENOENT;
if ((t->debug_active != true) || (!t->debug_stop != having_go)) {
/* Not in debugging session or undesired GO state */
rc = EINVAL;
goto error_exit;
}
 
213,7 → 214,7
ipl = interrupts_disable();
 
/* On success, this will lock t->debug_lock */
rc = _thread_op_begin(t);
rc = _thread_op_begin(t, false);
if (rc != EOK) {
interrupts_restore(ipl);
return rc;
234,7 → 235,60
return 0;
}
 
int udebug_stop(thread_t *t, call_t *call)
{
ipl_t ipl;
int rc;
 
klog_printf("udebug_stop()");
 
ipl = interrupts_disable();
 
/*
* On success, this will lock t->debug_lock. Note that this makes sure
* the thread is not stopped.
*/
rc = _thread_op_begin(t, true);
if (rc != EOK) {
interrupts_restore(ipl);
return rc;
}
 
/* Take GO away from the thread */
t->debug_stop = true;
 
if (!t->debug_stoppable) {
/* Answer will be sent when the thread becomes stoppable */
_thread_op_end(t);
interrupts_restore(ipl);
return 0;
}
 
/*
* Answer GO call
*/
klog_printf("udebug_stop - answering go call");
 
/* Make sure nobody takes this call away from us */
call = t->debug_go_call;
t->debug_go_call = NULL;
 
IPC_SET_RETVAL(call->data, 0);
IPC_SET_ARG1(call->data, UDEBUG_EVENT_STOP);
klog_printf("udebug_stop/ipc_answer");
 
THREAD->cur_event = UDEBUG_EVENT_STOP;
_thread_op_end(t);
 
spinlock_lock(&TASK->lock);
ipc_answer(&TASK->answerbox, call);
spinlock_unlock(&TASK->lock);
 
interrupts_restore(ipl);
klog_printf("udebog_stop/done");
return 0;
}
 
int udebug_thread_read(void **buffer, size_t buf_size, size_t *n)
{
thread_t *t;
310,7 → 364,7
ipl = interrupts_disable();
 
/* On success, this will lock t->debug_lock */
rc = _thread_op_begin(t);
rc = _thread_op_begin(t, false);
if (rc != EOK) {
interrupts_restore(ipl);
return rc;
350,7 → 404,7
ipl = interrupts_disable();
 
/* On success, this will lock t->debug_lock */
rc = _thread_op_begin(t);
rc = _thread_op_begin(t, false);
if (rc != EOK) {
interrupts_restore(ipl);
return rc;
389,7 → 443,7
ipl = interrupts_disable();
 
/* On success, this will lock t->debug_lock */
rc = _thread_op_begin(t);
rc = _thread_op_begin(t, false);
if (rc != EOK) {
interrupts_restore(ipl);
return rc;
/branches/tracing/uspace/app/sctrace/debug_api.c
79,5 → 79,12
tid, (sysarg_t)ev_type, (sysarg_t)sc_id, (sysarg_t)sc_rc);
}
 
int debug_stop(unsigned phoneid, unsigned tid)
{
return async_req_2_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_STOP,
tid);
}
 
 
/** @}
*/
/branches/tracing/uspace/app/sctrace/debug_api.h
43,6 → 43,7
int debug_args_read(unsigned phoneid, unsigned tid, unsigned *buffer);
int debug_go(unsigned phoneid, unsigned tid, unsigned *ev_type,
unsigned *sc_id, unsigned *sc_rc);
int debug_stop(unsigned phoneid, unsigned tid);
 
 
#endif
/branches/tracing/uspace/app/sctrace/sctrace.c
62,6 → 62,9
int phoneid;
int abort_trace;
 
unsigned thash;
volatile int paused;
 
void thread_trace_start(unsigned thread_hash);
 
static proto_t *proto_console;
334,6 → 337,16
case UDEBUG_EVENT_SYSCALL:
event_syscall(thread_id, thread_hash, val0, (int)val1);
break;
case UDEBUG_EVENT_STOP:
printf("stop event\n");
printf("waiting for resume\n");
while (paused) {
usleep(1000000);
fibril_yield();
printf(".");
}
printf("resumed\n");
break;
case UDEBUG_EVENT_NEW_THREAD:
event_new_thread(val0);
break;
352,6 → 365,8
{
fid_t fid;
 
thash = thread_hash;
 
fid = fibril_create(trace_loop, (void *)thread_hash);
if (fid == 0) {
printf("Warning: Failed creating fibril\n");
364,6 → 379,7
int taskid;
int i;
int rc;
int c;
 
printf("Syscall Tracer\n");
printf("Press 'c' to connect\n");
394,7 → 410,18
thread_trace_start(thread_hash_buf[i]);
}
 
getchar();
while(1) {
c = getchar();
if (c == 'q') break;
if (c == 'p') {
paused = 1;
rc = debug_stop(phoneid, thash);
printf("stop -> %d\n", rc);
}
if (c == 'r') {
paused = 0;
}
}
 
printf("terminate debugging session...\n");
abort_trace = 1;
413,6 → 440,7
oper_t *o;
 
next_thread_id = 1;
paused = 0;
 
proto_init();
 
/branches/tracing/uspace/app/tester/debug/debug1.c
43,26 → 43,33
#include <vfs/vfs.h>
#include <errno.h>
 
static ipc_call_t call;
 
char * test_debug1(bool quiet)
{
int rc;
thread_id_t tid;
// ipc_call_t call;
 
done = 0;
 
getchar();
if (mount("tmpfs", "/", "nulldev0") != EOK)
return "mount() failed.\n";
getchar();
/* while(1) {
printf(".");
ipc_wait_for_call(&call);
}*/
// getchar();
// if (mount("tmpfs", "/", "nulldev0") != EOK)
// return "mount() failed.\n";
// getchar();
 
// printf("running debug1 test\n");
// rc = thread_create(t_proc, NULL, "test", &tid);
 
//printf("(active) wait for thread 'test'\n");
// while (!done) {
// usleep(20000000);
// printf(".");
// }
while (!done) {
usleep(1*1000*1000);
printf(".");
}
 
// printf("done\n");
return NULL;