X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Flttv%2Fstate.c;h=dee43252eaf4ddd1eb6c3eb838cb07e71c7c9d58;hb=d448fce24840c50fbd998d06a7daa595859df2ff;hp=1fbb627eab96aed27b20a6579934226b9708b4e6;hpb=f4b88a7dd49bfb6b88ea579410d7e4b59faaf73c;p=lttv.git diff --git a/ltt/branches/poly/lttv/lttv/state.c b/ltt/branches/poly/lttv/lttv/state.c index 1fbb627e..dee43252 100644 --- a/ltt/branches/poly/lttv/lttv/state.c +++ b/ltt/branches/poly/lttv/lttv/state.c @@ -174,10 +174,14 @@ restore_init_state(LttvTraceState *self) self->nb_event = 0; /* Seek time to beginning */ - g_tree_destroy(self->parent.ts_context->pqueue); - self->parent.ts_context->pqueue = g_tree_new(compare_tracefile); + // Mathieu : fix : don't seek traceset here : causes inconsistency in seek + // closest. It's the tracecontext job to seek the trace to the beginning + // anyway : the init state might be used at the middle of the trace as well... + //g_tree_destroy(self->parent.ts_context->pqueue); + //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile); - lttv_process_trace_seek_time(&self->parent, ltt_time_zero); + + //lttv_process_trace_seek_time(&self->parent, ltt_time_zero); nb_cpus = ltt_trace_get_num_cpu(self->parent.t); @@ -557,8 +561,8 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) nb_tracefile = self->parent.tracefiles->len; - g_tree_destroy(tsc->pqueue); - tsc->pqueue = g_tree_new(compare_tracefile); + //g_tree_destroy(tsc->pqueue); + //tsc->pqueue = g_tree_new(compare_tracefile); for(i = 0 ; i < nb_tracefile ; i++) { tfcs = @@ -582,6 +586,7 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) g_assert(tfcs->parent.t_context != NULL); LttvTracefileContext *tfc = LTTV_TRACEFILE_CONTEXT(tfcs); + g_tree_remove(tsc->pqueue, tfc); if(ep != NULL) { g_assert(ltt_tracefile_seek_position(tfc->tf, ep) == 0); @@ -883,6 +888,25 @@ free_name_tables(LttvTraceState *tcs) g_free(name_tables); } +#ifdef HASH_TABLE_DEBUG + +static void test_process(gpointer key, gpointer value, gpointer user_data) +{ + LttvProcessState *process = (LttvProcessState *)value; + + /* Test for process corruption */ + guint stack_len = process->execution_stack->len; +} + +static void hash_table_check(GHashTable *table) +{ + g_hash_table_foreach(table, test_process, NULL); +} + + +#endif + + static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, guint state_id) { @@ -890,6 +914,10 @@ static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, guint cpu = ltt_tracefile_num(tfs->parent.tf); LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; + +#ifdef HASH_TABLE_DEBUG + hash_table_check(ts->processes); +#endif LttvProcessState *process = ts->running_process[cpu]; guint depth = process->execution_stack->len; @@ -1211,6 +1239,7 @@ static gboolean process_fork(void *hook_data, void *call_data) guint cpu = ltt_tracefile_num(s->parent.tf); LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; LttvProcessState *process = ts->running_process[cpu]; + LttvProcessState *child_process; /* Parent PID */ f = thf->f1; @@ -1220,18 +1249,40 @@ static gboolean process_fork(void *hook_data, void *call_data) f = thf->f2; child_pid = ltt_event_get_unsigned(e, f); + /* 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 + * in a SMP case where we don't have enough precision on the clocks */ +#if 0 zombie_process = lttv_state_find_process(ts, ANY_CPU, child_pid); if(unlikely(zombie_process != NULL)) { /* Reutilisation of PID. Only now we are sure that the old PID * has been released. FIXME : should know when release_task happens instead. */ + guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t); + guint i; + for(i=0; i< num_cpus; i++) { + g_assert(process != ts->running_process[i]); + } + exit_process(s, zombie_process); } +#endif //0 g_assert(process->pid != child_pid); // FIXME : Add this test in the "known state" section // g_assert(process->pid == parent_pid); - lttv_state_create_process(ts, process, cpu, child_pid, &s->parent.timestamp); + child_process = lttv_state_find_process(ts, ANY_CPU, child_pid); + if(child_process == NULL) { + lttv_state_create_process(ts, process, cpu, + child_pid, &s->parent.timestamp); + } else { + /* The process has already been created : due to time imprecision between + * multiple CPUs : it has been scheduled in before creation. + * + * Simply put a correct parent. + */ + child_process->ppid = process->pid; + } return FALSE; } @@ -1270,12 +1321,19 @@ static gboolean process_free(void *hook_data, void *call_data) /* PID of the process to release */ release_pid = ltt_event_get_unsigned(e, thf->f1); + + g_assert(release_pid != 0); process = lttv_state_find_process(ts, ANY_CPU, release_pid); if(likely(process != NULL)) { /* release_task is happening at kernel level : we can now safely release * the data structure of the process */ + guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t); + guint i; + for(i=0; i< num_cpus; i++) { + g_assert(process != ts->running_process[i]); + } exit_process(s, process); } @@ -1446,7 +1504,6 @@ gint lttv_state_hook_remove_event_hooks(void *hook_data, void *call_data) return 0; } -static guint test_event_count = 0; void lttv_state_remove_event_hooks(LttvTracesetState *self) { LttvTraceset *traceset = self->parent.ts; @@ -1496,14 +1553,12 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k)); g_array_free(hooks, TRUE); } - g_info("EVENT COUNT TEST : %u", test_event_count); } static gboolean state_save_event_hook(void *hook_data, void *call_data) { guint *event_count = (guint*)hook_data; - test_event_count++; /* Only save at LTTV_STATE_SAVE_INTERVAL */ if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL)) return FALSE; @@ -1543,6 +1598,15 @@ static gboolean state_save_event_hook(void *hook_data, void *call_data) return FALSE; } +static gboolean state_save_after_trace_hook(void *hook_data, void *call_data) +{ + LttvTraceState *tcs = (LttvTraceState *)(call_data); + + *(tcs->max_time_state_recomputed_in_seek) = tcs->parent.time_span.end_time; + + return FALSE; +} + #if 0 static gboolean block_start(void *hook_data, void *call_data) { @@ -1691,6 +1755,10 @@ void lttv_state_save_add_event_hooks(LttvTracesetState *self) } } + + lttv_process_traceset_begin(&self->parent, + NULL, NULL, NULL, NULL, NULL); + } gint lttv_state_save_hook_add_event_hooks(void *hook_data, void *call_data) @@ -1751,7 +1819,19 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self) LttvTracefileState *tfs; + LttvHooks *after_trace = lttv_hooks_new(); + + lttv_hooks_add(after_trace, + state_save_after_trace_hook, + NULL, + LTTV_PRIO_STATE); + + + lttv_process_traceset_end(&self->parent, + NULL, after_trace, NULL, NULL, NULL); + lttv_hooks_destroy(after_trace); + nb_trace = lttv_traceset_number(traceset); for(i = 0 ; i < nb_trace ; i++) { @@ -1766,7 +1846,6 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self) LttvTracefileContext*, j)); event_count = lttv_hooks_remove(tfs->parent.event, state_save_event_hook); - } g_free(event_count); } @@ -1801,8 +1880,8 @@ void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree; - g_tree_destroy(self->parent.pqueue); - self->parent.pqueue = g_tree_new(compare_tracefile); + //g_tree_destroy(self->parent.pqueue); + //self->parent.pqueue = g_tree_new(compare_tracefile); g_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec);