#include <ltt/event.h>
#include <ltt/type.h>
#include <stdio.h>
+#include <string.h>
#define PREALLOCATED_EXECUTION_STACK 10
GQuark
LTT_FACILITY_KERNEL,
- LTT_FACILITY_PROCESS;
+ LTT_FACILITY_KERNEL_ARCH,
+ LTT_FACILITY_PROCESS,
+ LTT_FACILITY_FS,
+ LTT_FACILITY_STATEDUMP;
/* Events Quarks */
LTT_EVENT_TRAP_EXIT,
LTT_EVENT_IRQ_ENTRY,
LTT_EVENT_IRQ_EXIT,
+ LTT_EVENT_SOFT_IRQ_ENTRY,
+ LTT_EVENT_SOFT_IRQ_EXIT,
LTT_EVENT_SCHEDCHANGE,
LTT_EVENT_FORK,
+ LTT_EVENT_KERNEL_THREAD,
LTT_EVENT_EXIT,
- LTT_EVENT_FREE;
+ LTT_EVENT_FREE,
+ LTT_EVENT_EXEC,
+ LTT_EVENT_ENUM_PROCESS_STATE;
/* Fields Quarks */
LTT_FIELD_SYSCALL_ID,
LTT_FIELD_TRAP_ID,
LTT_FIELD_IRQ_ID,
+ LTT_FIELD_SOFT_IRQ_ID,
LTT_FIELD_OUT,
LTT_FIELD_IN,
LTT_FIELD_OUT_STATE,
LTT_FIELD_PARENT_PID,
LTT_FIELD_CHILD_PID,
- LTT_FIELD_PID;
+ LTT_FIELD_PID,
+ LTT_FIELD_FILENAME,
+ LTT_FIELD_NAME,
+ LTT_FIELD_MODE,
+ LTT_FIELD_SUBMODE,
+ LTT_FIELD_STATUS;
LttvExecutionMode
LTTV_STATE_MODE_UNKNOWN,
LTTV_STATE_USER_MODE,
LTTV_STATE_SYSCALL,
LTTV_STATE_TRAP,
- LTTV_STATE_IRQ;
+ LTTV_STATE_IRQ,
+ LTTV_STATE_SOFT_IRQ;
LttvExecutionSubmode
LTTV_STATE_SUBMODE_UNKNOWN,
LTTV_STATE_EXIT,
LTTV_STATE_ZOMBIE,
LTTV_STATE_WAIT,
- LTTV_STATE_RUN;
+ LTTV_STATE_RUN,
+ LTTV_STATE_DEAD;
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,
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,
+ LTTV_STATE_UNNAMED, <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)
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");
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 *syscall_names;
GQuark *trap_names;
GQuark *irq_names;
+ GQuark *soft_irq_names;
} LttvNameTables;
}
#endif //0
if(lttv_trace_find_hook(tcs->parent.t,
- LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
+ LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
LTT_FIELD_SYSCALL_ID, 0, 0,
- NULL, &h))
+ NULL, NULL, &h))
return;
thf = lttv_trace_hook_get_first(&h);
lttv_trace_hook_destroy(&h);
- /* CHECK syscalls should be an enum but currently are not!
name_tables->syscall_names = g_new(GQuark, nb);
for(i = 0 ; i < nb ; i++) {
- name_tables->syscall_names[i] = g_quark_from_string(
- ltt_enum_string_get(t, i));
+ name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
}
- */
- name_tables->syscall_names = g_new(GQuark, 256);
- for(i = 0 ; i < 256 ; i++) {
- g_string_printf(fe_name, "syscall %d", i);
- name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
- }
+ //name_tables->syscall_names = g_new(GQuark, 256);
+ //for(i = 0 ; i < 256 ; i++) {
+ // g_string_printf(fe_name, "syscall %d", i);
+ // name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
+ //}
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);
t = ltt_field_type(thf->f1);
- nb = ltt_type_element_number(t);
+ //nb = ltt_type_element_number(t);
lttv_trace_hook_destroy(&h);
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);
t = ltt_field_type(thf->f1);
- nb = ltt_type_element_number(t);
+ //nb = ltt_type_element_number(t);
lttv_trace_hook_destroy(&h);
name_tables->irq_names[i] = g_quark_from_string(fe_name->str);
}
+ /*
+ name_tables->soft_irq_names = g_new(GQuark, nb);
+ for(i = 0 ; i < nb ; i++) {
+ name_tables->soft_irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
+ }
+ */
+
+ name_tables->soft_irq_names = g_new(GQuark, 256);
+ for(i = 0 ; i < 256 ; i++) {
+ g_string_printf(fe_name, "softirq %d", i);
+ name_tables->soft_irq_names[i] = g_quark_from_string(fe_name->str);
+ }
+
+
g_string_free(fe_name, TRUE);
}
tcs->syscall_names = name_tables->syscall_names;
tcs->trap_names = name_tables->trap_names;
tcs->irq_names = name_tables->irq_names;
+ tcs->soft_irq_names = name_tables->soft_irq_names;
}
g_free(name_tables->syscall_names);
g_free(name_tables->trap_names);
g_free(name_tables->irq_names);
+ g_free(name_tables->soft_irq_names);
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;
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;
LttvProcessState *
-lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent,
- guint pid)
+lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent,
+ guint cpu, guint pid, GQuark name, 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->name = name;
+ //process->last_cpu = tfs->cpu_name;
+ //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
+ process->kernel_thread = 0;
+
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
else {
process->ppid = 0;
- process->name = LTTV_STATE_UNNAMED;
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);
- 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);
+ LttvExecutionState *es;
+
+ /* Put ltt_time_zero creation time for unexisting processes */
+ if(unlikely(process == NULL)) {
+ process = lttv_state_create_process(ts,
+ NULL, cpu, pid, LTTV_STATE_UNNAMED, timestamp);
+ /* We are not sure is it's a kernel thread or normal thread, put the
+ * bottom stack state to unknown */
+ es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
+ es->t = LTTV_STATE_MODE_UNKNOWN;
+ }
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);
return FALSE;
}
+static gboolean soft_irq_entry(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+ LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
+ 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;
+
+ submode = ((LttvTraceState *)(s->parent.t_context))->soft_irq_names[
+ ltt_event_get_unsigned(e, f)];
+
+ /* Do something with the info about being in user or system mode when int? */
+ push_state(s, LTTV_STATE_SOFT_IRQ, submode);
+ return FALSE;
+}
+
+
+static gboolean soft_irq_exit(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+ pop_state(s, LTTV_STATE_SOFT_IRQ);
+ return FALSE;
+}
+
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];
+ LttvProcessState *old_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
the wrongly attributed statistics. */
//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);
+ //missing events. We need to silently ignore schedchange coming after a
+ //process_free, or it causes glitches. (FIXME)
+ //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;
+ process->state->change = s->parent.timestamp;
} else {
- if(unlikely(state_out == 0)) s->process->state->s = LTTV_STATE_WAIT_CPU;
- else s->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);
-
- s->process->state->change = s->parent.timestamp;
+ if(unlikely(state_out == 0)) process->state->s = LTTV_STATE_WAIT_CPU;
+ else process->state->s = LTTV_STATE_WAIT;
+ process->state->change = s->parent.timestamp;
+ }
+
+ if(state_out == 32)
+ exit_process(s, process); /* EXIT_DEAD */
+ /* see sched.h for states */
}
- 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;
}
LttvTracefileState *s = (LttvTracefileState *)call_data;
LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
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;
- parent_pid = ltt_event_get_unsigned(e, f);
+ parent_pid = ltt_event_get_unsigned(e, thf->f1);
/* Child PID */
- f = thf->f2;
- child_pid = ltt_event_get_unsigned(e, f);
+ child_pid = ltt_event_get_unsigned(e, thf->f2);
- 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.
+ *
+ * Test reenabled after precision fixes on time. (Mathieu) */
+#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(zombie_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) {
+ child_process = lttv_state_create_process(ts, process, cpu,
+ child_pid, LTTV_STATE_UNNAMED, &s->parent.timestamp);
+ } else {
+ /* The process has already been created : due to time imprecision between
+ * multiple CPUs : it has been scheduled in before creation. Note that we
+ * shouldn't have this kind of imprecision.
+ *
+ * Simply put a correct parent.
+ */
+ g_assert(0); /* This is a problematic case : the process has been created
+ before the fork event */
+ child_process->ppid = process->pid;
+ }
+ g_assert(child_process->name == LTTV_STATE_UNNAMED);
+ child_process->name = process->name;
return FALSE;
}
+/* We stamp a newly created process as kernel_thread */
+static gboolean process_kernel_thread(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+ LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
+ LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
+ guint pid;
+ guint cpu = ltt_tracefile_num(s->parent.tf);
+ LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
+ LttvProcessState *process;
+ LttvExecutionState *es;
+
+ /* PID */
+ pid = ltt_event_get_unsigned(e, thf->f1);
+
+ process = lttv_state_find_process(ts, ANY_CPU, pid);
+ es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
+ es->t = LTTV_STATE_SYSCALL;
+ process->kernel_thread = 1;
+
+ return FALSE;
+}
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;
}
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 */
- exit_process(s, process);
+ //This test is fun, though, as it may happen that
+ //at time t : CPU 0 : process_free
+ //at time t+150ns : CPU 1 : schedule out
+ //Clearly due to time imprecision, we disable it. (Mathieu)
+ //If this weird case happen, we have no choice but to put the
+ //Currently running process on the cpu to 0.
+ //I re-enable it following time precision fixes. (Mathieu)
+ //Well, in the case where an process is freed by a process on another CPU
+ //and still scheduled, it happens that this is the schedchange that will
+ //drop the last reference count. Do not free it here!
+ 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]);
+ if(process == ts->running_process[i]) {
+ //ts->running_process[i] = lttv_state_find_process(ts, i, 0);
+ break;
+ }
+ }
+ //if(i == num_cpus) /* process is not scheduled */
+ //exit_process(s, process); // do nothing : wait for the schedchange to
+ //delete the 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 */
+ guint64 name_len = ltt_event_field_element_number(e, thf->f1);
+ //name = ltt_event_get_string(e, thf->f1);
+ LttField *child = ltt_event_field_element_select(e, thf->f1, 0);
+ gchar *name_begin =
+ (gchar*)(ltt_event_data(e)+ltt_event_field_offset(e, child));
+ gchar *null_term_name = g_new(gchar, name_len+1);
+ memcpy(null_term_name, name_begin, name_len);
+ null_term_name[name_len] = '\0';
+
+ process->name = g_quark_from_string(null_term_name);
+ g_free(null_term_name);
+ return FALSE;
+}
+
+static gboolean enum_process_state(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+ LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
+ //It's slow : optimise later by doing this before reading trace.
+ LttEventType *et = ltt_event_eventtype(e);
+ //
+ LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
+ guint parent_pid;
+ guint pid;
+ gchar * command;
+ guint cpu = ltt_tracefile_num(s->parent.tf);
+ LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
+ LttvProcessState *process = ts->running_process[cpu];
+ LttvProcessState *parent_process;
+ LttField *f4, *f5, *f6;
+ GQuark mode, submode, status;
+
+ /* PID */
+ pid = ltt_event_get_unsigned(e, thf->f1);
+
+ /* Parent PID */
+ parent_pid = ltt_event_get_unsigned(e, thf->f2);
+
+ /* Command name */
+ command = ltt_event_get_string(e, thf->f3);
+
+ /* mode */
+ f4 = ltt_eventtype_field_by_name(et, LTT_FIELD_MODE);
+ mode = ltt_enum_string_get(ltt_field_type(f4),
+ ltt_event_get_unsigned(e, f4));
+
+ /* submode */
+ f5 = ltt_eventtype_field_by_name(et, LTT_FIELD_SUBMODE);
+ submode = ltt_enum_string_get(ltt_field_type(f5),
+ ltt_event_get_unsigned(e, f5));
+
+ /* status */
+ f6 = ltt_eventtype_field_by_name(et, LTT_FIELD_STATUS);
+ status = ltt_enum_string_get(ltt_field_type(f6),
+ ltt_event_get_unsigned(e, f6));
+
+ /* The process might exist if a process was forked while performing the sate dump. */
+ process = lttv_state_find_process(ts, ANY_CPU, pid);
+ if(process == NULL) {
+ parent_process = lttv_state_find_process(ts, ANY_CPU, parent_pid);
+ process = lttv_state_create_process(ts, parent_process, cpu,
+ pid, g_quark_from_string(command),
+ &s->parent.timestamp);
+
+ /* Keep the stack bottom : a running user mode */
+#if 0
+ /* Disabled because of inconsistencies in the current statedump states. */
+ if(mode == LTTV_STATE_USER_MODE) {
+ /* Only keep the bottom */
+ process->execution_stack = g_array_set_size(process->execution_stack, 1);
+ } else {
+ /* On top of it : */
+ LttvExecutionState *es;
+ es = process->state = &g_array_index(process->execution_stack,
+ LttvExecutionState, 1);
+ es->t = mode;
+ es->s = status;
+ es->n = submode;
+ }
+#endif //0
+
+ /* UNKNOWN STATE */
+ {
+ LttvExecutionState *es;
+ es = process->state = &g_array_index(process->execution_stack,
+ LttvExecutionState, 1);
+ es->t = LTTV_STATE_MODE_UNKNOWN;
+ es->s = LTTV_STATE_UNNAMED;
+ es->n = LTTV_STATE_SUBMODE_UNKNOWN;
+ }
+ } else {
+ /* The process has already been created :
+ * Probably was forked while dumping the process state or
+ * was simply scheduled in prior to get the state dump event.
+ */
+ process->ppid = parent_pid;
+ process->name = g_quark_from_string(command);
+ /* Don't mess around with the stack, it will eventually become
+ * ok after the end of state dump. */
+ }
+
+ 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), 15);
+ hooks = g_array_set_size(hooks, 15);
ret = lttv_trace_find_hook(ts->parent.t,
- LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
+ LTT_FACILITY_KERNEL_ARCH, 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,
+ LTT_FACILITY_KERNEL_ARCH, 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_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
+ LTT_FIELD_SOFT_IRQ_ID, 0, 0,
+ soft_irq_entry, NULL, &g_array_index(hooks, LttvTraceHook, 6));
+ g_assert(!ret);
+
+ ret = lttv_trace_find_hook(ts->parent.t,
+ LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
+ 0, 0, 0,
+ soft_irq_exit, NULL, &g_array_index(hooks, LttvTraceHook, 7));
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, 8));
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, 9));
+ g_assert(!ret);
+
+ ret = lttv_trace_find_hook(ts->parent.t,
+ LTT_FACILITY_PROCESS, LTT_EVENT_KERNEL_THREAD,
+ LTT_FIELD_PID, 0, 0,
+ process_kernel_thread, NULL, &g_array_index(hooks, LttvTraceHook, 10));
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, 11));
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, 12));
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, 13));
+ g_assert(!ret);
+
+ /* statedump-related hooks */
+ ret = lttv_trace_find_hook(ts->parent.t,
+ LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
+ LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
+ enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, 14));
+ g_assert(!ret);
+
/* Add these hooks to each event_by_id hooks list */
nb_tracefile = ts->parent.tracefiles->len;
}
}
}
- lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
+ lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
*(val.v_pointer) = hooks;
}
}
nb_trace = lttv_traceset_number(traceset);
for(i = 0 ; i < nb_trace ; i++) {
ts = LTTV_TRACE_STATE(self->parent.traces[i]);
- lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
+ lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
hooks = *(val.v_pointer);
/* Remove these hooks from each event_by_id hooks list */
}
}
-
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++) {
ts = (LttvTraceState *)self->parent.traces[i];
nb_tracefile = ts->parent.tracefiles->len;
- guint *event_count;
+ guint *event_count = NULL;
for(j = 0 ; j < nb_tracefile ; j++) {
tfs =
LttvTracefileContext*, j));
event_count = lttv_hooks_remove(tfs->parent.event,
state_save_event_hook);
- g_free(event_count);
-
}
+ if(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");
}
static void module_init()
{
LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
- LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode");
- LTTV_STATE_USER_MODE = g_quark_from_string("user mode");
- LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork");
- LTTV_STATE_SYSCALL = g_quark_from_string("system call");
- LTTV_STATE_TRAP = g_quark_from_string("trap");
- LTTV_STATE_IRQ = g_quark_from_string("irq");
- LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode");
- LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)");
- LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu");
- LTTV_STATE_EXIT = g_quark_from_string("exiting");
- LTTV_STATE_ZOMBIE = g_quark_from_string("zombie");
- LTTV_STATE_WAIT = g_quark_from_string("wait for I/O");
- LTTV_STATE_RUN = g_quark_from_string("running");
+ LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("MODE_UNKNOWN");
+ LTTV_STATE_USER_MODE = g_quark_from_string("USER_MODE");
+ LTTV_STATE_SYSCALL = g_quark_from_string("SYSCALL");
+ LTTV_STATE_TRAP = g_quark_from_string("TRAP");
+ LTTV_STATE_IRQ = g_quark_from_string("IRQ");
+ LTTV_STATE_SOFT_IRQ = g_quark_from_string("SOFTIRQ");
+ LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("UNKNOWN");
+ LTTV_STATE_SUBMODE_NONE = g_quark_from_string("NONE");
+ LTTV_STATE_WAIT_FORK = g_quark_from_string("WAIT_FORK");
+ LTTV_STATE_WAIT_CPU = g_quark_from_string("WAIT_CPU");
+ LTTV_STATE_EXIT = g_quark_from_string("EXIT");
+ LTTV_STATE_ZOMBIE = g_quark_from_string("ZOMBIE");
+ LTTV_STATE_WAIT = g_quark_from_string("WAIT");
+ LTTV_STATE_RUN = g_quark_from_string("RUN");
+ LTTV_STATE_DEAD = g_quark_from_string("DEAD");
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_KERNEL_ARCH = g_quark_from_string("kernel_arch");
LTT_FACILITY_PROCESS = g_quark_from_string("process");
+ LTT_FACILITY_FS = g_quark_from_string("fs");
+ LTT_FACILITY_STATEDUMP = g_quark_from_string("statedump");
LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
LTT_EVENT_IRQ_ENTRY = g_quark_from_string("irq_entry");
LTT_EVENT_IRQ_EXIT = g_quark_from_string("irq_exit");
+ LTT_EVENT_SOFT_IRQ_ENTRY = g_quark_from_string("soft_irq_entry");
+ LTT_EVENT_SOFT_IRQ_EXIT = g_quark_from_string("soft_irq_exit");
LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange");
LTT_EVENT_FORK = g_quark_from_string("fork");
+ LTT_EVENT_KERNEL_THREAD = g_quark_from_string("kernel_thread");
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_EVENT_ENUM_PROCESS_STATE = g_quark_from_string("enumerate_process_state");
LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
LTT_FIELD_TRAP_ID = g_quark_from_string("trap_id");
LTT_FIELD_IRQ_ID = g_quark_from_string("irq_id");
+ LTT_FIELD_SOFT_IRQ_ID = g_quark_from_string("softirq_id");
LTT_FIELD_OUT = g_quark_from_string("out");
LTT_FIELD_IN = g_quark_from_string("in");
LTT_FIELD_OUT_STATE = g_quark_from_string("out_state");
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");
+ LTT_FIELD_NAME = g_quark_from_string("name");
+ LTT_FIELD_MODE = g_quark_from_string("mode");
+ LTT_FIELD_SUBMODE = g_quark_from_string("submode");
+ LTT_FIELD_STATUS = g_quark_from_string("status");
}