LTT_EVENT_EXEC,
LTT_EVENT_ENUM_PROCESS_STATE,
LTT_EVENT_FUNCTION_ENTRY,
- LTT_EVENT_FUNCTION_EXIT;
+ LTT_EVENT_FUNCTION_EXIT,
+ LTT_EVENT_THREAD_BRAND;
/* Fields Quarks */
LTT_FIELD_PID,
LTT_FIELD_FILENAME,
LTT_FIELD_NAME,
+ LTT_FIELD_TYPE,
LTT_FIELD_MODE,
LTT_FIELD_SUBMODE,
LTT_FIELD_STATUS,
LttvProcessStatus
LTTV_STATE_UNNAMED,
+ LTTV_STATE_UNBRANDED,
LTTV_STATE_WAIT_FORK,
LTTV_STATE_WAIT_CPU,
LTTV_STATE_EXIT,
LTTV_STATE_RUN,
LTTV_STATE_DEAD;
+LttvProcessType
+ LTTV_STATE_USER_THREAD,
+ LTTV_STATE_KERNEL_THREAD;
+
static GQuark
LTTV_STATE_TRACEFILES,
LTTV_STATE_PROCESSES,
guint i, nb_cpus;
LttvTracefileState *tfcs;
+
+ LttTime start_time, end_time;
/* Free the process tables */
if(self->processes != NULL) lttv_state_free_process_table(self->processes);
//g_tree_destroy(self->parent.ts_context->pqueue);
//self->parent.ts_context->pqueue = g_tree_new(compare_tracefile);
+ ltt_trace_time_span_get(self->parent.t, &start_time, &end_time);
//lttv_process_trace_seek_time(&self->parent, ltt_time_zero);
/* 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);
+ LTTV_STATE_UNNAMED, &start_time);
self->running_process[i]->state->s = LTTV_STATE_RUN;
self->running_process[i]->cpu = i;
}
process = (LttvProcessState *)value;
fprintf(fp,
-" <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 CORE=%p PID=%u PPID=%u TYPE=\"%s\"CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\">\n",
+ process, process->pid, process->ppid, g_quark_to_string(process->type),
+ process->creation_time.tv_sec,
process->creation_time.tv_nsec, g_quark_to_string(process->name),
+ g_quark_to_string(process->brand),
process->cpu);
for(i = 0 ; i < process->execution_stack->len; i++) {
typedef struct _LttvNameTables {
// FIXME GQuark *eventtype_names;
GQuark *syscall_names;
- guint nb_syscalls;
+ guint nb_syscalls;
GQuark *trap_names;
+ guint nb_traps;
GQuark *irq_names;
GQuark *soft_irq_names;
} LttvNameTables;
name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str);
}
#endif //0
- if(lttv_trace_find_hook(tcs->parent.t,
+ if(!lttv_trace_find_hook(tcs->parent.t,
LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
LTT_FIELD_SYSCALL_ID, 0, 0,
- NULL, NULL, &h))
- return;
-
- thf = lttv_trace_hook_get_first(&h);
-
- t = ltt_field_type(thf->f1);
- nb = ltt_type_element_number(t);
-
- lttv_trace_hook_destroy(&h);
+ NULL, NULL, &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);
- name_tables->syscall_names = g_new(GQuark, nb);
- name_tables->nb_syscalls = nb;
+ name_tables->syscall_names = g_new(GQuark, nb);
+ name_tables->nb_syscalls = nb;
- for(i = 0 ; i < nb ; i++) {
- name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
- }
+ for(i = 0 ; i < nb ; 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);
+ //}
+ } else {
+ name_tables->syscall_names = NULL;
+ name_tables->nb_syscalls = 0;
+ }
- if(lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL,
+ if(!lttv_trace_find_hook(tcs->parent.t, LTT_FACILITY_KERNEL,
LTT_EVENT_TRAP_ENTRY,
LTT_FIELD_TRAP_ID, 0, 0,
- NULL, NULL, &h))
- return;
+ NULL, NULL, &h)) {
- 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);
+ t = ltt_field_type(thf->f1);
+ //nb = ltt_type_element_number(t);
- lttv_trace_hook_destroy(&h);
-
- /*
- name_tables->trap_names = g_new(GQuark, nb);
- for(i = 0 ; i < nb ; i++) {
- name_tables->trap_names[i] = g_quark_from_string(
- ltt_enum_string_get(t, i));
- }
- */
+ lttv_trace_hook_destroy(&h);
- name_tables->trap_names = g_new(GQuark, 256);
- for(i = 0 ; i < 256 ; i++) {
- g_string_printf(fe_name, "trap %d", i);
- name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
- }
+ /*
+ name_tables->trap_names = g_new(GQuark, nb);
+ for(i = 0 ; i < nb ; i++) {
+ name_tables->trap_names[i] = g_quark_from_string(
+ ltt_enum_string_get(t, i));
+ }
+ */
+ name_tables->nb_traps = 256;
+ name_tables->trap_names = g_new(GQuark, 256);
+ for(i = 0 ; i < 256 ; i++) {
+ g_string_printf(fe_name, "trap %d", i);
+ name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
+ }
+ } else {
+ name_tables->trap_names = NULL;
+ name_tables->nb_traps = 0;
+ }
- if(lttv_trace_find_hook(tcs->parent.t,
+ if(!lttv_trace_find_hook(tcs->parent.t,
LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
LTT_FIELD_IRQ_ID, 0, 0,
- NULL, NULL, &h))
- return;
-
- thf = lttv_trace_hook_get_first(&h);
-
- t = ltt_field_type(thf->f1);
- //nb = ltt_type_element_number(t);
-
- lttv_trace_hook_destroy(&h);
+ NULL, NULL, &h)) {
+
+ thf = lttv_trace_hook_get_first(&h);
+
+ t = ltt_field_type(thf->f1);
+ //nb = ltt_type_element_number(t);
- /*
- name_tables->irq_names = g_new(GQuark, nb);
- for(i = 0 ; i < nb ; i++) {
- name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
- }
- */
+ lttv_trace_hook_destroy(&h);
- name_tables->irq_names = g_new(GQuark, 256);
- for(i = 0 ; i < 256 ; i++) {
- g_string_printf(fe_name, "irq %d", i);
- name_tables->irq_names[i] = g_quark_from_string(fe_name->str);
- }
+ /*
+ name_tables->irq_names = g_new(GQuark, nb);
+ for(i = 0 ; i < nb ; i++) {
+ name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
+ }
+ */
+ name_tables->irq_names = g_new(GQuark, 256);
+ for(i = 0 ; i < 256 ; i++) {
+ g_string_printf(fe_name, "irq %d", i);
+ name_tables->irq_names[i] = g_quark_from_string(fe_name->str);
+ }
+ } else {
+ name_tables->irq_names = NULL;
+ }
/*
name_tables->soft_irq_names = g_new(GQuark, nb);
for(i = 0 ; i < nb ; i++) {
tcs->syscall_names = name_tables->syscall_names;
tcs->nb_syscalls = name_tables->nb_syscalls;
tcs->trap_names = name_tables->trap_names;
+ tcs->nb_traps = name_tables->nb_traps;
tcs->irq_names = name_tables->irq_names;
tcs->soft_irq_names = name_tables->soft_irq_names;
}
*(v.v_pointer) = NULL;
// g_free(name_tables->eventtype_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);
+ if(name_tables->syscall_names) g_free(name_tables->syscall_names);
+ if(name_tables->trap_names) g_free(name_tables->trap_names);
+ if(name_tables->irq_names) g_free(name_tables->irq_names);
+ if(name_tables->soft_irq_names) g_free(name_tables->soft_irq_names);
+ if(name_tables) g_free(name_tables);
}
#ifdef HASH_TABLE_DEBUG
es->t = t;
es->n = state_id;
es->entry = es->change = tfs->parent.timestamp;
+ es->cum_cpu_time = ltt_time_zero;
es->s = process->state->s;
process->state = es;
}
+/* pop state
+ * return 1 when empty, else 0 */
+int lttv_state_pop_state_cleanup(LttvProcessState *process,
+ LttvTracefileState *tfs)
+{
+ guint cpu = tfs->cpu;
+ LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
+
+ guint depth = process->execution_stack->len;
+
+ if(depth == 1){
+ return 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;
+
+ return 0;
+}
static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
{
g_info("process state has %s when pop_int is %s\n",
g_quark_to_string(process->state->t),
g_quark_to_string(t));
- g_info("{ %u, %u, %s, %s }\n",
+ g_info("{ %u, %u, %s, %s, %s }\n",
process->pid,
process->ppid,
g_quark_to_string(process->name),
+ g_quark_to_string(process->brand),
g_quark_to_string(process->state->s));
return;
}
process->pid = pid;
process->cpu = cpu;
process->name = name;
+ process->brand = LTTV_STATE_UNBRANDED;
//process->last_cpu = tfs->cpu_name;
//process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
- process->kernel_thread = 0;
+ process->type = LTTV_STATE_USER_THREAD;
process->usertrace = ltt_state_usertrace_find(tcs, pid, timestamp);
process->current_function = 0; //function 0x0 by default.
es->entry = *timestamp;
//g_assert(timestamp->tv_sec != 0);
es->change = *timestamp;
+ es->cum_cpu_time = ltt_time_zero;
es->s = LTTV_STATE_RUN;
es = process->state = &g_array_index(process->execution_stack,
es->entry = *timestamp;
//g_assert(timestamp->tv_sec != 0);
es->change = *timestamp;
+ es->cum_cpu_time = ltt_time_zero;
es->s = LTTV_STATE_WAIT_FORK;
/* Allocate an empty function call stack. If it's empty, use 0x0. */
LttvExecutionSubmode submode;
- submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[
- ltt_event_get_unsigned(e, f)];
+ guint64 nb_traps = ((LttvTraceState *)(s->parent.t_context))->nb_traps;
+ guint64 trap = ltt_event_get_long_unsigned(e, f);
+
+ if(trap < nb_traps) {
+ submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[trap];
+ } else {
+ /* Fixup an incomplete trap table */
+ GString *string = g_string_new("");
+ g_string_printf(string, "trap %u", trap);
+ submode = g_quark_from_string(string->str);
+ g_string_free(string, TRUE);
+ }
+
push_state(s, LTTV_STATE_TRAP, submode);
return FALSE;
}
LttvExecutionSubmode submode;
submode = ((LttvTraceState *)(s->parent.t_context))->soft_irq_names[
- ltt_event_get_unsigned(e, f)];
+ ltt_event_get_long_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);
tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
g_info("process state has %llu when pop_function is %llu\n",
process->current_function, funcptr);
- g_info("{ %u, %u, %s, %s }\n",
+ g_info("{ %u, %u, %s, %s, %s }\n",
process->pid,
process->ppid,
g_quark_to_string(process->name),
+ g_quark_to_string(process->brand),
g_quark_to_string(process->state->s));
return;
}
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;
+ process->type = LTTV_STATE_KERNEL_THREAD;
return FALSE;
}
guint pid;
guint cpu = s->cpu;
LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
- LttvProcessState *process = ts->running_process[cpu];
+ 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(process->pid == pid);
+ process = lttv_state_find_process(ts, ANY_CPU, pid);
if(likely(process != NULL)) {
process->state->s = LTTV_STATE_EXIT;
}
break;
}
}
- //if(i == num_cpus) /* process is not scheduled */
- //exit_process(s, process); // do nothing : wait for the schedchange to
- //delete the process.
+ if(i == num_cpus) /* process is not scheduled */
+ exit_process(s, process);
}
return FALSE;
return FALSE;
}
+static gboolean thread_brand(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 = s->cpu;
+ LttvProcessState *process = ts->running_process[cpu];
+
+ name = ltt_event_get_string(e, thf->f1);
+ process->brand = g_quark_from_string(name);
+
+ return FALSE;
+}
+
static gboolean enum_process_state(void *hook_data, void *call_data)
{
LttvTracefileState *s = (LttvTracefileState *)call_data;
LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
LttvProcessState *process = ts->running_process[cpu];
LttvProcessState *parent_process;
- LttField *f4, *f5, *f6;
- GQuark mode, submode, status;
+ LttField *f4, *f5, *f6, *f7;
+ GQuark type, mode, submode, status;
+ LttvExecutionState *es;
/* PID */
pid = ltt_event_get_unsigned(e, thf->f1);
/* 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),
+ /* type */
+ f4 = ltt_eventtype_field_by_name(et, LTT_FIELD_TYPE);
+ type = 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),
+ /* mode */
+ f5 = ltt_eventtype_field_by_name(et, LTT_FIELD_MODE);
+ mode = 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),
+ /* submode */
+ f6 = ltt_eventtype_field_by_name(et, LTT_FIELD_SUBMODE);
+ submode = ltt_enum_string_get(ltt_field_type(f6),
ltt_event_get_unsigned(e, f6));
+ /* status */
+ f7 = ltt_eventtype_field_by_name(et, LTT_FIELD_STATUS);
+ status = ltt_enum_string_get(ltt_field_type(f7),
+ ltt_event_get_unsigned(e, f7));
+
/* 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) {
&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) {
+ if(type == LTTV_STATE_KERNEL_THREAD) {
/* Only keep the bottom */
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_SYSCALL;
+ es->s = status;
+ es->n = submode;
} else {
/* On top of it : */
- LttvExecutionState *es;
es = process->state = &g_array_index(process->execution_stack,
LttvExecutionState, 1);
- es->t = mode;
+ es->t = LTTV_STATE_USER_MODE;
es->s = status;
es->n = submode;
}
-#endif //0
-
+#if 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;
}
+#endif //0
} 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.
+ * We know for sure if it is a user space thread.
*/
process->ppid = parent_pid;
process->name = g_quark_from_string(command);
+ es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
+ if(type != LTTV_STATE_KERNEL_THREAD)
+ es->t = LTTV_STATE_USER_MODE;
/* Don't mess around with the stack, it will eventually become
* ok after the end of state dump. */
}
/* Find the eventtype id for the following events and register the
associated by id hooks. */
- hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 17);
- hooks = g_array_set_size(hooks, 17); // Max possible number of hooks.
+ hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 18);
+ hooks = g_array_set_size(hooks, 18); // Max possible number of hooks.
hn = 0;
ret = lttv_trace_find_hook(ts->parent.t,
process_exec, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
if(ret) hn--;
+ ret = lttv_trace_find_hook(ts->parent.t,
+ LTT_FACILITY_USER_GENERIC, LTT_EVENT_THREAD_BRAND,
+ LTT_FIELD_NAME, 0, 0,
+ thread_brand, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+ if(ret) hn--;
+
/* statedump-related hooks */
ret = lttv_trace_find_hook(ts->parent.t,
LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
static void module_init()
{
- LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
+ LTTV_STATE_UNNAMED = g_quark_from_string("UNNAMED");
+ LTTV_STATE_UNBRANDED = g_quark_from_string("UNBRANDED");
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_WAIT = g_quark_from_string("WAIT");
LTTV_STATE_RUN = g_quark_from_string("RUN");
LTTV_STATE_DEAD = g_quark_from_string("DEAD");
+ LTTV_STATE_USER_THREAD = g_quark_from_string("USER_THREAD");
+ LTTV_STATE_KERNEL_THREAD = g_quark_from_string("KERNEL_THREAD");
LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
LTTV_STATE_PROCESSES = g_quark_from_string("processes");
LTTV_STATE_PROCESS = g_quark_from_string("process");
LTT_EVENT_ENUM_PROCESS_STATE = g_quark_from_string("enumerate_process_state");
LTT_EVENT_FUNCTION_ENTRY = g_quark_from_string("function_entry");
LTT_EVENT_FUNCTION_EXIT = g_quark_from_string("function_exit");
+ LTT_EVENT_THREAD_BRAND = g_quark_from_string("thread_brand");
LTT_FIELD_SYSCALL_ID = g_quark_from_string("syscall_id");
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_TYPE = g_quark_from_string("type");
LTT_FIELD_MODE = g_quark_from_string("mode");
LTT_FIELD_SUBMODE = g_quark_from_string("submode");
LTT_FIELD_STATUS = g_quark_from_string("status");