add usertrace support
[lttv.git] / ltt / branches / poly / lttv / lttv / state.c
index 3602c677f746c8330fe9a1df798eb6a26238fc7c..5eb533facfcb4c068426dba11726dd0881601442 100644 (file)
@@ -54,6 +54,7 @@ GQuark
     LTT_EVENT_SOFT_IRQ_EXIT,
     LTT_EVENT_SCHEDCHANGE,
     LTT_EVENT_FORK,
+    LTT_EVENT_KERNEL_THREAD,
     LTT_EVENT_EXIT,
     LTT_EVENT_FREE,
     LTT_EVENT_EXEC,
@@ -258,18 +259,30 @@ init(LttvTracesetState *self, LttvTraceset *ts)
     get_max_time(tcs);
 
     nb_tracefile = tc->tracefiles->len;
-#if 0
+    tcs->processes = NULL;
+    tcs->running_process = g_new(LttvProcessState*, 
+                                 ltt_trace_get_num_cpu(tc->t));
+    restore_init_state(tcs);
     for(j = 0 ; j < nb_tracefile ; j++) {
       tfcs = 
           LTTV_TRACEFILE_STATE(g_array_index(tc->tracefiles,
                                           LttvTracefileContext*, j));
       tfcs->tracefile_name = ltt_tracefile_name(tfcs->parent.tf);
+                       tfcs->cpu = ltt_tracefile_cpu(tfcs->parent.tf);
+                       
+                       if(ltt_tracefile_tid(tfcs->parent.tf) != 0) {
+                               /* It's a Usertrace */
+                               LttvProcessState *process;
+                               LttTime timestamp = 
+                                       ltt_interpolate_time_from_tsc(tfcs->parent.tf,
+                                                       ltt_tracefile_creation(tfcs->parent.tf));
+                               process = lttv_state_find_process_or_create(
+                                                                                               tcs,
+                                                                                               0, ltt_tracefile_tid(tfcs->parent.tf),
+                                                                                               &timestamp);
+                               process->usertrace = tfcs;
+                       }
     }
-#endif //0
-    tcs->processes = NULL;
-    tcs->running_process = g_new(LttvProcessState*, 
-                                 ltt_trace_get_num_cpu(tc->t));
-    restore_init_state(tcs);
   }
 }
 
@@ -939,8 +952,8 @@ static void push_state(LttvTracefileState *tfs, LttvExecutionMode t,
 {
   LttvExecutionState *es;
   
-  guint cpu = ltt_tracefile_num(tfs->parent.tf);
   LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
+  guint cpu = tfs->cpu;
 
 #ifdef HASH_TABLE_DEBUG
   hash_table_check(ts->processes);
@@ -966,7 +979,7 @@ static void push_state(LttvTracefileState *tfs, LttvExecutionMode t,
 
 static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
 {
-  guint cpu = ltt_tracefile_num(tfs->parent.tf);
+  guint cpu = tfs->cpu;
   LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
   LttvProcessState *process = ts->running_process[cpu];
 
@@ -1017,6 +1030,9 @@ lttv_state_create_process(LttvTraceState *tcs, LttvProcessState *parent,
   process->name = name;
   //process->last_cpu = tfs->cpu_name;
   //process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
+       process->kernel_thread = 0;
+       process->usertrace = NULL;
+
   g_info("Process %u, core %p", process->pid, process);
   g_hash_table_insert(tcs->processes, process, process);
 
@@ -1082,10 +1098,17 @@ lttv_state_find_process_or_create(LttvTraceState *ts, guint cpu, guint pid,
     LttTime *timestamp)
 {
   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,
+  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;
 }
 
@@ -1239,9 +1262,10 @@ static gboolean soft_irq_exit(void *hook_data, void *call_data)
 static gboolean schedchange(void *hook_data, void *call_data)
 {
   LttvTracefileState *s = (LttvTracefileState *)call_data;
-  guint cpu = ltt_tracefile_num(s->parent.tf);
+  guint cpu = s->cpu;
   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;
@@ -1261,7 +1285,8 @@ static gboolean schedchange(void *hook_data, void *call_data)
        the wrongly attributed statistics. */
 
     //This test only makes sense once the state is known and if there is no
-    //missing events.
+    //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);
     //}
@@ -1274,8 +1299,8 @@ static gboolean schedchange(void *hook_data, void *call_data)
       else process->state->s = LTTV_STATE_WAIT;
       process->state->change = s->parent.timestamp;
     }
-
-    if(state_out == 32)
+               
+               if(state_out == 32)
        exit_process(s, process); /* EXIT_DEAD */
           /* see sched.h for states */
   }
@@ -1286,6 +1311,8 @@ static gboolean schedchange(void *hook_data, void *call_data)
                   &s->parent.timestamp);
   process->state->s = LTTV_STATE_RUN;
   process->cpu = cpu;
+       if(process->usertrace)
+               process->usertrace->cpu = cpu;
  // process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
   process->state->change = s->parent.timestamp;
   return FALSE;
@@ -1299,7 +1326,7 @@ static gboolean process_fork(void *hook_data, void *call_data)
   guint parent_pid;
   guint child_pid;
   LttvProcessState *zombie_process;
-  guint cpu = ltt_tracefile_num(s->parent.tf);
+  guint cpu = s->cpu;
   LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
   LttvProcessState *process = ts->running_process[cpu];
   LttvProcessState *child_process;
@@ -1345,8 +1372,10 @@ static gboolean process_fork(void *hook_data, void *call_data)
      *
      * Simply put a correct parent.
      */
-    g_assert(0); /* This is a problematic case : the process has been created
-                    before the fork event */
+               //It can also happen when created by a usertrace. In that case, it's
+               //correct.
+    //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);
@@ -1355,6 +1384,28 @@ static gboolean process_fork(void *hook_data, void *call_data)
   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 = s->cpu;
+  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)
 {
@@ -1363,7 +1414,7 @@ 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);
+  guint cpu = s->cpu;
   LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
   LttvProcessState *process = ts->running_process[cpu];
 
@@ -1416,8 +1467,9 @@ static gboolean process_free(void *hook_data, void *call_data)
         break;
       }
     }
-    if(i == num_cpus) /* process is not scheduled */
-      exit_process(s, process);
+    //if(i == num_cpus) /* process is not scheduled */
+      //exit_process(s, process);      // do nothing : wait for the schedchange to
+                       //delete the process.
   }
 
   return FALSE;
@@ -1431,7 +1483,7 @@ static gboolean process_exec(void *hook_data, void *call_data)
   LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
   LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
   //gchar *name;
-  guint cpu = ltt_tracefile_num(s->parent.tf);
+  guint cpu = s->cpu;
   LttvProcessState *process = ts->running_process[cpu];
 
   /* PID of the process to release */
@@ -1460,7 +1512,7 @@ static gboolean enum_process_state(void *hook_data, void *call_data)
   guint parent_pid;
   guint pid;
   gchar * command;
-  guint cpu = ltt_tracefile_num(s->parent.tf);
+  guint cpu = s->cpu;
   LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
   LttvProcessState *process = ts->running_process[cpu];
   LttvProcessState *parent_process;
@@ -1575,8 +1627,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), 14);
-    hooks = g_array_set_size(hooks, 14);
+    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_ARCH, LTT_EVENT_SYSCALL_ENTRY,
@@ -1638,29 +1690,35 @@ void lttv_state_add_event_hooks(LttvTracesetState *self)
         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, NULL, &g_array_index(hooks, LttvTraceHook, 10));
+        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, NULL, &g_array_index(hooks, LttvTraceHook, 11));
+        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, 12));
+        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, 13));
+        enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, 14));
     g_assert(!ret);
 
     
@@ -1685,7 +1743,7 @@ void lttv_state_add_event_hooks(LttvTracesetState *self)
         }
       }
     }
-    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;
   }
 }
@@ -1720,7 +1778,7 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self)
   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 */
@@ -1802,6 +1860,13 @@ static gboolean state_save_after_trace_hook(void *hook_data, void *call_data)
   return FALSE;
 }
 
+guint lttv_state_current_cpu(LttvTracefileState *tfs)
+{
+       return tfs->cpu;
+}
+
+
+
 #if 0
 static gboolean block_start(void *hook_data, void *call_data)
 {
@@ -2332,6 +2397,7 @@ static void module_init()
   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");
This page took 0.02742 seconds and 4 git commands to generate.