X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Flttv%2Fstate.c;h=aef86ae5c667b5a7ffa23c8b18d89eaaecc041c6;hb=c607371be079c36e281398a753221002c1c4c851;hp=b107c25b40554c7e5d17a9f3f1052622f290d69a;hpb=3054461acbbd00cc70e9e3046050f074e9eec4c9;p=lttv.git diff --git a/ltt/branches/poly/lttv/lttv/state.c b/ltt/branches/poly/lttv/lttv/state.c index b107c25b..aef86ae5 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,14 +164,36 @@ 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++) { @@ -181,9 +207,10 @@ restore_init_state(LttvTraceState *self) tfcs->process->last_cpu = tfcs->cpu_name; 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) @@ -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); + 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,11 +360,19 @@ 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; @@ -340,8 +380,8 @@ void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp) tfcs = LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles, LttvTracefileContext*, i)); - fprintf(fp, " process->pid, tfcs->parent.timestamp.tv_sec, + 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"); @@ -402,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; @@ -423,6 +465,18 @@ 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++) { @@ -433,9 +487,11 @@ static void state_save(LttvTraceState *self, LttvAttribute *container) 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); /* Only save the position if the tfs has not infinite time. */ @@ -453,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 %u offset %u 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); } @@ -463,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; @@ -488,10 +546,23 @@ 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); + //g_tree_destroy(tsc->pqueue); + //tsc->pqueue = g_tree_new(compare_tracefile); for(i = 0 ; i < nb_tracefile ; i++) { tfcs = @@ -500,13 +571,13 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) 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); @@ -515,12 +586,14 @@ 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); 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; } @@ -530,12 +603,14 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container) 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; @@ -556,6 +631,14 @@ 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++) { @@ -610,7 +693,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; } @@ -805,12 +888,37 @@ 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; @@ -831,7 +939,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; @@ -864,32 +974,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 = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf); + 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 @@ -902,47 +1008,58 @@ 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 = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf); + 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); - process->execution_stack = g_array_set_size(process->execution_stack, 1); + process->execution_stack = g_array_set_size(process->execution_stack, 2); 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_RUN; + + es = process->state = &g_array_index(process->execution_stack, + LttvExecutionState, 1); + es->t = LTTV_STATE_SYSCALL; + es->n = LTTV_STATE_SUBMODE_NONE; + 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; } @@ -959,7 +1076,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); @@ -1065,6 +1182,10 @@ 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 = (LttvTraceHookByFacility *)hook_data; guint pid_in, pid_out; @@ -1073,8 +1194,8 @@ static gboolean schedchange(void *hook_data, void *call_data) pid_out = ltt_event_get_unsigned(e, thf->f1); pid_in = ltt_event_get_unsigned(e, thf->f2); state_out = ltt_event_get_int(e, thf->f3); - - if(likely(s->process != NULL)) { + + 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 @@ -1084,30 +1205,34 @@ static gboolean schedchange(void *hook_data, void *call_data) //This test only makes sense once the state is known and if there is no //missing events. - //if(unlikely(s->process->pid != pid_out)) { - // g_assert(s->process->pid == 0); + //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 = ltt_tracefile_num(((LttvTracefileContext*)s)->tf); - 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; } @@ -1120,6 +1245,10 @@ static gboolean process_fork(void *hook_data, void *call_data) 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; @@ -1129,18 +1258,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; } @@ -1153,14 +1304,17 @@ static gboolean process_exit(void *hook_data, void *call_data) 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; } @@ -1168,6 +1322,7 @@ 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 = (LttvTraceHookByFacility *)hook_data; guint release_pid; @@ -1175,18 +1330,47 @@ 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(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); @@ -1223,8 +1407,8 @@ 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); - hooks = g_array_set_size(hooks, 10); + hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 11); + hooks = g_array_set_size(hooks, 11); ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY, @@ -1286,6 +1470,13 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) 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 */ @@ -1373,7 +1564,6 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) } } - static gboolean state_save_event_hook(void *hook_data, void *call_data) { guint *event_count = (guint*)hook_data; @@ -1417,6 +1607,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) { @@ -1565,6 +1764,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) @@ -1625,7 +1828,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++) { @@ -1640,7 +1855,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); } @@ -1663,6 +1877,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; @@ -1673,6 +1889,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]; @@ -1705,6 +1926,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 */ @@ -1719,6 +1941,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"); } @@ -1893,6 +2116,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"); @@ -1905,6 +2129,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"); @@ -1917,6 +2142,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"); @@ -1928,6 +2154,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"); }