X-Git-Url: http://git.liburcu.org/?p=lttv.git;a=blobdiff_plain;f=lttv%2Flttv%2Fstate.c;h=2a0717a9c43caf6997b52ccc61186f031ab4aeca;hp=38d3ba4a5f8d8cfd6264428b1f72336e3dea0a59;hb=7b20eed1e2a33658249baf49488b6c93028639f9;hpb=e865422cc50d00cb57ec05ed07bba4cbe160904e diff --git a/lttv/lttv/state.c b/lttv/lttv/state.c index 38d3ba4a..2a0717a9 100644 --- a/lttv/lttv/state.c +++ b/lttv/lttv/state.c @@ -25,24 +25,13 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include #include #include -#include #include - -/* Comment : - * Mathieu Desnoyers - * usertrace is there only to be able to update the current CPU of the - * usertraces when there is a schedchange. it is a way to link the ProcessState - * to the associated usertrace. Link only created upon thread creation. - * - * The cpu id is necessary : it gives us back the current ProcessState when we - * are considering data from the usertrace. - */ +#include #define PREALLOCATED_EXECUTION_STACK 10 @@ -75,8 +64,8 @@ GQuark LTT_EVENT_PAGE_FAULT_NOSEM_EXIT, LTT_EVENT_PAGE_FAULT_ENTRY, LTT_EVENT_PAGE_FAULT_EXIT, - LTT_EVENT_TRAP_ENTRY, - LTT_EVENT_TRAP_EXIT, + //LTT_EVENT_TRAP_ENTRY, + //LTT_EVENT_TRAP_EXIT, LTT_EVENT_IRQ_ENTRY, LTT_EVENT_IRQ_EXIT, LTT_EVENT_SOFT_IRQ_RAISE, @@ -196,7 +185,7 @@ static GQuark LTTV_STATE_PROCESSES, LTTV_STATE_PROCESS, LTTV_STATE_RUNNING_PROCESS, - LTTV_STATE_EVENT, + LTTV_STATE_POSITION, LTTV_STATE_SAVED_STATES, LTTV_STATE_SAVED_STATES_TIME, LTTV_STATE_TIME, @@ -235,7 +224,7 @@ static LttvBdevState *bdevstate_new(void); static void bdevstate_free(LttvBdevState *); static void bdevstate_free_cb(gpointer key, gpointer value, gpointer user_data); static LttvBdevState *bdevstate_copy(LttvBdevState *bds); - +void lttv_state_add_event_hooks(LttvTraceset *traceset); #if (__WORDSIZE == 32) guint guint64_hash(gconstpointer key) @@ -254,25 +243,6 @@ gboolean guint64_equal(gconstpointer a, gconstpointer b) } #endif -void lttv_state_save(LttvTraceState *self, LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container); -} - - -void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); -} - - -void lttv_state_state_saved_free(LttvTraceState *self, - LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_saved_free(self, container); -} - - guint process_hash(gconstpointer key) { guint pid = ((const LttvProcessState *)key)->pid; @@ -297,17 +267,6 @@ gboolean process_equal(gconstpointer a, gconstpointer b) return ret; } -static void delete_usertrace(gpointer key, gpointer value, gpointer user_data) -{ - g_tree_destroy((GTree*)value); -} - -static void lttv_state_free_usertraces(GHashTable *usertraces) -{ - g_hash_table_foreach(usertraces, delete_usertrace, NULL); - g_hash_table_destroy(usertraces); -} - gboolean rettrue(gpointer key, gpointer value, gpointer user_data) { return TRUE; @@ -343,20 +302,6 @@ static void fill_name_table(LttvTraceState *ts, GQuark *table, guint nb, g_string_free(fe_name, TRUE); } -static void expand_syscall_table(LttvTraceState *ts, int id) -{ - LttvNameTables *nt = ts->name_tables; - guint new_nb; - - new_nb = check_expand(nt->nb_syscalls, id); - if(likely(new_nb == nt->nb_syscalls)) - return; - expand_name_table(ts, &nt->syscall_names, nt->nb_syscalls, new_nb); - fill_name_table(ts, nt->syscall_names, nt->nb_syscalls, new_nb, "syscall"); - /* Update the table size */ - nt->nb_syscalls = new_nb; -} - static void expand_kprobe_table(LttvTraceState *ts, guint64 ip, char *symbol) { LttvNameTables *nt = ts->name_tables; @@ -450,13 +395,11 @@ static void restore_init_state(LttvTraceState *self) //LttvTracefileState *tfcs; - LttTime start_time, end_time; + LttTime start_time; /* Free the process tables */ if(self->processes != NULL) lttv_state_free_process_table(self->processes); - if(self->usertraces != NULL) lttv_state_free_usertraces(self->usertraces); self->processes = g_hash_table_new(process_hash, process_equal); - self->usertraces = g_hash_table_new(g_direct_hash, g_direct_equal); self->nb_event = 0; /* Seek time to beginning */ @@ -466,11 +409,14 @@ static void restore_init_state(LttvTraceState *self) //g_tree_destroy(self->parent.ts_context->pqueue); //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile); - ltt_trace_time_span_get(self->parent.t, &start_time, &end_time); + start_time = ltt_time_from_uint64( + bt_trace_handle_get_timestamp_begin(self->trace->traceset->context, + self->trace->id,BT_CLOCK_REAL)); + //lttv_process_trace_seek_time(&self->parent, ltt_time_zero); - nb_cpus = ltt_trace_get_num_cpu(self->parent.t); + nb_cpus = lttv_trace_get_num_cpu(self->trace); nb_irqs = self->name_tables->nb_irqs; nb_soft_irqs = self->name_tables->nb_soft_irqs; nb_traps = self->name_tables->nb_traps; @@ -551,19 +497,7 @@ static void restore_init_state(LttvTraceState *self) //static LttTime time_zero = {0,0}; -static gint compare_usertraces(gconstpointer a, gconstpointer b, - gpointer user_data) -{ - const LttTime *t1 = (const LttTime *)a; - const LttTime *t2 = (const LttTime *)b; - - return ltt_time_compare(*t1, *t2); -} - -static void free_usertrace_key(gpointer data) -{ - g_free(data); -} +#ifdef BABEL_CLEANUP #define MAX_STRING_LEN 4096 @@ -642,157 +576,89 @@ end: g_ptr_array_free(quarktable, TRUE); return; } +#endif /* BABEL_CLEANUP */ -static void init(LttvTracesetState *self, LttvTraceset *ts) +void lttv_trace_state_init(LttvTraceState *trace_state, LttvTrace *trace) { - guint i, j, nb_trace, nb_tracefile, nb_cpu; + guint j, nb_cpu; guint64 nb_irq; - - LttvTraceContext *tc; - - LttvTraceState *tcs; - - LttvTracefileState *tfcs; - LttvAttributeValue v; - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - init((LttvTracesetContext *)self, ts); + trace_state->trace = trace; - nb_trace = lttv_traceset_number(ts); - for(i = 0 ; i < nb_trace ; i++) { - tc = self->parent.traces[i]; - tcs = LTTV_TRACE_STATE(tc); - tcs->save_interval = LTTV_STATE_SAVE_INTERVAL; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT, - LTTV_UINT, &v); - (*v.v_uint)++; - - if(*(v.v_uint) == 1) { - create_name_tables(tcs); - create_max_time(tcs); - } - get_name_tables(tcs); - get_max_time(tcs); - - nb_tracefile = tc->tracefiles->len; - nb_cpu = ltt_trace_get_num_cpu(tc->t); - nb_irq = tcs->name_tables->nb_irqs; - tcs->processes = NULL; - tcs->usertraces = NULL; - tcs->running_process = g_new(LttvProcessState*, nb_cpu); - - /* init cpu resource stuff */ - tcs->cpu_states = g_new(LttvCPUState, nb_cpu); - for(j = 0; jcpu_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvCPUMode)); - tcs->cpu_states[j].irq_stack = g_array_new(FALSE, FALSE, sizeof(gint)); - tcs->cpu_states[j].softirq_stack = g_array_new(FALSE, FALSE, sizeof(gint)); - tcs->cpu_states[j].trap_stack = g_array_new(FALSE, FALSE, sizeof(gint)); - g_assert(tcs->cpu_states[j].mode_stack != NULL); - } + trace_state->save_interval = LTTV_STATE_SAVE_INTERVAL; + lttv_attribute_find(lttv_trace_attribute(trace), LTTV_STATE_TRACE_STATE_USE_COUNT, + LTTV_UINT, &v); + (*v.v_uint)++; - /* init irq resource stuff */ - tcs->irq_states = g_new(LttvIRQState, nb_irq); - for(j = 0; jirq_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvIRQMode)); - g_assert(tcs->irq_states[j].mode_stack != NULL); - } - - /* init soft irq stuff */ - /* the kernel has a statically fixed max of 32 softirqs */ - tcs->soft_irq_states = g_new(LttvSoftIRQState, tcs->name_tables->nb_soft_irqs); - - /* init trap stuff */ - tcs->trap_states = g_new(LttvTrapState, tcs->name_tables->nb_traps); - - /* init bdev resource stuff */ - tcs->bdev_states = g_hash_table_new(g_int_hash, g_int_equal); - - restore_init_state(tcs); - for(j = 0 ; j < nb_tracefile ; j++) { - tfcs = - LTTV_TRACEFILE_STATE(g_array_index(tc->tracefiles, - LttvTracefileContext*, j)); - tfcs->tracefile_name = ltt_tracefile_name(tfcs->parent.tf); - tfcs->cpu = ltt_tracefile_cpu(tfcs->parent.tf); - tfcs->cpu_state = &(tcs->cpu_states[tfcs->cpu]); - if(ltt_tracefile_tid(tfcs->parent.tf) != 0) { - /* It's a Usertrace */ - guint tid = ltt_tracefile_tid(tfcs->parent.tf); - GTree *usertrace_tree = (GTree*)g_hash_table_lookup(tcs->usertraces, - GUINT_TO_POINTER(tid)); - if(!usertrace_tree) { - usertrace_tree = g_tree_new_full(compare_usertraces, - NULL, free_usertrace_key, NULL); - g_hash_table_insert(tcs->usertraces, - GUINT_TO_POINTER(tid), usertrace_tree); - } - LttTime *timestamp = g_new(LttTime, 1); - *timestamp = ltt_interpolate_time_from_tsc(tfcs->parent.tf, - ltt_tracefile_creation(tfcs->parent.tf)); - g_tree_insert(usertrace_tree, timestamp, tfcs); - } - } - - /* See if the trace has saved states */ - state_load_saved_states(tcs); + if (*(v.v_uint) == 1) { + create_name_tables(trace_state); + create_max_time(trace_state); + } + get_name_tables(trace_state); + get_max_time(trace_state); + + nb_cpu = lttv_trace_get_num_cpu(trace); + nb_irq = trace_state->name_tables->nb_irqs; + trace_state->processes = NULL; + trace_state->running_process = g_new(LttvProcessState*, nb_cpu); + + /* init cpu resource stuff */ + trace_state->cpu_states = g_new(LttvCPUState, nb_cpu); + for (j = 0; j < nb_cpu; j++) { + trace_state->cpu_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvCPUMode)); + trace_state->cpu_states[j].irq_stack = g_array_new(FALSE, FALSE, sizeof(gint)); + trace_state->cpu_states[j].softirq_stack = g_array_new(FALSE, FALSE, sizeof(gint)); + trace_state->cpu_states[j].trap_stack = g_array_new(FALSE, FALSE, sizeof(gint)); + g_assert(trace_state->cpu_states[j].mode_stack != NULL); } -} - -static void fini(LttvTracesetState *self) -{ - guint i, nb_trace; - LttvTraceState *tcs; + /* init irq resource stuff */ + trace_state->irq_states = g_new(LttvIRQState, nb_irq); + for (j = 0; j < nb_irq; j++) { + trace_state->irq_states[j].mode_stack = g_array_new(FALSE, FALSE, sizeof(LttvIRQMode)); + g_assert(trace_state->irq_states[j].mode_stack != NULL); + } - //LttvTracefileState *tfcs; + /* init soft irq stuff */ + /* the kernel has a statically fixed max of 32 softirqs */ + trace_state->soft_irq_states = g_new(LttvSoftIRQState, trace_state->name_tables->nb_soft_irqs); - LttvAttributeValue v; + /* init trap stuff */ + trace_state->trap_states = g_new(LttvTrapState, trace_state->name_tables->nb_traps); - nb_trace = lttv_traceset_number(LTTV_TRACESET_CONTEXT(self)->ts); - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceState *)(LTTV_TRACESET_CONTEXT(self)->traces[i]); - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT, - LTTV_UINT, &v); + /* init bdev resource stuff */ + trace_state->bdev_states = g_hash_table_new(g_int_hash, g_int_equal); - g_assert(*(v.v_uint) != 0); - (*v.v_uint)--; + restore_init_state(trace_state); - if(*(v.v_uint) == 0) { - free_name_tables(tcs); - free_max_time(tcs); - free_saved_state(tcs); - } - g_free(tcs->running_process); - tcs->running_process = NULL; - lttv_state_free_process_table(tcs->processes); - lttv_state_free_usertraces(tcs->usertraces); - tcs->processes = NULL; - tcs->usertraces = NULL; - } - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - fini((LttvTracesetContext *)self); + /* See if the trace has saved states */ + //state_load_saved_states(trace_state); } - -static LttvTracesetContext *new_traceset_context(LttvTracesetContext *self) +void lttv_trace_state_fini(LttvTraceState *trace_state) { - return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE, NULL)); -} - + LttvTrace *trace = trace_state->trace; + LttvAttributeValue v; -static LttvTraceContext *new_trace_context(LttvTracesetContext *self) -{ - return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE, NULL)); -} + lttv_attribute_find(lttv_trace_attribute(trace), LTTV_STATE_TRACE_STATE_USE_COUNT, + LTTV_UINT, &v); + g_assert(*(v.v_uint) != 0); + (*v.v_uint)--; -static LttvTracefileContext *new_tracefile_context(LttvTracesetContext *self) -{ - return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE, NULL)); + if (*(v.v_uint) == 0) { + free_name_tables(trace_state); + free_max_time(trace_state); + free_saved_state(trace_state); + } + g_free(trace_state->running_process); + trace_state->running_process = NULL; + lttv_state_free_process_table(trace_state->processes); + trace_state->processes = NULL; } +#ifdef BABEL_CLEANUP /* Write the process state of the trace */ @@ -834,13 +700,6 @@ static void write_process_state(gpointer key, gpointer value, fprintf(fp, " \n", address); } - if(process->usertrace) { - fprintf(fp, " ", - g_quark_to_string(process->usertrace->tracefile_name), - process->usertrace->cpu); - } - - fprintf(fp, " \n"); } @@ -971,21 +830,6 @@ static void write_process_state_raw(gpointer key, gpointer value, fprintf(fp, " \n", address); #endif //0 } - - if(process->usertrace) { - fputc(HDR_USERTRACE, fp); - //fprintf(fp, "%s", g_quark_to_string(process->usertrace->tracefile_name)); - //fputc('\0', fp); - fwrite(&process->usertrace->tracefile_name, - sizeof(process->usertrace->tracefile_name), 1, fp); - fwrite(&process->usertrace->cpu, sizeof(process->usertrace->cpu), 1, fp); -#if 0 - fprintf(fp, " ", - g_quark_to_string(process->usertrace->tracefile_name), - process->usertrace->cpu); -#endif //0 - } - } @@ -1143,13 +987,6 @@ static void read_process_state_raw(LttvTraceState *self, FILE *fp, process->current_function = *address; break; - case HDR_USERTRACE: - res = fread(&tmpq, sizeof(tmpq), 1, fp); - res += fread(&process->usertrace->cpu, - sizeof(process->usertrace->cpu), 1, fp); - g_assert(res == 2); - break; - default: ungetc(hdr, fp); goto end_loop; @@ -1205,7 +1042,6 @@ void lttv_state_read_raw(LttvTraceState *self, FILE *fp, GPtrArray *quarktable) case HDR_QUARK: case HDR_ES: case HDR_USER_STACK: - case HDR_USERTRACE: case HDR_PROCESS_STATE: case HDR_CPU: ungetc(hdr, fp); @@ -1299,7 +1135,6 @@ void lttv_trace_states_read_raw(LttvTraceState *tcs, FILE *fp, case HDR_QUARK: case HDR_ES: case HDR_USER_STACK: - case HDR_USERTRACE: case HDR_PROCESS: case HDR_CPU: g_error("Error while parsing saved state file :" @@ -1317,7 +1152,7 @@ end_loop: lttv_process_trace_seek_time(&tcs->parent, ltt_time_zero); return; } - +#endif /* BABEL_CLEANUP */ /* Copy each process from an existing hash table to a new one */ @@ -1344,6 +1179,7 @@ static void copy_process_state(gpointer key, gpointer value,gpointer user_data) } new_process->state = &g_array_index(new_process->execution_stack, LttvExecutionState, new_process->execution_stack->len - 1); +#ifdef BABEL_CLEANUP new_process->user_stack = g_array_sized_new(FALSE, FALSE, sizeof(guint64), 0); new_process->user_stack = g_array_set_size(new_process->user_stack, @@ -1353,6 +1189,7 @@ static void copy_process_state(gpointer key, gpointer value,gpointer user_data) g_array_index(process->user_stack, guint64, i); } new_process->current_function = process->current_function; +#endif /* BABEL_CLEANUP */ /* fd hash table stuff */ { @@ -1598,29 +1435,20 @@ static void lttv_state_free_blkdev_hashtable(GHashTable *ht) to the current process and a "position" member storing the tracefile position (needed to seek to the current "next" event. */ -static void state_save(LttvTraceState *self, LttvAttribute *container) +void lttv_state_save(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps; - - LttvTracefileState *tfcs; - - LttvAttribute *tracefiles_tree, *tracefile_tree; + guint i, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps; guint *running_process; LttvAttributeValue value; - LttEventPosition *ep; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - value = lttv_attribute_add(container, LTTV_STATE_PROCESSES, LTTV_POINTER); *(value.v_pointer) = lttv_state_copy_process_table(self->processes); /* Add the currently running processes array */ - nb_cpus = ltt_trace_get_num_cpu(self->parent.t); + nb_cpus = lttv_trace_get_num_cpu(self->trace); running_process = g_new(guint, nb_cpus); for(i=0;irunning_process[i]->pid; @@ -1631,8 +1459,13 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) g_info("State save"); - nb_tracefile = self->parent.tracefiles->len; + /* Save the current position */ + value = lttv_attribute_add(container, LTTV_STATE_POSITION, + LTTV_POINTER); + *(value.v_pointer) = lttv_traceset_create_current_position(lttv_trace_get_traceset(self->trace)); +#ifdef BABEL_CLEANUP + nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { tfcs = LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, @@ -1668,6 +1501,7 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) tfcs->parent.timestamp.tv_nsec); } } +#endif /* BABEL_CLEANUP */ /* save the cpu state */ { @@ -1710,33 +1544,13 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) *(value.v_pointer) = lttv_state_copy_blkdev_hashtable(self->bdev_states); } - -static void state_restore(LttvTraceState *self, LttvAttribute *container) +void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile, pid, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps; - - LttvTracefileState *tfcs; - - LttvAttribute *tracefiles_tree, *tracefile_tree; - + guint i, pid, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps; guint *running_process; - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - - gboolean is_named; - - LttEventPosition *ep; - - LttvTracesetContext *tsc = self->parent.ts_context; - int retval; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, &value); g_assert(type == LTTV_POINTER); @@ -1744,7 +1558,7 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) self->processes = lttv_state_copy_process_table(*(value.v_pointer)); /* Add the currently running processes array */ - nb_cpus = ltt_trace_get_num_cpu(self->parent.t); + nb_cpus = lttv_trace_get_num_cpu(self->trace); type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS, &value); g_assert(type == LTTV_POINTER); @@ -1755,7 +1569,7 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) g_assert(self->running_process[i] != NULL); } - nb_tracefile = self->parent.tracefiles->len; + //nb_tracefile = self->parent.tracefiles->len; //g_tree_destroy(tsc->pqueue); //tsc->pqueue = g_tree_new(compare_tracefile); @@ -1793,6 +1607,7 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) lttv_state_free_blkdev_hashtable(self->bdev_states); self->bdev_states = lttv_state_copy_blkdev_hashtable(*(value.v_pointer)); +#ifdef BABEL_CLEANUP for(i = 0 ; i < nb_tracefile ; i++) { tfcs = LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, @@ -1832,30 +1647,30 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) tfc->timestamp = ltt_time_infinite; } } +#endif /* BABEL_CLEANUP */ } - -static void state_saved_free(LttvTraceState *self, LttvAttribute *container) +/* + * Note: the position must be explicitely set on the entire traceset to + * match the trace states. + */ +LttvTracesetPosition *lttv_trace_state_get_position(LttvAttribute *container) { - guint i, nb_tracefile, nb_cpus, nb_irqs, nb_soft_irqs; + LttvAttributeType type; + LttvAttributeValue value; - LttvAttribute *tracefiles_tree, *tracefile_tree; + type = lttv_attribute_get_by_name(container, LTTV_STATE_POSITION, &value); + g_assert(type == LTTV_POINTER); + return *(value.v_pointer); +} +void lttv_state_saved_free(LttvTraceState *self, LttvAttribute *container) +{ + guint nb_cpus, nb_irqs, nb_soft_irqs; guint *running_process; - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - - gboolean is_named; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - g_object_ref(G_OBJECT(tracefiles_tree)); - lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES); - type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, &value); g_assert(type == LTTV_POINTER); @@ -1870,7 +1685,7 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) running_process = *(value.v_pointer); g_free(running_process); - /* free cpu resource states */ + /* free cpu resources */ type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_CPUS_COUNT, &value); g_assert(type == LTTV_UINT); nb_cpus = *value.v_uint; @@ -1895,6 +1710,12 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) g_assert(type == LTTV_POINTER); lttv_state_free_blkdev_hashtable(*(value.v_pointer)); + /* remove the position */ + type = lttv_attribute_get_by_name(container, LTTV_STATE_POSITION, &value); + g_assert(type == LTTV_POINTER); + lttv_traceset_destroy_position(*(value.v_pointer)); + +#ifdef BABEL_CLEANUP nb_tracefile = self->parent.tracefiles->len; for(i = 0 ; i < nb_tracefile ; i++) { @@ -1909,42 +1730,40 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer)); } g_object_unref(G_OBJECT(tracefiles_tree)); +#endif /* BABEL_CLEANUP */ } static void free_saved_state(LttvTraceState *self) { guint i, nb; - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - gboolean is_named; - LttvAttribute *saved_states; - saved_states = lttv_attribute_find_subdir(self->parent.t_a, + saved_states = lttv_attribute_find_subdir(lttv_trace_attribute(self->trace), LTTV_STATE_SAVED_STATES); nb = lttv_attribute_get_number(saved_states); for(i = 0 ; i < nb ; i++) { type = lttv_attribute_get(saved_states, i, &name, &value, &is_named); g_assert(type == LTTV_GOBJECT); - state_saved_free(self, *((LttvAttribute **)value.v_gobject)); + lttv_state_saved_free(self, *((LttvAttribute **)value.v_gobject)); } - lttv_attribute_remove_by_name(self->parent.t_a, LTTV_STATE_SAVED_STATES); + lttv_attribute_remove_by_name(lttv_trace_attribute(self->trace), + LTTV_STATE_SAVED_STATES); } -static void create_max_time(LttvTraceState *tcs) +static void create_max_time(LttvTraceState *trace_state) { LttvAttributeValue v; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + lttv_attribute_find(lttv_trace_attribute(trace_state->trace), + LTTV_STATE_SAVED_STATES_TIME, LTTV_POINTER, &v); g_assert(*(v.v_pointer) == NULL); *(v.v_pointer) = g_new(LttTime,1); @@ -1952,22 +1771,24 @@ static void create_max_time(LttvTraceState *tcs) } -static void get_max_time(LttvTraceState *tcs) +static void get_max_time(LttvTraceState *trace_state) { LttvAttributeValue v; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + lttv_attribute_find(lttv_trace_attribute(trace_state->trace), + LTTV_STATE_SAVED_STATES_TIME, LTTV_POINTER, &v); g_assert(*(v.v_pointer) != NULL); - tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer); + trace_state->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer); } -static void free_max_time(LttvTraceState *tcs) +static void free_max_time(LttvTraceState *trace_state) { LttvAttributeValue v; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + lttv_attribute_find(lttv_trace_attribute(trace_state->trace), + LTTV_STATE_SAVED_STATES_TIME, LTTV_POINTER, &v); g_free(*(v.v_pointer)); *(v.v_pointer) = NULL; @@ -1983,13 +1804,14 @@ static void create_name_tables(LttvTraceState *tcs) LttvAttributeValue v; - GArray *hooks; + // GArray *hooks; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + lttv_attribute_find(lttv_trace_attribute(tcs->trace), LTTV_STATE_NAME_TABLES, LTTV_POINTER, &v); g_assert(*(v.v_pointer) == NULL); *(v.v_pointer) = name_tables; +#ifdef BABEL_CLEANUP hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 1); if(!lttv_trace_find_hook(tcs->parent.t, @@ -2015,6 +1837,7 @@ static void create_name_tables(LttvTraceState *tcs) // g_string_free(string, TRUE); // } // } +#endif /* BABEL_CLEANUP */ name_tables->nb_syscalls = PREALLOC_NB_SYSCALLS; name_tables->syscall_names = g_new(GQuark, name_tables->nb_syscalls); @@ -2022,12 +1845,15 @@ static void create_name_tables(LttvTraceState *tcs) g_string_printf(fe_name, "syscall %d", i); name_tables->syscall_names[i] = g_quark_from_string(fe_name->str); } +#ifdef BABEL_CLEANUP } else { name_tables->syscall_names = NULL; name_tables->nb_syscalls = 0; } lttv_trace_hook_remove_all(&hooks); +#endif /* BABEL_CLEANUP */ +#ifdef BABEL_CLEANUP if(!lttv_trace_find_hook(tcs->parent.t, LTT_CHANNEL_KERNEL, LTT_EVENT_TRAP_ENTRY, @@ -2050,18 +1876,22 @@ static void create_name_tables(LttvTraceState *tcs) // ltt_enum_string_get(t, i)); // } +#endif /* BABEL_CLEANUP */ 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); } +#ifdef BABEL_CLEANUP } else { name_tables->trap_names = NULL; name_tables->nb_traps = 0; } lttv_trace_hook_remove_all(&hooks); +#endif /* BABEL_CLEANUP */ +#ifdef BABEL_CLEANUP if(!lttv_trace_find_hook(tcs->parent.t, LTT_CHANNEL_KERNEL, LTT_EVENT_IRQ_ENTRY, @@ -2076,17 +1906,20 @@ static void create_name_tables(LttvTraceState *tcs) */ /* FIXME: LttvIRQState *irq_states should become a g_array */ +#endif /* BABEL_CLEANUP */ 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); } +#ifdef BABEL_CLEANUP } else { name_tables->nb_irqs = 0; name_tables->irq_names = NULL; } lttv_trace_hook_remove_all(&hooks); +#endif /* BABEL_CLEANUP */ /* name_tables->soft_irq_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { @@ -2100,7 +1933,7 @@ static void create_name_tables(LttvTraceState *tcs) g_string_printf(fe_name, "softirq %d", i); name_tables->soft_irq_names[i] = g_quark_from_string(fe_name->str); } - g_array_free(hooks, TRUE); + // g_array_free(hooks, TRUE); g_string_free(fe_name, TRUE); @@ -2117,7 +1950,7 @@ static void get_name_tables(LttvTraceState *tcs) { LttvAttributeValue v; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + lttv_attribute_find(lttv_trace_attribute(tcs->trace), LTTV_STATE_NAME_TABLES, LTTV_POINTER, &v); g_assert(*(v.v_pointer) != NULL); tcs->name_tables = (LttvNameTables *)*(v.v_pointer); @@ -2130,7 +1963,7 @@ static void free_name_tables(LttvTraceState *tcs) LttvAttributeValue v; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + lttv_attribute_find(lttv_trace_attribute(tcs->trace), LTTV_STATE_NAME_TABLES, LTTV_POINTER, &v); name_tables = (LttvNameTables *)*(v.v_pointer); *(v.v_pointer) = NULL; @@ -2224,13 +2057,15 @@ static void irq_pop_mode(LttvIRQState *irqst) g_array_set_size(irqst->mode_stack, irqst->mode_stack->len - 1); } -static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, +static void push_state(LttvEvent *event, + LttvTraceState *ts, LttvExecutionMode t, guint state_id) { LttvExecutionState *es; + gint cpu; - LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; - guint cpu = tfs->cpu; + cpu = lttv_traceset_get_cpuid_from_event(event); + g_assert(cpu >= 0); #ifdef HASH_TABLE_DEBUG hash_table_check(ts->processes); @@ -2248,7 +2083,7 @@ static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, es = &g_array_index(process->execution_stack, LttvExecutionState, depth); es->t = t; es->n = state_id; - es->entry = es->change = tfs->parent.timestamp; + es->entry = es->change = lttv_event_get_timestamp(event); es->cum_cpu_time = ltt_time_zero; es->s = process->state->s; process->state = es; @@ -2257,7 +2092,7 @@ static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, /* pop state * return 1 when empty, else 0 */ int -lttv_state_pop_state_cleanup(LttvProcessState *process, LttvTracefileState *tfs) +lttv_state_pop_state_cleanup(LttvProcessState *process, LttvEvent *event) { guint depth = process->execution_stack->len; @@ -2269,22 +2104,27 @@ lttv_state_pop_state_cleanup(LttvProcessState *process, LttvTracefileState *tfs) g_array_set_size(process->execution_stack, depth - 1); process->state = &g_array_index(process->execution_stack, LttvExecutionState, depth - 2); - process->state->change = tfs->parent.timestamp; + process->state->change = lttv_event_get_timestamp(event); return 0; } -static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) +static void pop_state(LttvEvent *event, + LttvTraceState *ts, LttvExecutionMode t) { - guint cpu = tfs->cpu; - LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; + LttvProcessState *process; + gint cpu; + + cpu = lttv_traceset_get_cpuid_from_event(event); + g_assert(cpu >= 0); + process = ts->running_process[cpu]; guint depth = process->execution_stack->len; if(process->state->t != t){ - g_info("Different execution mode type (%lu.%09lu): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + g_info("Different execution mode type: ignore it\n" + ); + g_info("process state has %s when pop_int is %s\n", g_quark_to_string(process->state->t), g_quark_to_string(t)); @@ -2298,8 +2138,10 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) } if(depth == 1){ - g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + //TODO ybrosseau readd debug + //g_info("Trying to pop last state on stack (%lu.%09lu): ignore it\n", + // tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + g_info("Trying to pop last state on stack: ignore it\n"); return; } @@ -2307,7 +2149,7 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) g_array_set_size(process->execution_stack, depth - 1); process->state = &g_array_index(process->execution_stack, LttvExecutionState, depth - 2); - process->state->change = tfs->parent.timestamp; + process->state->change = lttv_event_get_timestamp(event); } struct search_result { @@ -2315,53 +2157,6 @@ struct search_result { LttTime *best; /* Best result */ }; -static gint search_usertrace(gconstpointer a, gconstpointer b) -{ - const LttTime *elem_time = (const LttTime*)a; - /* Explicit non const cast */ - struct search_result *res = (struct search_result *)b; - - if(ltt_time_compare(*elem_time, *(res->time)) < 0) { - /* The usertrace was created before the schedchange */ - /* Get larger keys */ - return 1; - } else if(ltt_time_compare(*elem_time, *(res->time)) >= 0) { - /* The usertrace was created after the schedchange time */ - /* Get smaller keys */ - if(res->best) { - if(ltt_time_compare(*elem_time, *res->best) < 0) { - res->best = (LttTime *)elem_time; - } - } else { - res->best = (LttTime *)elem_time; - } - return -1; - } - return 0; -} - -static LttvTracefileState *ltt_state_usertrace_find(LttvTraceState *tcs, - guint pid, const LttTime *timestamp) -{ - LttvTracefileState *tfs = NULL; - struct search_result res; - /* Find the usertrace associated with a pid and time interval. - * Search in the usertraces by PID (within a hash) and then, for each - * corresponding element of the array, find the first one with creation - * timestamp the lowest, but higher or equal to "timestamp". */ - res.time = timestamp; - res.best = NULL; - GTree *usertrace_tree = g_hash_table_lookup(tcs->usertraces, - GUINT_TO_POINTER(pid)); - if(usertrace_tree) { - g_tree_search(usertrace_tree, search_usertrace, &res); - if(res.best) - tfs = g_tree_lookup(usertrace_tree, res.best); - } - - return tfs; -} - /* Return a new and initialized LttvProcessState structure */ LttvProcessState *lttv_state_create_process(LttvTraceState *tcs, @@ -2382,8 +2177,6 @@ LttvProcessState *lttv_state_create_process(LttvTraceState *tcs, //process->last_cpu = tfs->cpu_name; //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf); process->type = LTTV_STATE_USER_THREAD; - process->usertrace = ltt_state_usertrace_find(tcs, pid, timestamp); - process->current_function = 0; //function 0x0 by default. g_info("Process %u, core %p", process->pid, process); g_hash_table_insert(tcs->processes, process, process); @@ -2434,9 +2227,10 @@ LttvProcessState *lttv_state_create_process(LttvTraceState *tcs, es->s = LTTV_STATE_WAIT_FORK; /* Allocate an empty function call stack. If it's empty, use 0x0. */ - process->user_stack = g_array_sized_new(FALSE, FALSE, - sizeof(guint64), 0); - +#ifdef BABEL_CLEANUP + //process->user_stack = g_array_sized_new(FALSE, FALSE, + // sizeof(guint64), 0); +#endif process->fds = g_hash_table_new(g_direct_hash, g_direct_equal); return process; @@ -2483,9 +2277,9 @@ LttvProcessState *lttv_state_find_process_or_create(LttvTraceState *ts, * has the flag SA_NOCLDWAIT. It can also happen when the child is part * of a killed thread group, but isn't the leader. */ -static int exit_process(LttvTracefileState *tfs, LttvProcessState *process) +static int exit_process(LttvEvent *event, LttvProcessState *process) { - LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context); + LttvTraceState *ts = event->state; LttvProcessState key; /* Wait for both schedule with exit dead and process free to happen. @@ -2497,7 +2291,6 @@ static int exit_process(LttvTracefileState *tfs, LttvProcessState *process) key.cpu = process->cpu; g_hash_table_remove(ts->processes, &key); g_array_free(process->execution_stack, TRUE); - g_array_free(process->user_stack, TRUE); /* the following also clears the content */ g_hash_table_destroy(process->fds); @@ -2510,7 +2303,6 @@ static int exit_process(LttvTracefileState *tfs, LttvProcessState *process) static void free_process_state(gpointer key, gpointer value,gpointer user_data) { g_array_free(((LttvProcessState *)value)->execution_stack, TRUE); - g_array_free(((LttvProcessState *)value)->user_stack, TRUE); /* the following also clears the content */ g_hash_table_destroy(((LttvProcessState *)value)->fds); @@ -2528,40 +2320,56 @@ static void lttv_state_free_process_table(GHashTable *processes) static gboolean syscall_entry(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - guint cpu = s->cpu; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); + LttvEvent *event; + guint cpu; + LttvTraceState *ts; + LttvProcessState *process; LttvExecutionSubmode submode; - LttvNameTables *nt = ((LttvTraceState *)(s->parent.t_context))->name_tables; + char syscall_name[200]; + + event = (LttvEvent *) call_data; + if (strncmp(lttv_traceset_get_name_from_event(event), + "sys_", sizeof("sys_") - 1) != 0) + return FALSE; - guint syscall = ltt_event_get_unsigned(e, f); - expand_syscall_table(ts, syscall); - submode = nt->syscall_names[syscall]; + strncpy(syscall_name,lttv_traceset_get_name_from_event(event)+4,200); + + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + + submode = g_quark_from_string(syscall_name); /* There can be no system call from PID 0 : unknown state */ if(process->pid != 0) - push_state(s, LTTV_STATE_SYSCALL, submode); + push_state(event, ts, LTTV_STATE_SYSCALL, submode); return FALSE; } static gboolean syscall_exit(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - guint cpu = s->cpu; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; + LttvEvent *event; + guint cpu; + LttvTraceState *ts; + LttvProcessState *process; + + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "exit_syscall") != 0) + return FALSE; + + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; /* There can be no system call from PID 0 : unknown state */ - if(process->pid != 0) - pop_state(s, LTTV_STATE_SYSCALL); + if (process->pid != 0) + pop_state(event, ts, LTTV_STATE_SYSCALL); return FALSE; } - +#ifdef BABEL_CLEANUP static gboolean trap_entry(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; @@ -2612,32 +2420,41 @@ static gboolean trap_exit(void *hook_data, void *call_data) } return FALSE; } +#endif /* BABEL_CLEANUP */ static gboolean irq_entry(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //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; + LttvEvent *event; + guint cpu; + LttvTraceState *ts; LttvExecutionSubmode submode; - guint64 irq = ltt_event_get_long_unsigned(e, f); + LttvNameTables *nt; + guint64 irq; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "irq_handler_entry") != 0) + return FALSE; + + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + + nt = ts->name_tables; + irq = lttv_event_get_long(event, "irq"); expand_irq_table(ts, irq); submode = nt->irq_names[irq]; /* Do something with the info about being in user or system mode when int? */ - push_state(s, LTTV_STATE_IRQ, submode); + push_state(event, ts, LTTV_STATE_IRQ, submode); /* update cpu status */ - cpu_push_mode(s->cpu_state, LTTV_CPU_IRQ); + cpu_push_mode(&(ts->cpu_states[cpu]), LTTV_CPU_IRQ); /* update irq status */ - g_array_append_val(s->cpu_state->irq_stack, irq); + g_array_append_val(ts->cpu_states[cpu].irq_stack, irq); irq_push_mode(&ts->irq_states[irq], LTTV_IRQ_BUSY); return FALSE; @@ -2645,38 +2462,62 @@ static gboolean irq_entry(void *hook_data, void *call_data) static gboolean soft_irq_exit(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; + LttvEvent *event; + guint cpu; + LttvTraceState *ts; + + LttvCPUState *cpu_state; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "softirq_exit") != 0) + return FALSE; - pop_state(s, LTTV_STATE_SOFT_IRQ); + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + + cpu_state = &(ts->cpu_states[cpu]); + pop_state(event, ts, LTTV_STATE_SOFT_IRQ); /* update cpu status */ - cpu_pop_mode(s->cpu_state); + cpu_pop_mode(cpu_state); /* update softirq status */ - if (s->cpu_state->softirq_stack->len > 0) { - gint last = g_array_index(s->cpu_state->softirq_stack, gint, s->cpu_state->softirq_stack->len-1); + if (cpu_state->softirq_stack->len > 0) { + gint last = g_array_index(cpu_state->softirq_stack, gint, cpu_state->softirq_stack->len-1); if(ts->soft_irq_states[last].running) ts->soft_irq_states[last].running--; - g_array_remove_index(s->cpu_state->softirq_stack, s->cpu_state->softirq_stack->len-1); + g_array_remove_index(cpu_state->softirq_stack, cpu_state->softirq_stack->len-1); } return FALSE; } static gboolean irq_exit(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; + LttvEvent *event; + guint cpu; + LttvTraceState *ts; + + LttvCPUState *cpu_state; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "irq_handler_exit") != 0) + return FALSE; - pop_state(s, LTTV_STATE_IRQ); + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + cpu_state = &(ts->cpu_states[cpu]); + + pop_state(event, ts, LTTV_STATE_IRQ); /* update cpu status */ - cpu_pop_mode(s->cpu_state); + cpu_pop_mode(cpu_state); /* update irq status */ - if (s->cpu_state->irq_stack->len > 0) { - gint last = g_array_index(s->cpu_state->irq_stack, gint, s->cpu_state->irq_stack->len-1); - g_array_remove_index(s->cpu_state->irq_stack, s->cpu_state->irq_stack->len-1); + if (cpu_state->irq_stack->len > 0) { + gint last = g_array_index(cpu_state->irq_stack, gint, cpu_state->irq_stack->len-1); + g_array_remove_index(cpu_state->irq_stack, cpu_state->irq_stack->len-1); irq_pop_mode(&ts->irq_states[last]); } @@ -2685,14 +2526,20 @@ static gboolean irq_exit(void *hook_data, void *call_data) static gboolean soft_irq_raise(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); + LttvEvent *event; + //guint cpu; + LttvTraceState *ts; + + + guint64 softirq; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "softirq_raise") != 0) + return FALSE; - guint64 softirq = ltt_event_get_long_unsigned(e, f); + //cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + softirq = lttv_event_get_long_unsigned(event, "vec"); expand_soft_irq_table(ts, softirq); @@ -2705,27 +2552,38 @@ static gboolean soft_irq_raise(void *hook_data, void *call_data) static gboolean soft_irq_entry(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); + LttvEvent *event; + guint cpu; + LttvTraceState *ts; LttvExecutionSubmode submode; - guint64 softirq = ltt_event_get_long_unsigned(e, f); + LttvNameTables *nt; + guint64 softirq; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "softirq_entry") != 0) + return FALSE; + + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + + + + + softirq = lttv_event_get_long_unsigned(event, "vec"); expand_soft_irq_table(ts, softirq); - LttvNameTables *nt = ((LttvTraceState *)(s->parent.t_context))->name_tables; + nt = ts->name_tables; submode = nt->soft_irq_names[softirq]; /* Do something with the info about being in user or system mode when int? */ - push_state(s, LTTV_STATE_SOFT_IRQ, submode); + push_state(event, ts, LTTV_STATE_SOFT_IRQ, submode); /* update cpu status */ - cpu_push_mode(s->cpu_state, LTTV_CPU_SOFT_IRQ); + cpu_push_mode(&(ts->cpu_states[cpu]), LTTV_CPU_SOFT_IRQ); /* update softirq status */ - g_array_append_val(s->cpu_state->softirq_stack, softirq); - if(ts->soft_irq_states[softirq].pending) + g_array_append_val(ts->cpu_states[cpu].softirq_stack, softirq); + if (ts->soft_irq_states[softirq].pending) ts->soft_irq_states[softirq].pending--; ts->soft_irq_states[softirq].running++; @@ -2734,43 +2592,58 @@ static gboolean soft_irq_entry(void *hook_data, void *call_data) static gboolean enum_interrupt(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; - LttvNameTables *nt = ts->name_tables; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; + + LttvNameTables *nt; - GQuark action = g_quark_from_string(ltt_event_get_string(e, - lttv_trace_get_hook_field(th, 0))); - guint irq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1)); + GQuark action; + guint irq; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "lttng_statedump_interrupt") != 0) + return FALSE; + ts = event->state; + + nt = ts->name_tables; + irq = lttv_event_get_long_unsigned(event, "irq"); + action = g_quark_from_string(lttv_event_get_string(event, + "action")); expand_irq_table(ts, irq); nt->irq_names[irq] = action; return FALSE; } - +#ifdef BABEL_CLEANUP static gboolean bdev_request_issue(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState *)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; - guint major = ltt_event_get_long_unsigned(e, - lttv_trace_get_hook_field(th, 0)); - guint minor = ltt_event_get_long_unsigned(e, - lttv_trace_get_hook_field(th, 1)); - guint oper = ltt_event_get_long_unsigned(e, - lttv_trace_get_hook_field(th, 2)); - guint32 devcode = MKDEV(major,minor); + guint major; + guint minor; + guint oper; + guint32 devcode; + gpointer bdev; - /* have we seen this block device before? */ - gpointer bdev = get_hashed_bdevstate(ts, devcode); + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "block_rq_issue") != 0) + return FALSE; + + ts = event->state; + major = lttv_event_get_long_unsigned(event,); + + minor = lttv_event_get_long_unsigned(event,); + + oper = lttv_event_get_long_unsigned(event,); + + devcode = MKDEV(major,minor); + /* have we seen this block device before? */ + bdev = get_hashed_bdevstate(ts, devcode); if(oper == 0) bdev_push_mode(bdev, LTTV_BDEV_BUSY_READING); else @@ -2802,85 +2675,9 @@ static gboolean bdev_request_complete(void *hook_data, void *call_data) return FALSE; } - -static void push_function(LttvTracefileState *tfs, guint64 funcptr) -{ - guint64 *new_func; - - LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; - guint cpu = tfs->cpu; - LttvProcessState *process = ts->running_process[cpu]; - - guint depth = process->user_stack->len; - - process->user_stack = - g_array_set_size(process->user_stack, depth + 1); - - new_func = &g_array_index(process->user_stack, guint64, depth); - *new_func = funcptr; - process->current_function = funcptr; -} - -static void pop_function(LttvTracefileState *tfs, guint64 funcptr) -{ - guint cpu = tfs->cpu; - LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; - - if(process->current_function != funcptr){ - g_info("Different functions (%lu.%09lu): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); - g_info("process state has %" PRIu64 " when pop_function is %" PRIu64 "\n", - process->current_function, funcptr); - g_info("{ %u, %u, %s, %s, %s }\n", - process->pid, - process->ppid, - g_quark_to_string(process->name), - g_quark_to_string(process->brand), - g_quark_to_string(process->state->s)); - return; - } - guint depth = process->user_stack->len; - - if(depth == 0){ - g_info("Trying to pop last function on stack (%lu.%09lu): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); - return; - } - - process->user_stack = - g_array_set_size(process->user_stack, depth - 1); - process->current_function = - g_array_index(process->user_stack, guint64, depth - 2); -} - - -static gboolean function_entry(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); - guint64 funcptr = ltt_event_get_long_unsigned(e, f); - - push_function(s, funcptr); - return FALSE; -} - -static gboolean function_exit(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //guint8 ev_id = ltt_event_eventtype_id(e); - LttvTraceHook *th = (LttvTraceHook *)hook_data; - struct marker_field *f = lttv_trace_get_hook_field(th, 0); - guint64 funcptr = ltt_event_get_long_unsigned(e, f); - - pop_function(s, funcptr); - return FALSE; -} - +#endif +#ifdef BABEL_CLEANUP +// We dont have the syscall table in LTTng 2.0 static gboolean dump_syscall(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; @@ -2916,9 +2713,11 @@ static gboolean dump_kprobe(void *hook_data, void *call_data) return FALSE; } - +#endif +#ifdef BABEL_CLEANUP static gboolean dump_softirq(void *hook_data, void *call_data) { + LttvTracefileState *s = (LttvTracefileState *)call_data; LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; LttvNameTables *nt = ts->name_tables; @@ -2934,29 +2733,38 @@ static gboolean dump_softirq(void *hook_data, void *call_data) nt->soft_irq_names[id] = g_quark_from_string(symbol); return FALSE; -} +} +#endif static gboolean sched_try_wakeup(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; + LttvEvent *event; + LttvTraceState *ts; LttvProcessState *process; gint woken_pid; guint woken_cpu; + LttTime timestamp; - woken_pid = ltt_event_get_int(e, lttv_trace_get_hook_field(th, 0)); - woken_cpu = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1)); + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sched_wakeup") != 0) + return FALSE; + + ts = event->state; + woken_pid = lttv_event_get_long(event, "tid"); + woken_cpu = lttv_event_get_long(event, "target_cpu"); + + timestamp = lttv_event_get_timestamp(event); process = lttv_state_find_process_or_create( - (LttvTraceState*)s->parent.t_context, - woken_cpu, woken_pid, - &s->parent.timestamp); + ts, + woken_cpu, woken_pid, + ×tamp); 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; + process->state->change = timestamp; } g_debug("Wakeup: process %d on CPU %u\n", woken_pid, woken_cpu); @@ -2966,21 +2774,36 @@ static gboolean sched_try_wakeup(void *hook_data, void *call_data) static gboolean schedchange(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - guint cpu = s->cpu; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; + LttvEvent *event; + guint cpu; + LttvTraceState *ts; + LttvProcessState *process; + + //LttvProcessState *old_process = ts->running_process[cpu]; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; guint pid_in, pid_out; gint64 state_out; + //TODO ybrosseau 2012-07-13: manage this 20 in a constact or dynamically + char next_comm[20]; + LttTime timestamp; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sched_switch") != 0) + return FALSE; - pid_out = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); - pid_in = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1)); - state_out = ltt_event_get_long_int(e, lttv_trace_get_hook_field(th, 2)); + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + pid_out = lttv_event_get_long(event, "prev_tid"); + pid_in = lttv_event_get_long(event, "next_tid"); + state_out = lttv_event_get_long(event, "prev_state"); + strncpy(next_comm, lttv_event_get_string(event, "next_comm"), 20); + next_comm[20-1] = '\0'; + + timestamp = lttv_event_get_timestamp(event); + if(likely(process != NULL)) { /* We could not know but it was not the idle process executing. @@ -3006,52 +2829,51 @@ static gboolean schedchange(void *hook_data, void *call_data) g_assert(process->execution_stack->len == 1); process->state->t = LTTV_STATE_SYSCALL; process->state->s = LTTV_STATE_WAIT; - process->state->change = s->parent.timestamp; - process->state->entry = s->parent.timestamp; + process->state->change = timestamp; + process->state->entry = timestamp; } } else { if(unlikely(process->state->s == LTTV_STATE_EXIT)) { process->state->s = LTTV_STATE_ZOMBIE; - process->state->change = s->parent.timestamp; + process->state->change = timestamp; } else { if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU; else process->state->s = LTTV_STATE_WAIT; - process->state->change = s->parent.timestamp; + process->state->change = timestamp; } if(state_out == 32 || state_out == 64) { /* EXIT_DEAD || TASK_DEAD */ /* see sched.h for states */ - if (!exit_process(s, process)) { + if (!exit_process(event, process)) { process->state->s = LTTV_STATE_DEAD; - process->state->change = s->parent.timestamp; + process->state->change = timestamp; } } } } process = ts->running_process[cpu] = lttv_state_find_process_or_create( - (LttvTraceState*)s->parent.t_context, + ts, cpu, pid_in, - &s->parent.timestamp); + ×tamp); process->state->s = LTTV_STATE_RUN; process->cpu = cpu; - if(process->usertrace) - process->usertrace->cpu = cpu; // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf); - process->state->change = s->parent.timestamp; + process->state->change = timestamp; + process->name = g_quark_from_string(next_comm); /* update cpu status */ if(pid_in == 0) /* going to idle task */ - cpu_set_base_mode(s->cpu_state, LTTV_CPU_IDLE); + cpu_set_base_mode(&(ts->cpu_states[cpu]), LTTV_CPU_IDLE); else { /* scheduling a real task. * we must be careful here: * if we just schedule()'ed to a process that is * in a trap, we must put the cpu in trap mode */ - cpu_set_base_mode(s->cpu_state, LTTV_CPU_BUSY); + cpu_set_base_mode(&(ts->cpu_states[cpu]), LTTV_CPU_BUSY); if(process->state->t == LTTV_STATE_TRAP) - cpu_push_mode(s->cpu_state, LTTV_CPU_TRAP); + cpu_push_mode(&(ts->cpu_states[cpu]), LTTV_CPU_TRAP); } return FALSE; @@ -3059,30 +2881,34 @@ static gboolean schedchange(void *hook_data, void *call_data) 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; + LttvEvent *event; + LttvTraceState *ts; + LttvProcessState *process; + LttvProcessState *child_process; 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; - guint cpu = s->cpu; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; - LttvProcessState *child_process; - struct marker_field *f; + guint cpu; + LttTime timestamp; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sched_process_fork") != 0) + return FALSE; + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + timestamp = lttv_event_get_timestamp(event); + /* Skip Parent PID param */ /* Child PID */ - child_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1)); - s->parent.target_pid = child_pid; + child_pid = lttv_event_get_long(event, "child_tid"); + //ts->target_pid = child_pid; /* Child TGID */ - f = lttv_trace_get_hook_field(th, 2); - if (likely(f)) - child_tgid = ltt_event_get_unsigned(e, f); - else - child_tgid = 0; + + child_tgid = 0; /* Mathieu : it seems like the process might have been scheduled in before the * fork, and, in a rare case, might be the current process. This might happen @@ -3112,7 +2938,7 @@ static gboolean process_fork(void *hook_data, void *call_data) if(child_process == NULL) { child_process = lttv_state_create_process(ts, process, cpu, child_pid, child_tgid, - LTTV_STATE_UNNAMED, &s->parent.timestamp); + LTTV_STATE_UNNAMED, ×tamp); } else { /* The process has already been created : due to time imprecision between * multiple CPUs : it has been scheduled in before creation. Note that we @@ -3129,7 +2955,7 @@ static gboolean process_fork(void *hook_data, void *call_data) child_process->creation_time.tv_nsec, child_process->insertion_time.tv_sec, child_process->insertion_time.tv_nsec, - cpu, ltt_event_time(e).tv_sec, ltt_event_time(e).tv_nsec); + cpu, timestamp.tv_sec, timestamp.tv_nsec); //g_assert(0); /* This is a problematic case : the process has been created // before the fork event */ child_process->ppid = process->pid; @@ -3142,6 +2968,8 @@ static gboolean process_fork(void *hook_data, void *call_data) return FALSE; } +#ifdef BABEL_CLEANUP +//NO KTHREAD_CREATE in LTTng 2.0 /* We stamp a newly created process as kernel_thread. * The thread should not be running yet. */ static gboolean process_kernel_thread(void *hook_data, void *call_data) @@ -3156,7 +2984,7 @@ static gboolean process_kernel_thread(void *hook_data, void *call_data) /* PID */ pid = (guint)ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0)); - s->parent.target_pid = pid; + //s->parent.target_pid = pid; process = lttv_state_find_process_or_create(ts, ANY_CPU, pid, <t_time_zero); @@ -3171,18 +2999,25 @@ static gboolean process_kernel_thread(void *hook_data, void *call_data) return FALSE; } - +#endif static gboolean process_exit(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; + LttvEvent *event; + LttvTraceState *ts; guint pid; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; + guint cpu; LttvProcessState *process; // = ts->running_process[cpu]; - pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); - s->parent.target_pid = pid; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sched_process_exit") != 0) + return FALSE; + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + + pid = lttv_event_get_long(event, "tid"); + //s->parent.target_pid = pid; // FIXME : Add this test in the "known state" section // g_assert(process->pid == pid); @@ -3196,24 +3031,32 @@ static gboolean process_exit(void *hook_data, void *call_data) static gboolean process_free(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; + guint cpu; guint release_pid; LttvProcessState *process; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sched_process_free") != 0) + return FALSE; + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + /* PID of the process to release */ - release_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); - s->parent.target_pid = release_pid; + release_pid = lttv_event_get_long(event, "_tid"); + //s->parent.target_pid = release_pid; g_assert(release_pid != 0); process = lttv_state_find_process(ts, ANY_CPU, release_pid); if(likely(process != NULL)) - exit_process(s, process); + exit_process(event, process); return FALSE; //DISABLED +#if 0 if(likely(process != NULL)) { /* release_task is happening at kernel level : we can now safely release * the data structure of the process */ @@ -3241,18 +3084,25 @@ static gboolean process_free(void *hook_data, void *call_data) } return FALSE; +#endif //DISABLED } static gboolean process_exec(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHook *th = (LttvTraceHook *)hook_data; +{ + LttvEvent *event; + LttvTraceState *ts; + guint cpu; //gchar *name; - guint cpu = s->cpu; - LttvProcessState *process = ts->running_process[cpu]; + LttvProcessState *process; + + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "sys_execve") != 0) + return FALSE; + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; #if 0//how to use a sequence that must be transformed in a string /* PID of the process to release */ @@ -3269,13 +3119,13 @@ static gboolean process_exec(void *hook_data, void *call_data) process->name = g_quark_from_string(null_term_name); #endif //0 - process->name = g_quark_from_string(ltt_event_get_string(e, - lttv_trace_get_hook_field(th, 0))); + process->name = g_quark_from_string(lttv_event_get_string(event, + "filename")); process->brand = LTTV_STATE_UNBRANDED; //g_free(null_term_name); return FALSE; } - +#ifdef BABEL_CLEANUP static gboolean thread_brand(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; @@ -3291,7 +3141,10 @@ static gboolean thread_brand(void *hook_data, void *call_data) return FALSE; } - +#endif +#if 0 + // TODO We only have sys_open, without the FD + // manage to do somehting better static gboolean fs_open(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; @@ -3315,7 +3168,7 @@ static gboolean fs_open(void *hook_data, void *call_data) return FALSE; } - +#endif static void print_stack(LttvProcessState *process) { LttvExecutionState *es; @@ -3397,53 +3250,67 @@ static void fix_process(gpointer key, gpointer value, gpointer user_data) static gboolean statedump_end(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvTracefileContext *tfc = (LttvTracefileContext *)call_data; + LttvEvent *event; + LttvTraceState *ts; + LttTime timestamp; //LttEvent *e = ltt_tracefile_get_event(s->parent.tf); //LttvTraceHook *th = (LttvTraceHook *)hook_data; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "lttng_statedump_end") != 0) + return FALSE; + + ts = event->state; + timestamp = lttv_event_get_timestamp(event); /* For all processes */ /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */ /* else, if stack[0] is unknown, set to user mode, running */ - g_hash_table_foreach(ts->processes, fix_process, &tfc->timestamp); + g_hash_table_foreach(ts->processes, fix_process, ×tamp); return FALSE; } static gboolean enum_process_state(void *hook_data, void *call_data) { - LttvTracefileState *s = (LttvTracefileState *)call_data; - LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - //It's slow : optimise later by doing this before reading trace. - LttvTraceHook *th = (LttvTraceHook *)hook_data; + LttvEvent *event; + LttvTraceState *ts; + LttTime timestamp; guint parent_pid; guint pid; guint tgid; gchar * command; - guint cpu = s->cpu; - LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; - LttvProcessState *process = ts->running_process[cpu]; + guint cpu; LttvProcessState *parent_process; - struct marker_field *f; - GQuark type; + LttvProcessState *process; + + guint type; LttvExecutionState *es; guint i, nb_cpus; + event = (LttvEvent *) call_data; + if (strcmp(lttv_traceset_get_name_from_event(event), + "lttng_statedump_process_state") != 0) + return FALSE; + cpu = lttv_traceset_get_cpuid_from_event(event); + ts = event->state; + process = ts->running_process[cpu]; + timestamp = lttv_event_get_timestamp(event); + /* PID */ - pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 0)); - s->parent.target_pid = pid; + pid = lttv_event_get_long(event, "tid"); + //s->parent.target_pid = pid; /* Parent PID */ - parent_pid = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1)); + parent_pid = lttv_event_get_long(event, "ppid"); /* Command name */ - command = ltt_event_get_string(e, lttv_trace_get_hook_field(th, 2)); + command = lttv_event_get_string(event, "name"); /* type */ - f = lttv_trace_get_hook_field(th, 3); - type = ltt_enum_string_get(f, ltt_event_get_unsigned(e, f)); + + type = lttv_event_get_long(event, "type"); //FIXME: type is rarely used, enum must match possible types. @@ -3452,16 +3319,11 @@ static gboolean enum_process_state(void *hook_data, void *call_data) /* Skip submode 5th param */ /* Skip status 6th param */ - /* TGID */ - f = lttv_trace_get_hook_field(th, 7); - if(f) - tgid = ltt_event_get_unsigned(e, f); - else - tgid = 0; - + tgid = lttv_event_get_long(event, "pid"); + if(pid == 0) { - nb_cpus = ltt_trace_get_num_cpu(ts->parent.t); + nb_cpus = lttv_trace_get_num_cpu(ts->trace); for(i=0; iparent.timestamp); + ×tamp); /* Keep the stack bottom : a running user mode */ /* Disabled because of inconsistencies in the current statedump states. */ - if(type == LTTV_STATE_KERNEL_THREAD) { + //if(type == LTTV_STATE_KERNEL_THREAD) { + if(type == 1) { /* Only keep the bottom * FIXME Kernel thread : can be in syscall or interrupt or trap. */ /* Will cause expected trap when in fact being syscall (even after end of @@ -3561,34 +3424,62 @@ static gboolean enum_process_state(void *hook_data, void *call_data) return FALSE; } + + gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data) { - LttvTracesetState *tss = (LttvTracesetState*)(call_data); + LttvTraceset *traceset = (LttvTraceset *)(call_data); - lttv_state_add_event_hooks(tss); + lttv_state_add_event_hooks(traceset); return 0; } -void lttv_state_add_event_hooks(LttvTracesetState *self) +void lttv_state_add_event_hooks(LttvTraceset *traceset) { - LttvTraceset *traceset = self->parent.ts; - - guint i, j, k, nb_trace, nb_tracefile; - + gboolean result; + + LttvAttributeValue value; + LttvHooks*event_hook; +#ifdef BABEL_CLEANUP + LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); + result = lttv_iattribute_find_by_path(attributes, "hooks/event", + LTTV_POINTER, &value); + g_assert(result); + event_hook = *(value.v_pointer); +#endif + //TODO ybrosseau 2012-07-12: Validate that using traceset hooks instead of the global one is valid + //Use traceset hooks + event_hook = lttv_traceset_get_hooks(traceset); + g_assert(event_hook); + + lttv_hooks_add(event_hook,syscall_entry , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,syscall_exit , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,irq_entry , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,irq_exit , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,soft_irq_raise , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,soft_irq_entry , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,soft_irq_exit , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,schedchange , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,sched_try_wakeup , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,process_exit , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,process_free , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,process_fork , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,process_exec , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,enum_process_state , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,statedump_end , NULL, LTTV_PRIO_STATE); + lttv_hooks_add(event_hook,enum_interrupt , NULL, LTTV_PRIO_STATE); + +#ifdef BABEL_CLEANUP //For the whole function this time + guint i, j, k, nb_trace; LttvTraceState *ts; - - LttvTracefileState *tfs; - GArray *hooks; - - LttvTraceHook *th; - + // LttvTraceHook *th; LttvAttributeValue val; nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = (LttvTraceState *)self->parent.traces[i]; + for (i = 0 ; i < nb_trace ; i++) { + ts = lttv_traceset_get(traceset, i)-; /* Find the eventtype id for the following events and register the associated by id hooks. */ @@ -3597,7 +3488,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) //hooks = g_array_set_size(hooks, 19); // Max possible number of hooks. //hn = 0; - lttv_trace_find_hook(ts->parent.t, + lttv_trace_find_hook(tss->parent.t, LTT_CHANNEL_KERNEL, LTT_EVENT_SYSCALL_ENTRY, FIELD_ARRAY(LTT_FIELD_SYSCALL_ID), @@ -3609,6 +3500,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) NULL, syscall_exit, NULL, &hooks); +#ifdef BABEL_CLEANUP lttv_trace_find_hook(ts->parent.t, LTT_CHANNEL_KERNEL, LTT_EVENT_TRAP_ENTRY, @@ -3620,6 +3512,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) LTT_EVENT_TRAP_EXIT, NULL, trap_exit, NULL, &hooks); +#endif /* BABEL_CLEANUP */ lttv_trace_find_hook(ts->parent.t, LTT_CHANNEL_KERNEL, @@ -3633,6 +3526,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) NULL, trap_exit, NULL, &hooks); +#ifdef BABEL_CLEANUP lttv_trace_find_hook(ts->parent.t, LTT_CHANNEL_KERNEL, LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY, @@ -3644,6 +3538,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) LTT_EVENT_PAGE_FAULT_NOSEM_EXIT, NULL, trap_exit, NULL, &hooks); +#endif /* BABEL_CLEANUP */ lttv_trace_find_hook(ts->parent.t, LTT_CHANNEL_KERNEL, @@ -3816,36 +3711,58 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); *(val.v_pointer) = hooks; } +#endif } gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data) { - LttvTracesetState *tss = (LttvTracesetState*)(call_data); - lttv_state_remove_event_hooks(tss); + LttvTraceset *traceset = (LttvTraceset*)(call_data); + + lttv_state_remove_event_hooks(traceset); return 0; } -void lttv_state_remove_event_hooks(LttvTracesetState *self) +void lttv_state_remove_event_hooks(LttvTraceset *traceset) { - LttvTraceset *traceset = self->parent.ts; guint i, j, k, nb_trace, nb_tracefile; - LttvTraceState *ts; + //LttvTraceState *ts; - LttvTracefileState *tfs; + //GArray *hooks; - GArray *hooks; + //LttvTraceHook *th; - LttvTraceHook *th; + //LttvAttributeValue val; + + LttvHooks*event_hook; + //TODO ybrosseau 2012-07-17 validate this. Reversed what's done in the add + event_hook = lttv_traceset_get_hooks(traceset); + + g_assert(event_hook); - LttvAttributeValue val; + lttv_hooks_remove(event_hook,syscall_entry ); + lttv_hooks_remove(event_hook,syscall_exit); + lttv_hooks_remove(event_hook,irq_entry ); + lttv_hooks_remove(event_hook,irq_exit ); + lttv_hooks_remove(event_hook,soft_irq_raise); + lttv_hooks_remove(event_hook,soft_irq_entry); + lttv_hooks_remove(event_hook,soft_irq_exit); + lttv_hooks_remove(event_hook,schedchange); + lttv_hooks_remove(event_hook,sched_try_wakeup); + lttv_hooks_remove(event_hook,process_exit); + lttv_hooks_remove(event_hook,process_free); + lttv_hooks_remove(event_hook,process_exec); + lttv_hooks_remove(event_hook,enum_process_state); + lttv_hooks_remove(event_hook,statedump_end); + lttv_hooks_remove(event_hook,enum_interrupt); +#ifdef BABEL_CLEANUP nb_trace = lttv_traceset_number(traceset); for(i = 0 ; i < nb_trace ; i++) { - ts = LTTV_TRACE_STATE(self->parent.traces[i]); + ts = lttv_traceset_get(i); lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); hooks = *(val.v_pointer); @@ -3871,8 +3788,10 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) lttv_trace_hook_remove_all(&hooks); g_array_free(hooks, TRUE); } +#endif } + static gboolean state_save_event_hook(void *hook_data, void *call_data) { guint *event_count = (guint*)hook_data; @@ -3883,46 +3802,60 @@ static gboolean state_save_event_hook(void *hook_data, void *call_data) else *event_count = 0; - LttvTracefileState *self = (LttvTracefileState *)call_data; + LttvEvent *event = (LttvEvent *)call_data; - LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context); + LttvTraceset *traceset = lttv_trace_get_traceset(event->state->trace); LttvAttribute *saved_states_tree, *saved_state_tree; LttvAttributeValue value; + LttTime currentTime; + guint i; + currentTime = lttv_event_get_timestamp(event); + int nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { - saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, - LTTV_STATE_SAVED_STATES); - saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - value = lttv_attribute_add(saved_states_tree, - lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT); - *(value.v_gobject) = (GObject *)saved_state_tree; - value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME); - *(value.v_time) = self->parent.timestamp; - lttv_state_save(tcs, saved_state_tree); - g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec, - self->parent.timestamp.tv_nsec); + LttvTrace *trace = lttv_traceset_get(traceset, i); + LttvTraceState *tstate = trace->state; + saved_states_tree = lttv_attribute_find_subdir(trace->a, + LTTV_STATE_SAVED_STATES); - *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp; + saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + value = lttv_attribute_add(saved_states_tree, + lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT); + *(value.v_gobject) = (GObject *)saved_state_tree; + + + value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME); + *(value.v_time) = currentTime; + + lttv_state_save(tstate, saved_state_tree); + g_debug("Saving state at time %lu.%lu", currentTime.tv_sec, + currentTime.tv_nsec); + *(tstate->max_time_state_recomputed_in_seek) = currentTime; + } return FALSE; } static gboolean state_save_after_trace_hook(void *hook_data, void *call_data) { - LttvTraceState *tcs = (LttvTraceState *)(call_data); +#warning "Would we move max_time to traceset" + LttvTrace *trace = (LttvTrace *)(call_data); + LttvTraceState *tcs = trace->state; + TimeInterval time_span = lttv_traceset_get_time_span_real(lttv_trace_get_traceset(trace)); - *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time; + *(tcs->max_time_state_recomputed_in_seek) = time_span.end_time; return FALSE; } - +#ifdef BABEL_CLEANUP guint lttv_state_current_cpu(LttvTracefileState *tfs) { return tfs->cpu; } - +#endif //BABEL_CLEANUP #if 0 static gboolean block_start(void *hook_data, void *call_data) @@ -4041,9 +3974,8 @@ void lttv_state_save_add_event_hooks(LttvTracesetState *self) } #endif //0 -void lttv_state_save_add_event_hooks(LttvTracesetState *self) +void lttv_state_save_add_event_hooks(LttvTraceset *traceset) { - LttvTraceset *traceset = self->parent.ts; guint i, j, nb_trace, nb_tracefile; @@ -4051,7 +3983,17 @@ void lttv_state_save_add_event_hooks(LttvTracesetState *self) LttvTracefileState *tfs; - + + if(!traceset->has_precomputed_states) { + guint *event_count = g_new(guint, 1); + + *event_count = 0; + lttv_hooks_add(traceset->event_hooks, + state_save_event_hook, + event_count, + LTTV_PRIO_STATE); + +#ifdef BABEL_CLEANUP nb_trace = lttv_traceset_number(traceset); for(i = 0 ; i < nb_trace ; i++) { @@ -4074,17 +4016,18 @@ void lttv_state_save_add_event_hooks(LttvTracesetState *self) } } - - lttv_process_traceset_begin(&self->parent, - NULL, NULL, NULL, NULL, NULL); +#endif + lttv_process_traceset_begin(traceset, + NULL, NULL, NULL, NULL, NULL); + } } gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data) { - LttvTracesetState *tss = (LttvTracesetState*)(call_data); + LttvTraceset *ts = (LttvTraceset*)(call_data); - lttv_state_save_add_event_hooks(tss); + lttv_state_save_add_event_hooks(ts); return 0; } @@ -4128,9 +4071,8 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self) } #endif //0 -void lttv_state_save_remove_event_hooks(LttvTracesetState *self) +void lttv_state_save_remove_event_hooks(LttvTraceset *traceset) { - LttvTraceset *traceset = self->parent.ts; guint i, j, nb_trace, nb_tracefile; @@ -4139,6 +4081,7 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self) LttvTracefileState *tfs; LttvHooks *after_trace = lttv_hooks_new(); + guint *event_count = NULL; lttv_hooks_add(after_trace, state_save_after_trace_hook, @@ -4146,12 +4089,19 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self) LTTV_PRIO_STATE); - lttv_process_traceset_end(&self->parent, - NULL, after_trace, NULL, NULL, NULL); + lttv_process_traceset_end(traceset, + NULL, after_trace, NULL, NULL); lttv_hooks_destroy(after_trace); - nb_trace = lttv_traceset_number(traceset); + //nb_trace = lttv_traceset_number(traceset); + + event_count = lttv_hooks_remove(traceset->event_hooks, + state_save_event_hook); + + if(event_count) g_free(event_count); + +#ifdef BABEL_CLEANUP for(i = 0 ; i < nb_trace ; i++) { ts = (LttvTraceState *)self->parent.traces[i]; @@ -4170,28 +4120,48 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self) } if(event_count) g_free(event_count); } +#endif } gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data) { - LttvTracesetState *tss = (LttvTracesetState*)(call_data); + LttvTraceset *ts = (LttvTraceset*)(call_data); - lttv_state_save_remove_event_hooks(tss); + lttv_state_save_remove_event_hooks(ts); return 0; } -void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) + +void lttv_state_traceset_seek_time(LttvTraceset *traceset, LttTime t) { - LttvTraceset *traceset = self->parent.ts; + lttv_state_traceset_seek_time_closest(traceset, + t); + lttv_process_traceset_middle(traceset, t, G_MAXUINT, + NULL); +} + +void lttv_state_traceset_seek_position(LttvTraceset *traceset, LttvTracesetPosition *position) +{ + LttTime t = lttv_traceset_position_get_time(position); + + lttv_state_traceset_seek_time_closest(traceset, + t); + lttv_process_traceset_middle(traceset, + ltt_time_infinite, + G_MAXUINT, + position); +} +void lttv_state_traceset_seek_time_closest(LttvTraceset *traceset, LttTime t) +{ guint i, nb_trace; int min_pos, mid_pos, max_pos; guint call_rest = 0; - - LttvTraceState *tcs; + guint resto_start = 0; + guint resto_at = 0; LttvAttributeValue value; @@ -4202,6 +4172,8 @@ void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) gboolean is_named; LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree = NULL; + + LttTime closest_tree_time, restored_time; //g_tree_destroy(self->parent.pqueue); //self->parent.pqueue = g_tree_new(compare_tracefile); @@ -4210,10 +4182,12 @@ void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) nb_trace = lttv_traceset_number(traceset); for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceState *)self->parent.traces[i]; - if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) { - saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, + LttvTrace *trace = lttv_traceset_get(traceset, i); + LttvTraceState *tstate = trace->state; + + if(ltt_time_compare(t, *(tstate->max_time_state_recomputed_in_seek)) < 0) { + saved_states_tree = lttv_attribute_find_subdir(trace->a, LTTV_STATE_SAVED_STATES); min_pos = -1; @@ -4231,6 +4205,7 @@ void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) if(ltt_time_compare(*(value.v_time), t) < 0) { min_pos = mid_pos; closest_tree = saved_state_tree; + closest_tree_time = *(value.v_time); } else max_pos = mid_pos - 1; @@ -4240,26 +4215,65 @@ void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) /* restore the closest earlier saved state */ if(min_pos != -1) { - lttv_state_restore(tcs, closest_tree); - call_rest = 1; + if(ltt_time_compare(restored_time, closest_tree_time) == 0) { + + lttv_state_restore(tstate, closest_tree); + + restored_time = closest_tree_time; + call_rest = 1; + } else { + g_debug("State: restored time mismatch between traces"); + resto_start = 1; + break; + } + } /* There is no saved state, yet we want to have it. Restart at T0 */ else { - restore_init_state(tcs); - lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero); + resto_start = 1; + break; } } /* We want to seek quickly without restoring/updating the state */ else { - restore_init_state(tcs); - lttv_process_trace_seek_time(&(tcs->parent), t); + resto_at = 1; + break; } } - if(!call_rest) g_info("NOT Calling restore"); -} + if(resto_start || resto_at) { + // Restore init state and seek so + for(i = 0 ; i < nb_trace ; i++) { + LttvTrace *trace = lttv_traceset_get(traceset, i); + LttvTraceState *tstate = trace->state; + + restore_init_state(tstate); + } + + // If t > max saved state + if(resto_at) { + lttv_process_traceset_seek_time(traceset, t); + } else if (resto_start) { + // If no saved state + lttv_process_traceset_seek_time(traceset, ltt_time_zero); + } else { + g_assert(FALSE); + } + g_info("NOT Calling restore"); + + } else { + // Seek at checkpoint + lttv_process_traceset_seek_time(traceset, restored_time); + + + } + + +} + +#ifdef BABEL_CLEANUP static void traceset_state_instance_init (GTypeInstance *instance, gpointer g_class) { } @@ -4308,7 +4322,8 @@ GType lttv_traceset_state_get_type(void) return type; } - +#endif +#if BABEL_CLEANUP static void trace_state_instance_init (GTypeInstance *instance, gpointer g_class) { } @@ -4400,8 +4415,8 @@ GType lttv_tracefile_state_get_type(void) return type; } - -static void module_init() +#endif +static void module_init(void) { LTTV_STATE_UNNAMED = g_quark_from_string(""); LTTV_STATE_UNBRANDED = g_quark_from_string(""); @@ -4429,7 +4444,7 @@ static void module_init() LTTV_STATE_PROCESSES = g_quark_from_string("processes"); LTTV_STATE_PROCESS = g_quark_from_string("process"); LTTV_STATE_RUNNING_PROCESS = g_quark_from_string("running_process"); - LTTV_STATE_EVENT = g_quark_from_string("event"); + LTTV_STATE_POSITION = g_quark_from_string("position"); LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states"); LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time"); LTTV_STATE_TIME = g_quark_from_string("time"); @@ -4463,8 +4478,8 @@ static void module_init() LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry"); LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit"); - LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry"); - LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit"); + //LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry"); + //LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit"); LTT_EVENT_PAGE_FAULT_ENTRY = g_quark_from_string("page_fault_entry"); LTT_EVENT_PAGE_FAULT_EXIT = g_quark_from_string("page_fault_exit"); LTT_EVENT_PAGE_FAULT_NOSEM_ENTRY = g_quark_from_string("page_fault_nosem_entry");