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,
self->nb_event = 0;
/* Seek time to beginning */
- g_tree_destroy(self->parent.ts_context->pqueue);
- self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
+ // Mathieu : fix : don't seek traceset here : causes inconsistency in seek
+ // closest. It's the tracecontext job to seek the trace to the beginning
+ // anyway : the init state might be used at the middle of the trace as well...
+ //g_tree_destroy(self->parent.ts_context->pqueue);
+ //self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
- lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
+
+ //lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
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;
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);
}
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;
}
/* Free running processes array */
nb_cpus = ltt_trace_get_num_cpu(self->parent.t);
- type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_RUNNING_PROCESS,
+ type = lttv_attribute_get_by_name(container, LTTV_STATE_RUNNING_PROCESS,
&value);
g_assert(type == LTTV_POINTER);
running_process = *(value.v_pointer);
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)
{
guint cpu = ltt_tracefile_num(tfs->parent.tf);
LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
+
+#ifdef HASH_TABLE_DEBUG
+ hash_table_check(ts->processes);
+#endif
LttvProcessState *process = ts->running_process[cpu];
guint depth = process->execution_stack->len;
f = thf->f2;
child_pid = ltt_event_get_unsigned(e, f);
+ /* Mathieu : it seems like the process might have been scheduled in before the
+ * fork, and, in a rare case, might be the current process. This might happen
+ * in a SMP case where we don't have enough precision on the clocks */
+#if 0
zombie_process = lttv_state_find_process(ts, ANY_CPU, child_pid);
if(unlikely(zombie_process != NULL)) {
/* Reutilisation of PID. Only now we are sure that the old PID
* has been released. FIXME : should know when release_task happens instead.
*/
+ guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
+ guint i;
+ for(i=0; i< num_cpus; i++) {
+ g_assert(process != ts->running_process[i]);
+ }
+
exit_process(s, zombie_process);
}
+#endif //0
g_assert(process->pid != child_pid);
// FIXME : Add this test in the "known state" section
// g_assert(process->pid == parent_pid);
/* PID of the process to release */
release_pid = ltt_event_get_unsigned(e, thf->f1);
+
+ g_assert(release_pid != 0);
process = lttv_state_find_process(ts, ANY_CPU, release_pid);
if(likely(process != NULL)) {
/* release_task is happening at kernel level : we can now safely release
* the data structure of the process */
+ guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t);
+ guint i;
+ for(i=0; i< num_cpus; i++) {
+ g_assert(process != ts->running_process[i]);
+ }
exit_process(s, process);
}
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);
- 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,
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 */
}
}
-static guint test_event_count = 0;
static gboolean state_save_event_hook(void *hook_data, void *call_data)
{
guint *event_count = (guint*)hook_data;
- test_event_count++;
/* Only save at LTTV_STATE_SAVE_INTERVAL */
if(likely((*event_count)++ < LTTV_STATE_SAVE_INTERVAL))
return FALSE;
}
g_free(event_count);
}
- g_info("EVENT COUNT TEST : %u", test_event_count);
}
gint lttv_state_save_hook_remove_event_hooks(void *hook_data, void *call_data)
int min_pos, mid_pos, max_pos;
+ guint call_rest = 0;
+
LttvTraceState *tcs;
LttvAttributeValue value;
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");
}
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");
}