Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4667 → Rev 4668

/branches/dd/uspace/app/trace/trace.c
43,7 → 43,11
#include <task.h>
#include <mem.h>
#include <string.h>
#include <bool.h>
#include <loader/loader.h>
#include <io/console.h>
#include <io/keycode.h>
#include <fibril_sync.h>
 
#include <libc.h>
 
64,22 → 68,31
 
int next_thread_id;
 
ipc_call_t thread_ipc_req[THBUF_SIZE];
 
int phoneid;
int abort_trace;
bool abort_trace;
 
uintptr_t thash;
volatile int paused;
static bool paused;
static fibril_condvar_t state_cv;
static fibril_mutex_t state_lock;
 
static bool cev_valid;
static console_event_t cev;
 
void thread_trace_start(uintptr_t thread_hash);
 
static proto_t *proto_console;
static task_id_t task_id;
static loader_t *task_ldr;
static bool task_wait_for;
 
/** Combination of events/data to print. */
display_mask_t display_mask;
 
static int program_run_fibril(void *arg);
static int cev_fibril(void *arg);
 
static void program_run(void)
{
94,6 → 107,19
fibril_add_ready(fid);
}
 
static void cev_fibril_start(void)
{
fid_t fid;
 
fid = fibril_create(cev_fibril, NULL);
if (fid == 0) {
printf("Error creating fibril\n");
exit(1);
}
 
fibril_add_ready(fid);
}
 
static int program_run_fibril(void *arg)
{
int rc;
315,7 → 341,7
ipcp_call_sync(phoneidx, &question, &reply);
}
 
static void sc_ipc_call_sync_slow(sysarg_t *sc_args)
static void sc_ipc_call_sync_slow_b(unsigned thread_id, sysarg_t *sc_args)
{
ipc_call_t question, reply;
int rc;
322,15 → 348,27
 
memset(&question, 0, sizeof(question));
rc = udebug_mem_read(phoneid, &question.args, sc_args[1], sizeof(question.args));
printf("dmr->%d\n", rc);
if (rc < 0) return;
if (rc < 0) {
printf("Error: mem_read->%d\n", rc);
return;
}
 
thread_ipc_req[thread_id] = question;
}
 
static void sc_ipc_call_sync_slow_e(unsigned thread_id, sysarg_t *sc_args)
{
ipc_call_t question, reply;
int rc;
 
memset(&reply, 0, sizeof(reply));
rc = udebug_mem_read(phoneid, &reply.args, sc_args[2], sizeof(reply.args));
printf("dmr->%d\n", rc);
if (rc < 0) return;
if (rc < 0) {
printf("Error: mem_read->%d\n", rc);
return;
}
 
ipcp_call_sync(sc_args[0], &question, &reply);
ipcp_call_sync(sc_args[0], &thread_ipc_req[thread_id], &reply);
}
 
static void sc_ipc_wait(sysarg_t *sc_args, int sc_rc)
375,6 → 413,14
print_sc_args(sc_args, syscall_desc[sc_id].n_args);
}
 
switch (sc_id) {
case SYS_IPC_CALL_SYNC_SLOW:
sc_ipc_call_sync_slow_b(thread_id, sc_args);
break;
default:
break;
}
 
async_serialize_end();
}
 
415,7 → 461,7
sc_ipc_call_sync_fast(sc_args);
break;
case SYS_IPC_CALL_SYNC_SLOW:
sc_ipc_call_sync_slow(sc_args);
sc_ipc_call_sync_slow_e(thread_id, sc_args);
break;
case SYS_IPC_WAIT:
sc_ipc_wait(sc_args, sc_rc);
446,20 → 492,26
 
thread_hash = (uintptr_t)thread_hash_arg;
thread_id = next_thread_id++;
if (thread_id >= THBUF_SIZE) {
printf("Too many threads.\n");
return ELIMIT;
}
 
printf("Start tracing thread [%d] (hash 0x%lx).\n", thread_id, thread_hash);
 
while (!abort_trace) {
 
fibril_mutex_lock(&state_lock);
if (paused) {
printf("Press R to resume (and be patient).\n");
while (paused) {
usleep(1000000);
fibril_yield();
printf(".");
}
printf("Resumed\n");
printf("Thread [%d] paused. Press R to resume.\n",
thread_id);
 
while (paused)
fibril_condvar_wait(&state_cv, &state_lock);
 
printf("Thread [%d] resumed.\n", thread_id);
}
fibril_mutex_unlock(&state_lock);
 
/* Run thread until an event occurs */
rc = udebug_go(phoneid, thread_hash,
481,6 → 533,9
break;
case UDEBUG_EVENT_STOP:
printf("Stop event\n");
fibril_mutex_lock(&state_lock);
paused = true;
fibril_mutex_unlock(&state_lock);
break;
case UDEBUG_EVENT_THREAD_B:
event_thread_b(val0);
487,7 → 542,10
break;
case UDEBUG_EVENT_THREAD_E:
printf("Thread 0x%lx exited.\n", val0);
abort_trace = 1;
fibril_mutex_lock(&state_lock);
abort_trace = true;
fibril_condvar_broadcast(&state_cv);
fibril_mutex_unlock(&state_lock);
break;
default:
printf("Unknown event type %d.\n", ev_type);
540,6 → 598,33
if (rc != EOK)
goto error;
 
/* Send default files */
fdi_node_t *files[4];
fdi_node_t stdin_node;
fdi_node_t stdout_node;
fdi_node_t stderr_node;
if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK))
files[0] = &stdin_node;
else
files[0] = NULL;
if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK))
files[1] = &stdout_node;
else
files[1] = NULL;
if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK))
files[2] = &stderr_node;
else
files[2] = NULL;
files[3] = NULL;
rc = loader_set_files(ldr, files);
if (rc != EOK)
goto error;
 
/* Load the program. */
rc = loader_load_program(ldr);
if (rc != EOK)
555,11 → 640,32
return NULL;
}
 
static int cev_fibril(void *arg)
{
(void) arg;
 
while (true) {
fibril_mutex_lock(&state_lock);
while (cev_valid)
fibril_condvar_wait(&state_cv, &state_lock);
fibril_mutex_unlock(&state_lock);
 
if (!console_get_event(fphone(stdin), &cev))
return -1;
 
fibril_mutex_lock(&state_lock);
cev_valid = true;
fibril_condvar_broadcast(&state_cv);
fibril_mutex_unlock(&state_lock);
}
}
 
static void trace_task(task_id_t task_id)
{
console_event_t ev;
bool done;
int i;
int rc;
int c;
 
ipcp_init();
 
575,29 → 681,55
return;
}
 
abort_trace = 0;
abort_trace = false;
 
for (i = 0; i < n_threads; i++) {
thread_trace_start(thread_hash_buf[i]);
}
 
while(1) {
c = getchar();
if (c == 'q') break;
if (c == 'p') {
done = false;
 
while (!done) {
fibril_mutex_lock(&state_lock);
while (!cev_valid && !abort_trace)
fibril_condvar_wait(&state_cv, &state_lock);
fibril_mutex_unlock(&state_lock);
 
ev = cev;
 
fibril_mutex_lock(&state_lock);
cev_valid = false;
fibril_condvar_broadcast(&state_cv);
fibril_mutex_unlock(&state_lock);
 
if (abort_trace)
break;
 
if (ev.type != KEY_PRESS)
continue;
 
switch (ev.key) {
case KC_Q:
done = true;
break;
case KC_P:
printf("Pause...\n");
paused = 1;
rc = udebug_stop(phoneid, thash);
printf("stop -> %d\n", rc);
}
if (c == 'r') {
paused = 0;
if (rc != EOK)
printf("Error: stop -> %d\n", rc);
break;
case KC_R:
fibril_mutex_lock(&state_lock);
paused = false;
fibril_condvar_broadcast(&state_cv);
fibril_mutex_unlock(&state_lock);
printf("Resume...\n");
break;
}
}
 
printf("\nTerminate debugging session...\n");
abort_trace = 1;
abort_trace = true;
udebug_end(phoneid);
ipc_hangup(phoneid);
 
629,37 → 761,53
};
 
next_thread_id = 1;
paused = 0;
paused = false;
cev_valid = false;
 
fibril_mutex_initialize(&state_lock);
fibril_condvar_initialize(&state_cv);
 
proto_init();
 
p = proto_new("vfs");
o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_OPEN, o);
o = oper_new("open_node", 4, arg_def, V_INT_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_OPEN_NODE, o);
o = oper_new("read", 1, arg_def, V_ERRNO, 1, resp_def);
proto_add_oper(p, VFS_READ, o);
proto_add_oper(p, VFS_IN_READ, o);
o = oper_new("write", 1, arg_def, V_ERRNO, 1, resp_def);
proto_add_oper(p, VFS_WRITE, o);
proto_add_oper(p, VFS_IN_WRITE, o);
o = oper_new("seek", 3, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_SEEK, o);
o = oper_new("truncate", 5, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_TRUNCATE, o);
proto_add_oper(p, VFS_IN_TRUNCATE, o);
o = oper_new("fstat", 1, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_FSTAT, o);
o = oper_new("close", 1, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_CLOSE, o);
o = oper_new("mount", 2, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_MOUNT, o);
proto_add_oper(p, VFS_IN_MOUNT, o);
/* o = oper_new("unmount", 0, arg_def);
proto_add_oper(p, VFS_UNMOUNT, o);*/
o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_OPEN, o);
o = oper_new("close", 1, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_CLOSE, o);
o = oper_new("seek", 3, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_SEEK, o);
proto_add_oper(p, VFS_IN_UNMOUNT, o);*/
o = oper_new("sync", 1, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_SYNC, o);
o = oper_new("mkdir", 1, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_MKDIR, o);
proto_add_oper(p, VFS_IN_MKDIR, o);
o = oper_new("unlink", 0, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_UNLINK, o);
proto_add_oper(p, VFS_IN_UNLINK, o);
o = oper_new("rename", 0, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_RENAME, o);
proto_add_oper(p, VFS_IN_RENAME, o);
o = oper_new("stat", 0, arg_def, V_ERRNO, 0, resp_def);
proto_add_oper(p, VFS_IN_STAT, o);
 
proto_register(SERVICE_VFS, p);
 
p = proto_new("console");
 
o = oper_new("write", 1, arg_def, V_ERRNO, 1, resp_def);
proto_add_oper(p, VFS_IN_WRITE, o);
 
resp_def[0] = V_INTEGER; resp_def[1] = V_INTEGER;
resp_def[2] = V_INTEGER; resp_def[3] = V_CHAR;
o = oper_new("getkey", 0, arg_def, V_ERRNO, 4, resp_def);
752,6 → 900,7
--argc; ++argv;
task_id = strtol(*argv, &err_p, 10);
task_ldr = NULL;
task_wait_for = false;
if (*err_p) {
printf("Task ID syntax error\n");
print_syntax();
789,6 → 938,7
while (*cp) printf("'%s'\n", *cp++);
}
task_ldr = preload_task(*argv, argv, &task_id);
task_wait_for = true;
 
return 0;
}
796,6 → 946,8
int main(int argc, char *argv[])
{
int rc;
task_exit_t texit;
int retval;
 
printf("System Call / IPC Tracer\n");
printf("Controls: Q - Quit, P - Pause, R - Resume\n");
815,12 → 967,29
 
printf("Connected to task %lld.\n", task_id);
 
if (task_ldr != NULL) {
if (task_ldr != NULL)
program_run();
}
 
cev_fibril_start();
trace_task(task_id);
 
if (task_wait_for) {
printf("Waiting for task to exit.\n");
 
rc = task_wait(task_id, &texit, &retval);
if (rc != EOK) {
printf("Failed waiting for task.\n");
return -1;
}
 
if (texit == TASK_EXIT_NORMAL) {
printf("Task exited normally, return value %d.\n",
retval);
} else {
printf("Task exited unexpectedly.\n");
}
}
 
return 0;
}