X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Flttv%2Fstate.c;h=c06ba340e25fa77d7bfc97002f3e2de001f8c070;hb=26275aa2f3a7de1a352f4dcbf7f6e8bebd6951bf;hp=e8eb3db4c74b578f58322f88d9301df5e5ed1896;hpb=eed2ef37f908daf7b3f884b5d8f91dad03f10526;p=lttv.git diff --git a/ltt/branches/poly/lttv/lttv/state.c b/ltt/branches/poly/lttv/lttv/state.c index e8eb3db4..c06ba340 100644 --- a/ltt/branches/poly/lttv/lttv/state.c +++ b/ltt/branches/poly/lttv/lttv/state.c @@ -35,7 +35,8 @@ GQuark LTT_FACILITY_KERNEL, - LTT_FACILITY_PROCESS; + LTT_FACILITY_PROCESS, + LTT_FACILITY_FS; /* Events Quarks */ @@ -49,7 +50,8 @@ GQuark LTT_EVENT_SCHEDCHANGE, LTT_EVENT_FORK, LTT_EVENT_EXIT, - LTT_EVENT_FREE; + LTT_EVENT_FREE, + LTT_EVENT_EXEC; /* Fields Quarks */ @@ -62,7 +64,8 @@ GQuark LTT_FIELD_OUT_STATE, LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, - LTT_FIELD_PID; + LTT_FIELD_PID, + LTT_FIELD_FILENAME; LttvExecutionMode LTTV_STATE_MODE_UNKNOWN, @@ -88,6 +91,7 @@ static GQuark LTTV_STATE_TRACEFILES, LTTV_STATE_PROCESSES, LTTV_STATE_PROCESS, + LTTV_STATE_RUNNING_PROCESS, LTTV_STATE_EVENT, LTTV_STATE_SAVED_STATES, LTTV_STATE_SAVED_STATES_TIME, @@ -151,7 +155,7 @@ gboolean process_equal(gconstpointer a, gconstpointer b) if(likely(process_a->pid != process_b->pid)) ret = FALSE; else if(likely(process_a->pid == 0 && - process_a->last_cpu != process_b->last_cpu)) ret = FALSE; + process_a->cpu != process_b->cpu)) ret = FALSE; return ret; } @@ -160,30 +164,53 @@ gboolean process_equal(gconstpointer a, gconstpointer b) static void restore_init_state(LttvTraceState *self) { - guint i, nb_tracefile; + guint i, nb_cpus; LttvTracefileState *tfcs; + /* Free the process tables */ if(self->processes != NULL) lttv_state_free_process_table(self->processes); self->processes = g_hash_table_new(process_hash, process_equal); self->nb_event = 0; + /* Seek time to beginning */ + // 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); + + nb_cpus = ltt_trace_get_num_cpu(self->parent.t); + + /* Put the per cpu running_process to beginning state : process 0. */ + for(i=0; i< nb_cpus; i++) { + self->running_process[i] = lttv_state_create_process(self, NULL, i, 0, + <t_time_zero); + self->running_process[i]->state->s = LTTV_STATE_RUN; + self->running_process[i]->cpu = i; + } + +#if 0 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)); + LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, + LttvTracefileContext*, i)); ltt_trace_time_span_get(self->parent.t, &tfcs->parent.timestamp, NULL); // tfcs->saved_position = 0; tfcs->process = lttv_state_create_process(tfcs, NULL,0); tfcs->process->state->s = LTTV_STATE_RUN; tfcs->process->last_cpu = tfcs->cpu_name; - tfcs->process->last_cpu_index = ((LttvTracefileContext*)tfcs)->index; + tfcs->process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfcs)->tf); } +#endif //0 } -static LttTime time_zero = {0,0}; +//static LttTime time_zero = {0,0}; static void init(LttvTracesetState *self, LttvTraceset *ts) @@ -204,7 +231,7 @@ init(LttvTracesetState *self, LttvTraceset *ts) nb_trace = lttv_traceset_number(ts); for(i = 0 ; i < nb_trace ; i++) { tc = self->parent.traces[i]; - tcs = (LttvTraceState *)tc; + 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); @@ -218,14 +245,17 @@ init(LttvTracesetState *self, LttvTraceset *ts) get_max_time(tcs); nb_tracefile = tc->tracefiles->len; - +#if 0 for(j = 0 ; j < nb_tracefile ; j++) { tfcs = - LTTV_TRACEFILE_STATE(&g_array_index(tc->tracefiles, - LttvTracefileContext, j)); - tfcs->cpu_name = ltt_tracefile_name(tfcs->parent.tf); + LTTV_TRACEFILE_STATE(g_array_index(tc->tracefiles, + LttvTracefileContext*, j)); + tfcs->tracefile_name = ltt_tracefile_name(tfcs->parent.tf); } +#endif //0 tcs->processes = NULL; + tcs->running_process = g_new(LttvProcessState*, + ltt_trace_get_num_cpu(tc->t)); restore_init_state(tcs); } } @@ -256,6 +286,8 @@ fini(LttvTracesetState *self) free_max_time(tcs); free_saved_state(tcs); } + g_free(tcs->running_process); + tcs->running_process = NULL; lttv_state_free_process_table(tcs->processes); tcs->processes = NULL; } @@ -300,10 +332,10 @@ static void write_process_state(gpointer key, gpointer value, process = (LttvProcessState *)value; fprintf(fp, -" \n", +" \n", process, process->pid, process->ppid, process->creation_time.tv_sec, process->creation_time.tv_nsec, g_quark_to_string(process->name), - g_quark_to_string(process->last_cpu)); + process->cpu); for(i = 0 ; i < process->execution_stack->len; i++) { es = &g_array_index(process->execution_stack, LttvExecutionState, i); @@ -328,27 +360,35 @@ void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp) LttEventPosition *ep; + guint nb_cpus; + ep = ltt_event_position_new(); fprintf(fp,"\n", t.tv_sec, t.tv_nsec); g_hash_table_foreach(self->processes, write_process_state, fp); + + nb_cpus = ltt_trace_get_num_cpu(self->parent.t); + for(i=0;i\n", + i, self->running_process[i]->pid); + } 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)); - fprintf(fp, " process->pid, tfcs->parent.timestamp.tv_sec, + LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, + LttvTracefileContext*, i)); + fprintf(fp, " parent.timestamp.tv_sec, tfcs->parent.timestamp.tv_nsec); LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf); if(e == NULL) fprintf(fp,"/>\n"); else { ltt_event_position(e, ep); ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc); - fprintf(fp, " BLOCK=%lu OFFSET=%lu TSC=%llu/>\n", nb_block, offset, + fprintf(fp, " BLOCK=%u OFFSET=%u TSC=%llu/>\n", nb_block, offset, tsc); } } @@ -372,7 +412,9 @@ static void copy_process_state(gpointer key, gpointer value,gpointer user_data) *new_process = *process; new_process->execution_stack = g_array_sized_new(FALSE, FALSE, sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK); - g_array_set_size(new_process->execution_stack,process->execution_stack->len); + new_process->execution_stack = + g_array_set_size(new_process->execution_stack, + process->execution_stack->len); for(i = 0 ; i < process->execution_stack->len; i++) { g_array_index(new_process->execution_stack, LttvExecutionState, i) = g_array_index(process->execution_stack, LttvExecutionState, i); @@ -400,11 +442,13 @@ static GHashTable *lttv_state_copy_process_table(GHashTable *processes) static void state_save(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile; + guint i, nb_tracefile, nb_cpus; LttvTracefileState *tfcs; LttvAttribute *tracefiles_tree, *tracefile_tree; + + guint *running_process; LttvAttributeType type; @@ -421,24 +465,42 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) 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); + running_process = g_new(guint, nb_cpus); + for(i=0;irunning_process[i]->pid; + } + value = lttv_attribute_add(container, LTTV_STATE_RUNNING_PROCESS, + LTTV_POINTER); + *(value.v_pointer) = running_process; + + g_info("State save"); + 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)); + LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, + LttvTracefileContext*, i)); tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); value = lttv_attribute_add(tracefiles_tree, i, LTTV_GOBJECT); *(value.v_gobject) = (GObject *)tracefile_tree; +#if 0 value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS, LTTV_UINT); *(value.v_uint) = tfcs->process->pid; +#endif //0 value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT, LTTV_POINTER); - LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf); - if(e == NULL) *(value.v_pointer) = NULL; - else { + /* Only save the position if the tfs has not infinite time. */ + //if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent) + // && current_tfcs != tfcs) { + if(ltt_time_compare(tfcs->parent.timestamp, ltt_time_infinite) == 0) { + *(value.v_pointer) = NULL; + } else { + LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf); ep = ltt_event_position_new(); ltt_event_position(e, ep); *(value.v_pointer) = ep; @@ -447,7 +509,7 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) guint64 tsc; LttTracefile *tf; ltt_event_position_get(ep, &tf, &nb_block, &offset, &tsc); - g_debug("Block %lu offset %lu tsc %llu time %lu.%lu", nb_block, offset, + g_info("Block %u offset %u tsc %llu time %lu.%lu", nb_block, offset, tsc, tfcs->parent.timestamp.tv_sec, tfcs->parent.timestamp.tv_nsec); } @@ -457,12 +519,14 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) static void state_restore(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile, pid; + guint i, nb_tracefile, pid, nb_cpus; LttvTracefileState *tfcs; LttvAttribute *tracefiles_tree, *tracefile_tree; + guint *running_process; + LttvAttributeType type; LttvAttributeValue value; @@ -471,6 +535,8 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) LttEventPosition *ep; + LttvTracesetContext *tsc = self->parent.ts_context; + tracefiles_tree = lttv_attribute_find_subdir(container, LTTV_STATE_TRACEFILES); @@ -480,41 +546,70 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) lttv_state_free_process_table(self->processes); 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); + type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS, + &value); + g_assert(type == LTTV_POINTER); + running_process = *(value.v_pointer); + for(i=0;irunning_process[i] = lttv_state_find_process(self, i, pid); + g_assert(self->running_process[i] != NULL); + } + + nb_tracefile = self->parent.tracefiles->len; + g_tree_destroy(tsc->pqueue); + tsc->pqueue = g_tree_new(compare_tracefile); + for(i = 0 ; i < nb_tracefile ; i++) { tfcs = - LTTV_TRACEFILE_STATE(&g_array_index(self->parent.tracefiles, - LttvTracefileContext, i)); + LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, + LttvTracefileContext*, i)); type = lttv_attribute_get(tracefiles_tree, i, &name, &value); g_assert(type == LTTV_GOBJECT); tracefile_tree = *((LttvAttribute **)(value.v_gobject)); - +#if 0 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS, &value); g_assert(type == LTTV_UINT); pid = *(value.v_uint); tfcs->process = lttv_state_find_process_or_create(tfcs, pid); - +#endif //0 type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, &value); g_assert(type == LTTV_POINTER); - g_assert(*(value.v_pointer) != NULL); + //g_assert(*(value.v_pointer) != NULL); ep = *(value.v_pointer); g_assert(tfcs->parent.t_context != NULL); - lttv_process_tracefile_seek_position(LTTV_TRACEFILE_CONTEXT(tfcs), ep); + + LttvTracefileContext *tfc = LTTV_TRACEFILE_CONTEXT(tfcs); + + if(ep != NULL) { + g_assert(ltt_tracefile_seek_position(tfc->tf, ep) == 0); + tfc->timestamp = ltt_event_time(ltt_tracefile_get_event(tfc->tf)); + g_assert(ltt_time_compare(tfc->timestamp, ltt_time_infinite) != 0); + g_tree_insert(tsc->pqueue, tfc, tfc); + g_info("Restoring state for a tf at time %lu.%lu", tfc->timestamp.tv_sec, tfc->timestamp.tv_nsec); + } else { + tfc->timestamp = ltt_time_infinite; + } } } static void state_saved_free(LttvTraceState *self, LttvAttribute *container) { - guint i, nb_tracefile; + guint i, nb_tracefile, nb_cpus; LttvTracefileState *tfcs; LttvAttribute *tracefiles_tree, *tracefile_tree; + guint *running_process; + LttvAttributeType type; LttvAttributeValue value; @@ -535,12 +630,20 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) *(value.v_pointer) = NULL; lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES); + /* Free running processes array */ + nb_cpus = ltt_trace_get_num_cpu(self->parent.t); + type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS, + &value); + g_assert(type == LTTV_POINTER); + running_process = *(value.v_pointer); + g_free(running_process); + 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)); + LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, + LttvTracefileContext*, i)); type = lttv_attribute_get(tracefiles_tree, i, &name, &value); g_assert(type == LTTV_GOBJECT); tracefile_tree = *((LttvAttribute **)(value.v_gobject)); @@ -589,7 +692,7 @@ create_max_time(LttvTraceState *tcs) LTTV_POINTER, &v); g_assert(*(v.v_pointer) == NULL); *(v.v_pointer) = g_new(LttTime,1); - *((LttTime *)*(v.v_pointer)) = time_zero; + *((LttTime *)*(v.v_pointer)) = ltt_time_zero; } @@ -632,7 +735,7 @@ create_name_tables(LttvTraceState *tcs) GQuark f_name, e_name; - LttvTraceHook *h; + LttvTraceHook h; LttvTraceHookByFacility *thf; @@ -665,15 +768,15 @@ create_name_tables(LttvTraceState *tcs) if(lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY, LTT_FIELD_SYSCALL_ID, 0, 0, - NULL, h)) + NULL, NULL, &h)) return; - thf = lttv_trace_hook_get_first(h); + thf = lttv_trace_hook_get_first(&h); t = ltt_field_type(thf->f1); nb = ltt_type_element_number(t); - lttv_trace_hook_destroy(h); + lttv_trace_hook_destroy(&h); /* CHECK syscalls should be an enum but currently are not! name_tables->syscall_names = g_new(GQuark, nb); @@ -693,15 +796,15 @@ create_name_tables(LttvTraceState *tcs) if(lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY, LTT_FIELD_TRAP_ID, 0, 0, - NULL, h)) + NULL, NULL, &h)) return; - thf = lttv_trace_hook_get_first(h); + thf = lttv_trace_hook_get_first(&h); t = ltt_field_type(thf->f1); nb = ltt_type_element_number(t); - lttv_trace_hook_destroy(h); + lttv_trace_hook_destroy(&h); /* name_tables->trap_names = g_new(GQuark, nb); @@ -720,15 +823,15 @@ create_name_tables(LttvTraceState *tcs) if(lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY, LTT_FIELD_IRQ_ID, 0, 0, - NULL, h)) + NULL, NULL, &h)) return; - thf = lttv_trace_hook_get_first(h); + thf = lttv_trace_hook_get_first(&h); t = ltt_field_type(thf->f1); nb = ltt_type_element_number(t); - lttv_trace_hook_destroy(h); + lttv_trace_hook_destroy(&h); /* name_tables->irq_names = g_new(GQuark, nb); @@ -784,17 +887,46 @@ 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) { LttvExecutionState *es; + + guint cpu = ltt_tracefile_num(tfs->parent.tf); + LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; - LttvProcessState *process = tfs->process; +#ifdef HASH_TABLE_DEBUG + hash_table_check(ts->processes); +#endif + LttvProcessState *process = ts->running_process[cpu]; guint depth = process->execution_stack->len; - g_array_set_size(process->execution_stack, depth + 1); + process->execution_stack = + g_array_set_size(process->execution_stack, depth + 1); + /* Keep in sync */ + process->state = + &g_array_index(process->execution_stack, LttvExecutionState, depth - 1); + es = &g_array_index(process->execution_stack, LttvExecutionState, depth); es->t = t; es->n = state_id; @@ -806,7 +938,9 @@ static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) { - LttvProcessState *process = tfs->process; + guint cpu = ltt_tracefile_num(tfs->parent.tf); + LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context; + LttvProcessState *process = ts->running_process[cpu]; guint depth = process->execution_stack->len; @@ -830,7 +964,8 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) return; } - g_array_set_size(process->execution_stack, depth - 1); + process->execution_stack = + 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; @@ -838,32 +973,28 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) LttvProcessState * -lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent, - guint pid) +lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent, + guint cpu, guint pid, const LttTime *timestamp) { LttvProcessState *process = g_new(LttvProcessState, 1); LttvExecutionState *es; - LttvTraceContext *tc; - - LttvTraceState *tcs; + LttvTraceContext *tc = (LttvTraceContext*)tcs; char buffer[128]; - tc = tfs->parent.t_context; - tcs = (LttvTraceState *)tc; - process->pid = pid; - process->last_cpu = tfs->cpu_name; - process->last_cpu_index = ((LttvTracefileContext*)tfs)->index; - g_warning("Process %u, core %p", process->pid, process); + process->cpu = cpu; + //process->last_cpu = tfs->cpu_name; + //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf); + g_info("Process %u, core %p", process->pid, process); g_hash_table_insert(tcs->processes, process, process); if(parent) { process->ppid = parent->pid; process->name = parent->name; - process->creation_time = tfs->parent.timestamp; + process->creation_time = *timestamp; } /* No parent. This process exists but we are missing all information about @@ -876,47 +1007,49 @@ lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent, process->creation_time = ltt_time_zero; } - process->insertion_time = tfs->parent.timestamp; + process->insertion_time = *timestamp; sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec, process->creation_time.tv_nsec); process->pid_time = g_quark_from_string(buffer); - process->last_cpu = tfs->cpu_name; - process->last_cpu_index = ((LttvTracefileContext*)tfs)->index; + process->cpu = cpu; + //process->last_cpu = tfs->cpu_name; + //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf); process->execution_stack = g_array_sized_new(FALSE, FALSE, sizeof(LttvExecutionState), PREALLOCATED_EXECUTION_STACK); - g_array_set_size(process->execution_stack, 1); + 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_USER_MODE; es->n = LTTV_STATE_SUBMODE_NONE; - es->entry = tfs->parent.timestamp; - g_assert(tfs->parent.timestamp.tv_sec != 0); - es->change = tfs->parent.timestamp; + es->entry = *timestamp; + //g_assert(timestamp->tv_sec != 0); + es->change = *timestamp; es->s = LTTV_STATE_WAIT_FORK; return process; } -LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs, +LttvProcessState *lttv_state_find_process(LttvTraceState *ts, guint cpu, guint pid) { LttvProcessState key; LttvProcessState *process; - LttvTraceState* ts = (LttvTraceState*)tfs->parent.t_context; - key.pid = pid; - key.last_cpu = tfs->cpu_name; + key.cpu = cpu; process = g_hash_table_lookup(ts->processes, &key); return process; } LttvProcessState * -lttv_state_find_process_or_create(LttvTracefileState *tfs, guint pid) +lttv_state_find_process_or_create(LttvTraceState *ts, guint cpu, guint pid, + LttTime *timestamp) { - LttvProcessState *process = lttv_state_find_process(tfs, pid); - - if(unlikely(process == NULL)) process = lttv_state_create_process(tfs, NULL, pid); + LttvProcessState *process = lttv_state_find_process(ts, cpu, pid); + + /* Put ltt_time_zero creation time for unexisting processes */ + if(unlikely(process == NULL)) process = lttv_state_create_process(ts, + NULL, cpu, pid, timestamp); return process; } @@ -933,7 +1066,7 @@ static void exit_process(LttvTracefileState *tfs, LttvProcessState *process) LttvProcessState key; key.pid = process->pid; - key.last_cpu = process->last_cpu; + key.cpu = process->cpu; g_hash_table_remove(ts->processes, &key); g_array_free(process->execution_stack, TRUE); g_free(process); @@ -958,9 +1091,7 @@ static gboolean syscall_entry(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHookByFacility *thf = - lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, - ltt_event_facility_id(e)); + LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data; LttField *f = thf->f1; LttvExecutionSubmode submode; @@ -985,9 +1116,7 @@ static gboolean trap_entry(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHookByFacility *thf = - lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, - ltt_event_facility_id(e)); + LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data; LttField *f = thf->f1; LttvExecutionSubmode submode; @@ -1012,9 +1141,12 @@ static gboolean irq_entry(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHookByFacility *thf = - lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, - ltt_event_facility_id(e)); + guint8 fac_id = ltt_event_facility_id(e); + guint8 ev_id = ltt_event_eventtype_id(e); + LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data; + // g_assert(lttv_trace_hook_get_first((LttvTraceHook *)hook_data)->f1 != NULL); + g_assert(thf->f1 != NULL); + // g_assert(thf == lttv_trace_hook_get_first((LttvTraceHook *)hook_data)); LttField *f = thf->f1; LttvExecutionSubmode submode; @@ -1040,17 +1172,20 @@ static gboolean irq_exit(void *hook_data, void *call_data) static gboolean schedchange(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; + guint cpu = ltt_tracefile_num(s->parent.tf); + LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; + LttvProcessState *process = ts->running_process[cpu]; + LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHookByFacility *thf = - lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, - ltt_event_facility_id(e)); - guint pid_in, pid_out, state_out; + LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data; + guint pid_in, pid_out; + gint state_out; pid_out = ltt_event_get_unsigned(e, thf->f1); pid_in = ltt_event_get_unsigned(e, thf->f2); - state_out = ltt_event_get_unsigned(e, thf->f3); - - if(likely(s->process != NULL)) { + state_out = ltt_event_get_int(e, thf->f3); + + if(likely(process != NULL)) { /* We could not know but it was not the idle process executing. This should only happen at the beginning, before the first schedule @@ -1058,30 +1193,36 @@ static gboolean schedchange(void *hook_data, void *call_data) is missing. It is not obvious how we could, after the fact, compensate the wrongly attributed statistics. */ - if(unlikely(s->process->pid != pid_out)) { - g_assert(s->process->pid == 0); - } + //This test only makes sense once the state is known and if there is no + //missing events. + //if(unlikely(process->pid != pid_out)) { + // g_assert(process->pid == 0); + //} - if(unlikely(s->process->state->s == LTTV_STATE_EXIT)) { - s->process->state->s = LTTV_STATE_ZOMBIE; + if(unlikely(process->state->s == LTTV_STATE_EXIT)) { + process->state->s = LTTV_STATE_ZOMBIE; } else { - if(unlikely(state_out == 0)) s->process->state->s = LTTV_STATE_WAIT_CPU; - else s->process->state->s = LTTV_STATE_WAIT; + if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU; + else process->state->s = LTTV_STATE_WAIT; } /* FIXME : we do not remove process here, because the kernel * still has them : they may be zombies. We need to know * exactly when release_task is executed on the PID to * know when the zombie is destroyed. */ //else - // exit_process(s, s->process); + // exit_process(s, process); - s->process->state->change = s->parent.timestamp; + process->state->change = s->parent.timestamp; } - s->process = lttv_state_find_process_or_create(s, pid_in); - s->process->state->s = LTTV_STATE_RUN; - s->process->last_cpu = s->cpu_name; - s->process->last_cpu_index = ((LttvTracefileContext*)s)->index; - s->process->state->change = s->parent.timestamp; + process = ts->running_process[cpu] = + lttv_state_find_process_or_create( + (LttvTraceState*)s->parent.t_context, + cpu, pid_in, + &s->parent.timestamp); + process->state->s = LTTV_STATE_RUN; + process->cpu = cpu; + // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf); + process->state->change = s->parent.timestamp; return FALSE; } @@ -1089,13 +1230,15 @@ static gboolean process_fork(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHookByFacility *thf = - lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, - ltt_event_facility_id(e)); + LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data; LttField *f; guint parent_pid; guint child_pid; LttvProcessState *zombie_process; + 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; @@ -1105,18 +1248,40 @@ static gboolean process_fork(void *hook_data, void *call_data) f = thf->f2; child_pid = ltt_event_get_unsigned(e, f); - zombie_process = lttv_state_find_process(s, child_pid); + /* 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); } - g_assert(s->process->pid != child_pid); +#endif //0 + g_assert(process->pid != child_pid); // FIXME : Add this test in the "known state" section - // g_assert(s->process->pid == parent_pid); - lttv_state_create_process(s, s->process, child_pid); + // g_assert(process->pid == parent_pid); + 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; } @@ -1126,19 +1291,20 @@ static gboolean process_exit(void *hook_data, void *call_data) { LttvTracefileState *s = (LttvTracefileState *)call_data; LttEvent *e = ltt_tracefile_get_event(s->parent.tf); - LttvTraceHookByFacility *thf = - lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, - ltt_event_facility_id(e)); + LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data; LttField *f; guint pid; + guint cpu = ltt_tracefile_num(s->parent.tf); + LttvTraceState *ts = (LttvTraceState*)s->parent.t_context; + LttvProcessState *process = ts->running_process[cpu]; pid = ltt_event_get_unsigned(e, thf->f1); // FIXME : Add this test in the "known state" section - // g_assert(s->process->pid == pid); + // g_assert(process->pid == pid); - if(likely(s->process != NULL)) { - s->process->state->s = LTTV_STATE_EXIT; + if(likely(process != NULL)) { + process->state->s = LTTV_STATE_EXIT; } return FALSE; } @@ -1146,27 +1312,55 @@ 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); - LttvTraceHookByFacility *thf = - lttv_trace_hook_get_fac((LttvTraceHook *)hook_data, - ltt_event_facility_id(e)); + LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data; guint release_pid; LttvProcessState *process; /* 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(s, release_pid); + 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); } return FALSE; } + +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); + LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data; + gchar *name; + guint cpu = ltt_tracefile_num(s->parent.tf); + LttvProcessState *process = ts->running_process[cpu]; + + /* PID of the process to release */ + name = ltt_event_get_string(e, thf->f1); + + process->name = g_quark_from_string(name); + + return FALSE; +} + + + + gint lttv_state_hook_add_event_hooks(void *hook_data, void *call_data) { LttvTracesetState *tss = (LttvTracesetState*)(call_data); @@ -1194,6 +1388,8 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) LttvAttributeValue val; + gint ret; + nb_trace = lttv_traceset_number(traceset); for(i = 0 ; i < nb_trace ; i++) { ts = (LttvTraceState *)self->parent.traces[i]; @@ -1201,58 +1397,75 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) /* Find the eventtype id for the following events and register the associated by id hooks. */ - hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 10); - g_array_set_size(hooks, 10); + hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 11); + hooks = g_array_set_size(hooks, 11); - lttv_trace_find_hook(ts->parent.t, + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY, LTT_FIELD_SYSCALL_ID, 0, 0, - syscall_entry, &g_array_index(hooks, LttvTraceHook, 0)); + syscall_entry, NULL, &g_array_index(hooks, LttvTraceHook, 0)); + g_assert(!ret); - lttv_trace_find_hook(ts->parent.t, + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT, 0, 0, 0, - syscall_exit, &g_array_index(hooks, LttvTraceHook, 1)); + syscall_exit, NULL, &g_array_index(hooks, LttvTraceHook, 1)); + g_assert(!ret); - lttv_trace_find_hook(ts->parent.t, + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY, LTT_FIELD_TRAP_ID, 0, 0, - trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); + trap_entry, NULL, &g_array_index(hooks, LttvTraceHook, 2)); + g_assert(!ret); - lttv_trace_find_hook(ts->parent.t, + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT, 0, 0, 0, - trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); + trap_exit, NULL, &g_array_index(hooks, LttvTraceHook, 3)); + g_assert(!ret); - lttv_trace_find_hook(ts->parent.t, + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY, LTT_FIELD_IRQ_ID, 0, 0, - irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); + irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, 4)); + g_assert(!ret); - lttv_trace_find_hook(ts->parent.t, + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT, 0, 0, 0, - irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); + irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, 5)); + g_assert(!ret); - lttv_trace_find_hook(ts->parent.t, + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE, LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE, - schedchange, &g_array_index(hooks, LttvTraceHook, 6)); + schedchange, NULL, &g_array_index(hooks, LttvTraceHook, 6)); + g_assert(!ret); - lttv_trace_find_hook(ts->parent.t, + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_PROCESS, LTT_EVENT_FORK, LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0, - process_fork, &g_array_index(hooks, LttvTraceHook, 7)); + process_fork, NULL, &g_array_index(hooks, LttvTraceHook, 7)); + g_assert(!ret); - lttv_trace_find_hook(ts->parent.t, + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_PROCESS, LTT_EVENT_EXIT, LTT_FIELD_PID, 0, 0, - process_exit, &g_array_index(hooks, LttvTraceHook, 8)); + process_exit, NULL, &g_array_index(hooks, LttvTraceHook, 8)); + g_assert(!ret); - lttv_trace_find_hook(ts->parent.t, + ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_PROCESS, LTT_EVENT_FREE, LTT_FIELD_PID, 0, 0, - process_free, &g_array_index(hooks, LttvTraceHook, 9)); + process_free, NULL, &g_array_index(hooks, LttvTraceHook, 9)); + g_assert(!ret); + + ret = lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_FS, LTT_EVENT_EXEC, + LTT_FIELD_FILENAME, 0, 0, + process_exec, NULL, &g_array_index(hooks, LttvTraceHook, 10)); + g_assert(!ret); + /* Add these hooks to each event_by_id hooks list */ @@ -1261,8 +1474,8 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) for(j = 0 ; j < nb_tracefile ; j++) { tfs = - LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles, - LttvTracefileContext, j)); + LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles, + LttvTracefileContext*, j)); for(k = 0 ; k < hooks->len ; k++) { hook = &g_array_index(hooks, LttvTraceHook, k); @@ -1271,7 +1484,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) lttv_hooks_add( lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id), thf->h, - &g_array_index(hooks, LttvTraceHook, k), + thf, LTTV_PRIO_STATE); } } @@ -1320,8 +1533,8 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) for(j = 0 ; j < nb_tracefile ; j++) { tfs = - LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles, - LttvTracefileContext, j)); + LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles, + LttvTracefileContext*, j)); for(k = 0 ; k < hooks->len ; k++) { hook = &g_array_index(hooks, LttvTraceHook, k); @@ -1331,16 +1544,16 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) lttv_hooks_remove_data( lttv_hooks_by_id_find(tfs->parent.event_by_id, thf->id), thf->h, - &g_array_index(hooks, LttvTraceHook, k)); + thf); } - lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k)); } } + for(k = 0 ; k < hooks->len ; k++) + lttv_trace_hook_destroy(&g_array_index(hooks, LttvTraceHook, k)); g_array_free(hooks, TRUE); } } - static gboolean state_save_event_hook(void *hook_data, void *call_data) { guint *event_count = (guint*)hook_data; @@ -1349,7 +1562,7 @@ static gboolean state_save_event_hook(void *hook_data, void *call_data) if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL)) return FALSE; else - event_count = 0; + *event_count = 0; LttvTracefileState *self = (LttvTracefileState *)call_data; @@ -1523,8 +1736,8 @@ void lttv_state_save_add_event_hooks(LttvTracesetState *self) for(j = 0 ; j < nb_tracefile ; j++) { tfs = - LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles, - LttvTracefileContext, j)); + LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles, + LttvTracefileContext*, j)); lttv_hooks_add(tfs->parent.event, state_save_event_hook, event_count, @@ -1603,13 +1816,13 @@ void lttv_state_save_remove_event_hooks(LttvTracesetState *self) for(j = 0 ; j < nb_tracefile ; j++) { tfs = - LTTV_TRACEFILE_STATE(&g_array_index(ts->parent.tracefiles, - LttvTracefileContext, j)); + LTTV_TRACEFILE_STATE(g_array_index(ts->parent.tracefiles, + LttvTracefileContext*, j)); event_count = lttv_hooks_remove(tfs->parent.event, state_save_event_hook); - g_free(event_count); } + g_free(event_count); } } @@ -1630,6 +1843,8 @@ void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) int min_pos, mid_pos, max_pos; + guint call_rest = 0; + LttvTraceState *tcs; LttvAttributeValue value; @@ -1640,6 +1855,11 @@ 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_info("Entering seek_time_closest for time %lu.%lu", t.tv_sec, t.tv_nsec); + nb_trace = lttv_traceset_number(traceset); for(i = 0 ; i < nb_trace ; i++) { tcs = (LttvTraceState *)self->parent.traces[i]; @@ -1672,6 +1892,7 @@ 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; } /* There is no saved state, yet we want to have it. Restart at T0 */ @@ -1686,6 +1907,7 @@ void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) lttv_process_trace_seek_time(&(tcs->parent), t); } } + if(!call_rest) g_info("NOT Calling restore"); } @@ -1860,6 +2082,7 @@ static void module_init() LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles"); 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_SAVED_STATES = g_quark_from_string("saved states"); LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time"); @@ -1872,6 +2095,7 @@ static void module_init() LTT_FACILITY_KERNEL = g_quark_from_string("kernel"); LTT_FACILITY_PROCESS = g_quark_from_string("process"); + LTT_FACILITY_FS = g_quark_from_string("fs"); LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry"); @@ -1884,6 +2108,7 @@ static void module_init() LTT_EVENT_FORK = g_quark_from_string("fork"); LTT_EVENT_EXIT = g_quark_from_string("exit"); LTT_EVENT_FREE = g_quark_from_string("free"); + LTT_EVENT_EXEC = g_quark_from_string("exec"); LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id"); @@ -1895,6 +2120,7 @@ static void module_init() LTT_FIELD_PARENT_PID = g_quark_from_string("parent_pid"); LTT_FIELD_CHILD_PID = g_quark_from_string("child_pid"); LTT_FIELD_PID = g_quark_from_string("pid"); + LTT_FIELD_FILENAME = g_quark_from_string("filename"); }