LTT_EVENT_FREE,
LTT_EVENT_EXEC,
LTT_EVENT_ENUM_PROCESS_STATE,
+ LTT_EVENT_STATEDUMP_END,
LTT_EVENT_FUNCTION_ENTRY,
LTT_EVENT_FUNCTION_EXIT,
LTT_EVENT_THREAD_BRAND;
NULL, cpu, pid, 0, 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);
+ process->execution_stack =
+ g_array_set_size(process->execution_stack, 1);
+ process->state = es =
+ &g_array_index(process->execution_stack, LttvExecutionState, 0);
es->t = LTTV_STATE_MODE_UNKNOWN;
}
return process;
return FALSE;
}
+static void fix_process(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ LttvProcessState *process;
+ LttvExecutionState *es;
+ process = (LttvProcessState *)value;
+ LttvTracefileContext *tfc = (LttvTracefileContext *)user_data;
+ LttTime *timestamp = (LttTime*)user_data;
+
+printf("%s %s\n", g_quark_to_string(process->type), g_quark_to_string(process->state->t));
+
+ if(process->type == LTTV_STATE_KERNEL_THREAD) {
+ if(process->state->t == LTTV_STATE_MODE_UNKNOWN) {
+ process->state->t = LTTV_STATE_SYSCALL;
+ process->state->s = LTTV_STATE_WAIT;
+ process->state->n = LTTV_STATE_SUBMODE_NONE;
+ }
+ } else {
+ if(process->state->t == LTTV_STATE_MODE_UNKNOWN) {
+ 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 = *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,
+ 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->cum_cpu_time = ltt_time_zero;
+ es->s = LTTV_STATE_WAIT;
+ }
+ }
+}
+
+static gboolean statedump_end(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+ LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
+ LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+ LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
+ LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
+
+ /* For all processes */
+ /* if kernel thread, if stack[0] is unknown, set to syscall mode, wait */
+ /* else, if stack[0] is unknown, set to user mode, running */
+
+ g_hash_table_foreach(ts->processes, fix_process, &tfc->timestamp);
+}
+
static gboolean enum_process_state(void *hook_data, void *call_data)
{
LttvTracefileState *s = (LttvTracefileState *)call_data;
/* Keep the stack bottom : a running user mode */
/* Disabled because of inconsistencies in the current statedump states. */
if(type == LTTV_STATE_KERNEL_THREAD) {
- /* Only keep the bottom */
+ /* Only keep the bottom
+ * FIXME Kernel thread : can be in syscall or interrupt or trap. */
+ /* Will cause expected trap when in fact being syscall (even after end of
+ * statedump event)
+ * Will cause expected interrupt when being syscall. (only before end of
+ * statedump event) */
+ // This will cause a "popping last state on stack, ignoring it."
process->execution_stack = g_array_set_size(process->execution_stack, 1);
es = process->state = &g_array_index(process->execution_stack,
LttvExecutionState, 0);
+ process->type = LTTV_STATE_KERNEL_THREAD;
+ es->t = LTTV_STATE_MODE_UNKNOWN;
+ es->s = LTTV_STATE_UNNAMED;
+ es->n = LTTV_STATE_SUBMODE_UNKNOWN;
+#if 0
es->t = LTTV_STATE_SYSCALL;
es->s = status;
es->n = submode;
+#endif //0
} else {
- /* On top of it : */
+ /* User space process :
+ * bottom : user mode
+ * either currently running or scheduled out.
+ * can be scheduled out because interrupted in (user mode or in syscall)
+ * or because of an explicit call to the scheduler in syscall. Note that
+ * the scheduler call comes after the irq_exit, so never in interrupt
+ * context. */
+ // temp workaround : set size to 1 : only have user mode bottom of stack.
+ // will cause g_info message of expected syscall mode when in fact being
+ // in user mode. Can also cause expected trap when in fact being user
+ // mode in the event of a page fault reenabling interrupts in the handler.
+ // Expected syscall and trap can also happen after the end of statedump
+ // This will cause a "popping last state on stack, ignoring it."
+ process->execution_stack = g_array_set_size(process->execution_stack, 1);
es = process->state = &g_array_index(process->execution_stack,
- LttvExecutionState, 1);
+ LttvExecutionState, 0);
+ es->t = LTTV_STATE_MODE_UNKNOWN;
+ es->s = LTTV_STATE_UNNAMED;
+ es->n = LTTV_STATE_SUBMODE_UNKNOWN;
+#if 0
es->t = LTTV_STATE_USER_MODE;
es->s = status;
es->n = submode;
+#endif //0
}
#if 0
/* UNKNOWN STATE */
process->ppid = parent_pid;
process->tgid = tgid;
process->name = g_quark_from_string(command);
- es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
+ 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
/* Find the eventtype id for the following events and register the
associated by id hooks. */
- hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 18);
- hooks = g_array_set_size(hooks, 18); // Max possible number of hooks.
+ hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 19);
+ hooks = g_array_set_size(hooks, 19); // Max possible number of hooks.
hn = 0;
ret = lttv_trace_find_hook(ts->parent.t,
enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
if(ret) hn--;
+ ret = lttv_trace_find_hook(ts->parent.t,
+ LTT_FACILITY_STATEDUMP, LTT_EVENT_STATEDUMP_END,
+ 0, 0, 0,
+ statedump_end, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
+ if(ret) hn--;
+
ret = lttv_trace_find_hook(ts->parent.t,
LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
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_EVENT_STATEDUMP_END = g_quark_from_string("statedump_end");
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");