fix syscall table
[lttv.git] / ltt / branches / poly / lttv / lttv / state.c
index de2f16ed1f69a146e8355dc1186d1839bbb7d398..6aae5ad9e6658c7655d4a7f6e5b7f2824b67953c 100644 (file)
@@ -70,6 +70,7 @@ GQuark
     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;
@@ -1354,7 +1355,9 @@ typedef struct _LttvNameTables {
   GQuark *trap_names;
   guint nb_traps;
   GQuark *irq_names;
+  guint nb_irqs;
   GQuark *soft_irq_names;
+  guint nb_softirqs;
 } LttvNameTables;
 
 
@@ -1412,6 +1415,12 @@ create_name_tables(LttvTraceState *tcs)
 
     for(i = 0 ; i < nb ; i++) {
       name_tables->syscall_names[i] = ltt_enum_string_get(t, i);
+      if(!name_tables->syscall_names[i]) {
+        GString *string = g_string_new("");
+        g_string_printf(string, "syscall %u", i);
+        name_tables->syscall_names[i] = g_quark_from_string(string->str);
+        g_string_free(string, TRUE);
+      }
     }
 
     //name_tables->syscall_names = g_new(GQuark, 256);
@@ -1473,12 +1482,14 @@ create_name_tables(LttvTraceState *tcs)
     }
     */
 
+    name_tables->nb_irqs = 256;
     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->nb_irqs = 0;
     name_tables->irq_names = NULL;
   }
   /*
@@ -1488,6 +1499,7 @@ create_name_tables(LttvTraceState *tcs)
   }
   */
 
+  name_tables->nb_softirqs = 256;
   name_tables->soft_irq_names = g_new(GQuark, 256);
   for(i = 0 ; i < 256 ; i++) {
     g_string_printf(fe_name, "softirq %d", i);
@@ -1517,6 +1529,8 @@ get_name_tables(LttvTraceState *tcs)
   tcs->nb_traps = name_tables->nb_traps;
   tcs->irq_names = name_tables->irq_names;
   tcs->soft_irq_names = name_tables->soft_irq_names;
+  tcs->nb_irqs = name_tables->nb_irqs;
+  tcs->nb_softirqs = name_tables->nb_softirqs;
 }
 
 
@@ -1802,7 +1816,10 @@ lttv_state_find_process_or_create(LttvTraceState *ts, guint cpu, guint pid,
                 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;
@@ -1939,9 +1956,19 @@ static gboolean irq_entry(void *hook_data, void *call_data)
   LttField *f = thf->f1;
 
   LttvExecutionSubmode submode;
+  guint64 irq = ltt_event_get_unsigned(e, f);
+  guint64 nb_irqs = ((LttvTraceState *)(s->parent.t_context))->nb_irqs;
+  GString *string;
 
-  submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[
-      ltt_event_get_unsigned(e, f)];
+  if(irq < nb_irqs) {
+    submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[irq];
+  } else {
+    /* Fixup an incomplete irq table */
+    GString *string = g_string_new("");
+    g_string_printf(string, "irq %llu", irq);
+    submode = g_quark_from_string(string->str);
+    g_string_free(string, TRUE);
+  }
 
   /* Do something with the info about being in user or system mode when int? */
   push_state(s, LTTV_STATE_IRQ, submode);
@@ -1979,9 +2006,19 @@ static gboolean soft_irq_entry(void *hook_data, void *call_data)
   LttField *f = thf->f1;
 
   LttvExecutionSubmode submode;
+  guint64 softirq = ltt_event_get_unsigned(e, f);
+  guint64 nb_softirqs = ((LttvTraceState *)(s->parent.t_context))->nb_softirqs;
+  GString *string;
 
-  submode = ((LttvTraceState *)(s->parent.t_context))->soft_irq_names[
-      ltt_event_get_long_unsigned(e, f)];
+  if(softirq < nb_softirqs) {
+    submode = ((LttvTraceState *)(s->parent.t_context))->soft_irq_names[softirq];
+  } else {
+    /* Fixup an incomplete irq table */
+    GString *string = g_string_new("");
+    g_string_printf(string, "softirq %llu", softirq);
+    submode = g_quark_from_string(string->str);
+    g_string_free(string, TRUE);
+  }
 
   /* Do something with the info about being in user or system mode when int? */
   push_state(s, LTTV_STATE_SOFT_IRQ, submode);
@@ -2346,6 +2383,69 @@ static gboolean thread_brand(void *hook_data, void *call_data)
   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;
+
+  if(process->type == LTTV_STATE_KERNEL_THREAD) {
+    es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
+    if(es->t == LTTV_STATE_MODE_UNKNOWN) {
+      es->t = LTTV_STATE_SYSCALL;
+      es->s = LTTV_STATE_WAIT;
+      es->n = LTTV_STATE_SUBMODE_NONE;
+      es->entry = *timestamp;
+      es->change = *timestamp;
+      es->cum_cpu_time = ltt_time_zero;
+    }
+  } else {
+    es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
+    if(es->t == LTTV_STATE_MODE_UNKNOWN) {
+      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;
+
+      if(process->execution_stack->len == 1) {
+        /* Still in user mode, means never scheduled */
+        process->execution_stack =
+          g_array_set_size(process->execution_stack, 2);
+        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;
@@ -2423,9 +2523,15 @@ static gboolean enum_process_state(void *hook_data, void *call_data)
       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 {
       /* User space process :
        * bottom : user mode
@@ -2441,9 +2547,12 @@ static gboolean enum_process_state(void *hook_data, void *call_data)
       // 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);
-#if 0
       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;
@@ -2468,7 +2577,8 @@ static gboolean enum_process_state(void *hook_data, void *call_data)
     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
@@ -2515,8 +2625,8 @@ void lttv_state_add_event_hooks(LttvTracesetState *self)
     /* 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,
@@ -2617,6 +2727,12 @@ void lttv_state_add_event_hooks(LttvTracesetState *self)
         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,
@@ -3323,6 +3439,7 @@ static void module_init()
   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");
This page took 0.026982 seconds and 4 git commands to generate.