GQuark
LTT_FACILITY_KERNEL,
- LTT_FACILITY_PROCESS;
+ LTT_FACILITY_PROCESS,
+ LTT_FACILITY_FS;
/* Events Quarks */
LTT_EVENT_SCHEDCHANGE,
LTT_EVENT_FORK,
LTT_EVENT_EXIT,
- LTT_EVENT_FREE;
+ LTT_EVENT_FREE,
+ LTT_EVENT_EXEC;
/* Fields Quarks */
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,
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,
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;
}
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->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)
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);
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);
}
}
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;
}
process = (LttvProcessState *)value;
fprintf(fp,
-" <PROCESS CORE=%p PID=%u PPID=%u CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" CPU=\"%s\">\n",
+" <PROCESS CORE=%p PID=%u PPID=%u CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" CPU=\"%u\">\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);
LttEventPosition *ep;
+ guint nb_cpus;
+
ep = ltt_event_position_new();
fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\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<nb_cpus;i++) {
+ fprintf(fp,"<CPU NUM=%u RUNNING_PROCESS=%u>\n",
+ i, self->running_process[i]->pid);
+ }
nb_tracefile = self->parent.tracefiles->len;
tfcs =
LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
LttvTracefileContext*, i));
- fprintf(fp, " <TRACEFILE PID=%u TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
- tfcs->process->pid, tfcs->parent.timestamp.tv_sec,
+ fprintf(fp, " <TRACEFILE TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
+ tfcs->parent.timestamp.tv_sec,
tfcs->parent.timestamp.tv_nsec);
LttEvent *e = ltt_tracefile_get_event(tfcs->parent.tf);
if(e == NULL) fprintf(fp,"/>\n");
*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);
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;
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;i<nb_cpus;i++) {
+ running_process[i] = self->running_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++) {
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 of the tfs is in the pqueue */
- if(!g_tree_lookup(self->parent.ts_context->pqueue, &tfcs->parent)) {
+ /* 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);
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);
}
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;
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;i<nb_cpus;i++) {
+ pid = running_process[i];
+ self->running_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,
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);
- g_tree_destroy(tsc->pqueue);
- tsc->pqueue = g_tree_new(compare_tracefile);
-
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;
}
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;
*(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++) {
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;
}
GQuark f_name, e_name;
- LttvTraceHook *h;
+ LttvTraceHook h;
LttvTraceHookByFacility *thf;
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);
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);
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);
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;
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;
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;
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;
+ 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
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;
}
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);
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;
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
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;
}
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;
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;
}
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;
}
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;
/* 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);
/* 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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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 */
nb_tracefile = ts->parent.tracefiles->len;
nb_trace = lttv_traceset_number(traceset);
for(i = 0 ; i < nb_trace ; i++) {
- ts = (LttvTraceState*)self->parent.traces[i];
+ ts = LTTV_TRACE_STATE(self->parent.traces[i]);
lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
hooks = *(val.v_pointer);
}
}
-
static gboolean state_save_event_hook(void *hook_data, void *call_data)
{
guint *event_count = (guint*)hook_data;
if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
return FALSE;
else
- event_count = 0;
+ *event_count = 0;
LttvTracefileState *self = (LttvTracefileState *)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)
{
}
}
+
+ 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)
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++) {
LttvTracefileContext*, j));
event_count = lttv_hooks_remove(tfs->parent.event,
state_save_event_hook);
- g_free(event_count);
-
}
+ g_free(event_count);
}
}
int min_pos, mid_pos, max_pos;
+ guint call_rest = 0;
+
LttvTraceState *tcs;
LttvAttributeValue value;
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];
/* 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 */
lttv_process_trace_seek_time(&(tcs->parent), t);
}
}
+ if(!call_rest) g_info("NOT Calling restore");
}
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");
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");
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");
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");
}