X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=lttv%2Flttv%2Fstate.c;h=f3c4bb7d16a76f2d2ce8d09a624ec431dda26f93;hb=2bc1bcfb0fdff52b3350804d2824cd023f463f96;hp=bd3f64d6cd08473ece9108b784c4c6add5c815c7;hpb=5d80006cec19cba58b7a2e5a97b4afc5bd91c7e5;p=lttv.git diff --git a/lttv/lttv/state.c b/lttv/lttv/state.c index bd3f64d6..f3c4bb7d 100644 --- a/lttv/lttv/state.c +++ b/lttv/lttv/state.c @@ -20,7 +20,7 @@ #ifdef HAVE_CONFIG_H #include #endif - + #include #include #include @@ -143,8 +143,11 @@ GQuark LttvExecutionMode LTTV_STATE_MODE_UNKNOWN, LTTV_STATE_USER_MODE, + LTTV_STATE_MAYBE_USER_MODE, LTTV_STATE_SYSCALL, + LTTV_STATE_MAYBE_SYSCALL, LTTV_STATE_TRAP, + LTTV_STATE_MAYBE_TRAP, LTTV_STATE_IRQ, LTTV_STATE_SOFT_IRQ; @@ -578,6 +581,7 @@ static void state_load_saved_states(LttvTraceState *tcs) gint hdr; gchar buf[MAX_STRING_LEN]; guint len; + size_t res; trace_path = g_quark_to_string(ltt_trace_name(tcs->parent.t)); strncpy(path, trace_path, PATH_MAX-1); @@ -600,7 +604,8 @@ static void state_load_saved_states(LttvTraceState *tcs) g_ptr_array_set_size(quarktable, q+1); i=0; while(1) { - fread(&buf[i], sizeof(gchar), 1, fp); + res = fread(&buf[i], sizeof(gchar), 1, fp); + g_assert(res == 1); if(buf[i] == '\0' || feof(fp)) break; i++; } @@ -655,6 +660,8 @@ static void init(LttvTracesetState *self, LttvTraceset *ts) init((LttvTracesetContext *)self, ts); nb_trace = lttv_traceset_number(ts); + +#ifdef BABEL_CLEANUP for(i = 0 ; i < nb_trace ; i++) { tc = self->parent.traces[i]; tcs = LTTV_TRACE_STATE(tc); @@ -733,10 +740,12 @@ static void init(LttvTracesetState *self, LttvTraceset *ts) /* See if the trace has saved states */ state_load_saved_states(tcs); } +#endif } static void fini(LttvTracesetState *self) { +#ifdef BABEL_CLEANUP guint i, nb_trace; LttvTraceState *tcs; @@ -766,6 +775,7 @@ static void fini(LttvTracesetState *self) tcs->processes = NULL; tcs->usertraces = NULL; } +#endif LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> fini((LttvTracesetContext *)self); } @@ -1053,20 +1063,21 @@ static void read_process_state_raw(LttvTraceState *self, FILE *fp, LttvProcessState *process, *parent_process; LttvProcessState tmp; GQuark tmpq; + size_t res; guint64 *address; - /* TODO : check return value */ - fread(&tmp.type, sizeof(tmp.type), 1, fp); - fread(&tmp.name, sizeof(tmp.name), 1, fp); - fread(&tmp.brand, sizeof(tmp.brand), 1, fp); - fread(&tmp.pid, sizeof(tmp.pid), 1, fp); - fread(&tmp.free_events, sizeof(tmp.free_events), 1, fp); - fread(&tmp.tgid, sizeof(tmp.tgid), 1, fp); - fread(&tmp.ppid, sizeof(tmp.ppid), 1, fp); - fread(&tmp.cpu, sizeof(tmp.cpu), 1, fp); - fread(&tmp.creation_time, sizeof(tmp.creation_time), 1, fp); - fread(&tmp.insertion_time, sizeof(tmp.insertion_time), 1, fp); + res = fread(&tmp.type, sizeof(tmp.type), 1, fp); + res += fread(&tmp.name, sizeof(tmp.name), 1, fp); + res += fread(&tmp.brand, sizeof(tmp.brand), 1, fp); + res += fread(&tmp.pid, sizeof(tmp.pid), 1, fp); + res += fread(&tmp.free_events, sizeof(tmp.free_events), 1, fp); + res += fread(&tmp.tgid, sizeof(tmp.tgid), 1, fp); + res += fread(&tmp.ppid, sizeof(tmp.ppid), 1, fp); + res += fread(&tmp.cpu, sizeof(tmp.cpu), 1, fp); + res += fread(&tmp.creation_time, sizeof(tmp.creation_time), 1, fp); + res += fread(&tmp.insertion_time, sizeof(tmp.insertion_time), 1, fp); + g_assert(res == 10); if(tmp.pid == 0) { process = lttv_state_find_process(self, tmp.cpu, tmp.pid); @@ -1109,18 +1120,22 @@ static void read_process_state_raw(LttvTraceState *self, FILE *fp, process->execution_stack->len-1); process->state = es; - fread(&es->t, sizeof(es->t), 1, fp); + res = fread(&es->t, sizeof(es->t), 1, fp); + g_assert(res == 1); es->t = g_quark_from_string( (gchar*)g_ptr_array_index(quarktable, es->t)); - fread(&es->n, sizeof(es->n), 1, fp); + res = fread(&es->n, sizeof(es->n), 1, fp); + g_assert(res == 1); es->n = g_quark_from_string( (gchar*)g_ptr_array_index(quarktable, es->n)); - fread(&es->s, sizeof(es->s), 1, fp); + res = fread(&es->s, sizeof(es->s), 1, fp); + g_assert(res == 1); es->s = g_quark_from_string( (gchar*)g_ptr_array_index(quarktable, es->s)); - fread(&es->entry, sizeof(es->entry), 1, fp); - fread(&es->change, sizeof(es->change), 1, fp); - fread(&es->cum_cpu_time, sizeof(es->cum_cpu_time), 1, fp); + res = fread(&es->entry, sizeof(es->entry), 1, fp); + res += fread(&es->change, sizeof(es->change), 1, fp); + res += fread(&es->cum_cpu_time, sizeof(es->cum_cpu_time), 1, fp); + g_assert(res == 3); break; case HDR_USER_STACK: @@ -1128,13 +1143,16 @@ static void read_process_state_raw(LttvTraceState *self, FILE *fp, process->user_stack->len + 1); address = &g_array_index(process->user_stack, guint64, process->user_stack->len-1); - fread(address, sizeof(address), 1, fp); + res = fread(address, sizeof(address), 1, fp); + g_assert(res == 1); process->current_function = *address; break; case HDR_USERTRACE: - fread(&tmpq, sizeof(tmpq), 1, fp); - fread(&process->usertrace->cpu, sizeof(process->usertrace->cpu), 1, fp); + res = fread(&tmpq, sizeof(tmpq), 1, fp); + res += fread(&process->usertrace->cpu, + sizeof(process->usertrace->cpu), 1, fp); + g_assert(res == 2); break; default: @@ -1160,6 +1178,7 @@ void lttv_state_read_raw(LttvTraceState *self, FILE *fp, GPtrArray *quarktable) guint nb_cpus; int hdr; + size_t res; LttTime t; @@ -1171,7 +1190,8 @@ void lttv_state_read_raw(LttvTraceState *self, FILE *fp, GPtrArray *quarktable) restore_init_state(self); - fread(&t, sizeof(t), 1, fp); + res = fread(&t, sizeof(t), 1, fp); + g_assert(res == 1); do { if(feof(fp) || ferror(fp)) goto end_loop; @@ -1208,10 +1228,12 @@ end_loop: int cpu_num; hdr = fgetc(fp); g_assert(hdr == HDR_CPU); - fread(&cpu_num, sizeof(cpu_num), 1, fp); /* cpu number */ + res = fread(&cpu_num, sizeof(cpu_num), 1, fp); /* cpu number */ + g_assert(res == 1); g_assert(i == cpu_num); - fread(&self->running_process[i]->pid, + res = fread(&self->running_process[i]->pid, sizeof(self->running_process[i]->pid), 1, fp); + g_assert(res == 1); } nb_tracefile = self->parent.tracefiles->len; @@ -1226,13 +1248,15 @@ end_loop: g_tree_remove(pqueue, &tfcs->parent); hdr = fgetc(fp); g_assert(hdr == HDR_TRACEFILE); - fread(&tfcs->parent.timestamp, sizeof(tfcs->parent.timestamp), 1, fp); + res = fread(&tfcs->parent.timestamp, sizeof(tfcs->parent.timestamp), 1, fp); + g_assert(res == 1); /* Note : if timestamp if LTT_TIME_INFINITE, there will be no * position following : end of trace */ if(ltt_time_compare(tfcs->parent.timestamp, ltt_time_infinite) != 0) { - fread(&nb_block, sizeof(nb_block), 1, fp); - fread(&offset, sizeof(offset), 1, fp); - fread(&tsc, sizeof(tsc), 1, fp); + res = fread(&nb_block, sizeof(nb_block), 1, fp); + res += fread(&offset, sizeof(offset), 1, fp); + res += fread(&tsc, sizeof(tsc), 1, fp); + g_assert(res == 3); ltt_event_position_set(ep, tfcs->parent.tf, nb_block, offset, tsc); gint ret = ltt_tracefile_seek_position(tfcs->parent.tf, ep); g_assert(ret == 0); @@ -1820,8 +1844,6 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) { guint i, nb_tracefile, nb_cpus, nb_irqs, nb_soft_irqs; - LttvTracefileState *tfcs; - LttvAttribute *tracefiles_tree, *tracefile_tree; guint *running_process; @@ -1881,9 +1903,7 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { - tfcs = - LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, - LttvTracefileContext*, i)); + type = lttv_attribute_get(tracefiles_tree, i, &name, &value, &is_named); g_assert(type == LTTV_GOBJECT); tracefile_tree = *((LttvAttribute **)(value.v_gobject)); @@ -2001,9 +2021,9 @@ static void create_name_tables(LttvTraceState *tcs) // } // } - name_tables->nb_syscalls = 256; - name_tables->syscall_names = g_new(GQuark, 256); - for(i = 0 ; i < 256 ; i++) { + name_tables->nb_syscalls = PREALLOC_NB_SYSCALLS; + name_tables->syscall_names = g_new(GQuark, name_tables->nb_syscalls); + for(i = 0 ; i < name_tables->nb_syscalls; i++) { g_string_printf(fe_name, "syscall %d", i); name_tables->syscall_names[i] = g_quark_from_string(fe_name->str); } @@ -2035,9 +2055,9 @@ static void create_name_tables(LttvTraceState *tcs) // ltt_enum_string_get(t, i)); // } - name_tables->nb_traps = 256; - name_tables->trap_names = g_new(GQuark, 256); - for(i = 0 ; i < 256 ; i++) { + name_tables->nb_traps = PREALLOC_NB_TRAPS; + name_tables->trap_names = g_new(GQuark, name_tables->nb_traps); + for(i = 0 ; i < name_tables->nb_traps; i++) { g_string_printf(fe_name, "trap %d", i); name_tables->trap_names[i] = g_quark_from_string(fe_name->str); } @@ -2060,11 +2080,10 @@ static void create_name_tables(LttvTraceState *tcs) } */ /* FIXME: LttvIRQState *irq_states should become a g_array */ - /* temp fix: increase from 256 to 512 default size */ - name_tables->nb_irqs = 512; - name_tables->irq_names = g_new(GQuark, 512); - for(i = 0 ; i < 512 ; i++) { + name_tables->nb_irqs = PREALLOC_NB_IRQS; + name_tables->irq_names = g_new(GQuark, name_tables->nb_irqs); + for(i = 0 ; i < name_tables->nb_irqs; i++) { g_string_printf(fe_name, "irq %d", i); name_tables->irq_names[i] = g_quark_from_string(fe_name->str); } @@ -2080,8 +2099,7 @@ static void create_name_tables(LttvTraceState *tcs) } */ - /* the kernel is limited to 32 statically defined softirqs */ - name_tables->nb_soft_irqs = 32; + name_tables->nb_soft_irqs = PREALLOC_NB_SOFT_IRQS; name_tables->soft_irq_names = g_new(GQuark, name_tables->nb_soft_irqs); for(i = 0 ; i < name_tables->nb_soft_irqs ; i++) { g_string_printf(fe_name, "softirq %d", i); @@ -2678,21 +2696,10 @@ static gboolean soft_irq_raise(void *hook_data, void *call_data) //guint8 ev_id = ltt_event_eventtype_id(e); LttvTraceHook *th = (LttvTraceHook *)hook_data; struct marker_field *f = lttv_trace_get_hook_field(th, 0); - LttvNameTables *nt = ((LttvTraceState *)(s->parent.t_context))->name_tables; - LttvExecutionSubmode submode; guint64 softirq = ltt_event_get_long_unsigned(e, f); - guint64 nb_softirqs = nt->nb_soft_irqs; - if(softirq < nb_softirqs) { - submode = nt->soft_irq_names[softirq]; - } else { - /* Fixup an incomplete irq table */ - GString *string = g_string_new(""); - g_string_printf(string, "softirq %" PRIu64, softirq); - submode = g_quark_from_string(string->str); - g_string_free(string, TRUE); - } + expand_soft_irq_table(ts, softirq); /* update softirq status */ /* a soft irq raises are not cumulative */ @@ -2887,11 +2894,9 @@ static gboolean dump_syscall(void *hook_data, void *call_data) LttEvent *e = ltt_tracefile_get_event(s->parent.tf); LttvTraceHook *th = (LttvTraceHook *)hook_data; guint id; - guint64 address; char *symbol; id = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); - address = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1)); symbol = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2)); expand_syscall_table(ts, id); @@ -2925,11 +2930,9 @@ static gboolean dump_softirq(void *hook_data, void *call_data) LttEvent *e = ltt_tracefile_get_event(s->parent.tf); LttvTraceHook *th = (LttvTraceHook *)hook_data; guint id; - guint64 address; char *symbol; id = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); - address = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1)); symbol = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2)); expand_soft_irq_table(ts, id); @@ -2954,8 +2957,12 @@ static gboolean sched_try_wakeup(void *hook_data, void *call_data) (LttvTraceState*)s->parent.t_context, woken_cpu, woken_pid, &s->parent.timestamp); - process->state->s = LTTV_STATE_WAIT_CPU; - process->state->change = s->parent.timestamp; + + if (process->state->s == LTTV_STATE_WAIT || process->state->s == LTTV_STATE_WAIT_FORK) + { + process->state->s = LTTV_STATE_WAIT_CPU; + process->state->change = s->parent.timestamp; + } g_debug("Wakeup: process %d on CPU %u\n", woken_pid, woken_cpu); @@ -2996,8 +3003,11 @@ static gboolean schedchange(void *hook_data, void *call_data) if(process->pid == 0 && process->state->t == LTTV_STATE_MODE_UNKNOWN) { if(pid_out == 0) { - /* Scheduling out of pid 0 at beginning of the trace : - * we know for sure it is in syscall mode at this point. */ + /* + * Scheduling out of pid 0 at beginning of the trace. + * We are typically in system call mode at this point although + * (FIXME) we might be in a trap handler. + */ g_assert(process->execution_stack->len == 1); process->state->t = LTTV_STATE_SYSCALL; process->state->s = LTTV_STATE_WAIT; @@ -3057,7 +3067,6 @@ static gboolean process_fork(void *hook_data, void *call_data) LttvTracefileState *s = (LttvTracefileState *)call_data; LttEvent *e = ltt_tracefile_get_event(s->parent.tf); LttvTraceHook *th = (LttvTraceHook *)hook_data; - guint parent_pid; guint child_pid; /* In the Linux Kernel, there is one PID per thread. */ guint child_tgid; /* tgid in the Linux kernel is the "real" POSIX PID. */ //LttvProcessState *zombie_process; @@ -3067,8 +3076,7 @@ static gboolean process_fork(void *hook_data, void *call_data) LttvProcessState *child_process; struct marker_field *f; - /* Parent PID */ - parent_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); + /* Skip Parent PID param */ /* Child PID */ child_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1)); @@ -3343,7 +3351,7 @@ static void fix_process(gpointer key, gpointer value, gpointer user_data) if(process->type == LTTV_STATE_KERNEL_THREAD) { es = &g_array_index(process->execution_stack, LttvExecutionState, 0); - if(es->t == LTTV_STATE_MODE_UNKNOWN) { + if(es->t == LTTV_STATE_MAYBE_SYSCALL) { es->t = LTTV_STATE_SYSCALL; es->n = LTTV_STATE_SUBMODE_NONE; es->entry = *timestamp; @@ -3354,7 +3362,7 @@ static void fix_process(gpointer key, gpointer value, gpointer user_data) } } else { es = &g_array_index(process->execution_stack, LttvExecutionState, 0); - if(es->t == LTTV_STATE_MODE_UNKNOWN) { + if(es->t == LTTV_STATE_MAYBE_USER_MODE) { es->t = LTTV_STATE_USER_MODE; es->n = LTTV_STATE_SUBMODE_NONE; es->entry = *timestamp; @@ -3424,7 +3432,7 @@ static gboolean enum_process_state(void *hook_data, void *call_data) LttvProcessState *process = ts->running_process[cpu]; LttvProcessState *parent_process; struct marker_field *f; - GQuark type, mode, submode, status; + GQuark type; LttvExecutionState *es; guint i, nb_cpus; @@ -3444,17 +3452,11 @@ static gboolean enum_process_state(void *hook_data, void *call_data) //FIXME: type is rarely used, enum must match possible types. - /* mode */ - f = lttv_trace_get_hook_field(th, 4); - mode = ltt_enum_string_get(f,ltt_event_get_unsigned(e, f)); + /* Skip mode 4th param */ - /* submode */ - f = lttv_trace_get_hook_field(th, 5); - submode = ltt_enum_string_get(f, ltt_event_get_unsigned(e, f)); + /* Skip submode 5th param */ - /* status */ - f = lttv_trace_get_hook_field(th, 6); - status = ltt_enum_string_get(f, ltt_event_get_unsigned(e, f)); + /* Skip status 6th param */ /* TGID */ f = lttv_trace_get_hook_field(th, 7); @@ -3500,14 +3502,11 @@ static gboolean enum_process_state(void *hook_data, void *call_data) es = process->state = &g_array_index(process->execution_stack, LttvExecutionState, 0); process->type = LTTV_STATE_KERNEL_THREAD; - es->t = LTTV_STATE_MODE_UNKNOWN; + es->t = LTTV_STATE_MAYBE_SYSCALL; es->s = LTTV_STATE_UNNAMED; es->n = LTTV_STATE_SUBMODE_UNKNOWN; -#if 0 - es->t = LTTV_STATE_SYSCALL; - es->s = status; - es->n = submode; -#endif //0 + //es->s = status; + //es->n = submode; } else { /* User space process : * bottom : user mode @@ -3525,14 +3524,11 @@ static gboolean enum_process_state(void *hook_data, void *call_data) process->execution_stack = g_array_set_size(process->execution_stack, 1); es = process->state = &g_array_index(process->execution_stack, LttvExecutionState, 0); - es->t = LTTV_STATE_MODE_UNKNOWN; + es->t = LTTV_STATE_MAYBE_USER_MODE; es->s = LTTV_STATE_UNNAMED; es->n = LTTV_STATE_SUBMODE_UNKNOWN; - #if 0 - es->t = LTTV_STATE_USER_MODE; - es->s = status; - es->n = submode; - #endif //0 + //es->s = status; + //es->n = submode; } #if 0 /* UNKNOWN STATE */ @@ -4416,8 +4412,11 @@ static void module_init() LTTV_STATE_UNBRANDED = g_quark_from_string(""); LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("MODE_UNKNOWN"); LTTV_STATE_USER_MODE = g_quark_from_string("USER_MODE"); + LTTV_STATE_MAYBE_USER_MODE = g_quark_from_string("MAYBE_USER_MODE"); LTTV_STATE_SYSCALL = g_quark_from_string("SYSCALL"); + LTTV_STATE_MAYBE_SYSCALL = g_quark_from_string("MAYBE_SYSCALL"); LTTV_STATE_TRAP = g_quark_from_string("TRAP"); + LTTV_STATE_MAYBE_TRAP = g_quark_from_string("MAYBE_TRAP"); LTTV_STATE_IRQ = g_quark_from_string("IRQ"); LTTV_STATE_SOFT_IRQ = g_quark_from_string("SOFTIRQ"); LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("UNKNOWN");