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; |
} |
|