wait fork state now ok
[lttv.git] / ltt / branches / poly / lttv / modules / gui / controlflow / eventhooks.c
index 13c1e296280ffc50a95a99858f2a932376d5dafb..c53afe9c43c79871b8a294b7424fbe21f420acef 100644 (file)
 /* Event hooks are the drawing hooks called during traceset read. They draw the
  * icons, text, lines and background color corresponding to the events read.
  *
- * Two hooks are used for drawing : draw_before and draw_after hooks. The
- * draw_before is called before the state update that occurs with an event and
- * the draw_after hook is called after this state update.
+ * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
+ * before_schedchange is called before the state update that occurs with an event and
+ * the after_schedchange hook is called after this state update.
  *
- * The draw_before hooks fulfill the task of drawing the visible objects that
- * corresponds to the data accumulated by the draw_after hook.
+ * The before_schedchange hooks fulfill the task of drawing the visible objects that
+ * corresponds to the data accumulated by the after_schedchange hook.
  *
- * The draw_after hook accumulates the data that need to be shown on the screen
- * (items) into a queue. Then, the next draw_before hook will draw what that
+ * The after_schedchange hook accumulates the data that need to be shown on the screen
+ * (items) into a queue. Then, the next before_schedchange hook will draw what that
  * queue contains. That's the Right Way (TM) of drawing items on the screen,
  * because we need to draw the background first (and then add icons, text, ...
  * over it), but we only know the length of a background region once the state
- * corresponding to it is over, which happens to be at the next draw_before
+ * corresponding to it is over, which happens to be at the next before_schedchange
  * hook.
  *
  * We also have a hook called at the end of a chunk to draw the information left
@@ -224,9 +224,9 @@ void request_background_data(ControlFlowData *control_flow_data)
  * @return The widget created.
  */
 GtkWidget *
-h_guicontrolflow(Tab *tab, LttvTracesetSelector * s, char * key)
+h_guicontrolflow(Tab *tab)
 {
-  g_info("h_guicontrolflow, %p, %p, %s", tab, s, key);
+  g_info("h_guicontrolflow, %p", tab);
   ControlFlowData *control_flow_data = guicontrolflow() ;
   
   control_flow_data->tab = tab;
@@ -266,7 +266,7 @@ int event_selected_hook(void *hook_data, void *call_data)
 }
 
 
-static __inline PropertiesLine prepare_line(LttvProcessState *process)
+static __inline PropertiesLine prepare_status_line(LttvProcessState *process)
 {
   PropertiesLine prop_line;
   prop_line.line_width = 2;
@@ -274,7 +274,7 @@ static __inline PropertiesLine prepare_line(LttvProcessState *process)
   prop_line.y = MIDDLE;
   //GdkColormap *colormap = gdk_colormap_get_system();
   
-  g_debug("prepare_line for state : %s", g_quark_to_string(process->state->s));
+  g_debug("prepare_status_line for state : %s", g_quark_to_string(process->state->s));
 
   /* color of line : status of the process */
   if(process->state->s == LTTV_STATE_UNNAMED)
@@ -283,8 +283,8 @@ static __inline PropertiesLine prepare_line(LttvProcessState *process)
     prop_line.color = drawing_colors[COL_WAIT_FORK];
   else if(process->state->s == LTTV_STATE_WAIT_CPU)
     prop_line.color = drawing_colors[COL_WAIT_CPU];
-  else if(process->state->s == LTTV_STATE_EXIT)
-    prop_line.color = drawing_colors[COL_EXIT];
+  else if(process->state->s == LTTV_STATE_ZOMBIE)
+    prop_line.color = drawing_colors[COL_ZOMBIE];
   else if(process->state->s == LTTV_STATE_WAIT)
     prop_line.color = drawing_colors[COL_WAIT];
   else if(process->state->s == LTTV_STATE_RUN)
@@ -303,7 +303,7 @@ static __inline PropertiesLine prepare_line(LttvProcessState *process)
 
 
 
-/* draw_before_hook
+/* before_schedchange_hook
  * 
  * This function basically draw lines and icons. Two types of lines are drawn :
  * one small (3 pixels?) representing the state of the process and the second
@@ -321,7 +321,7 @@ static __inline PropertiesLine prepare_line(LttvProcessState *process)
  */
 
 
-int draw_before_hook(void *hook_data, void *call_data)
+int before_schedchange_hook(void *hook_data, void *call_data)
 {
   EventsRequest *events_request = (EventsRequest*)hook_data;
   ControlFlowData *control_flow_data = events_request->viewer_data;
@@ -397,9 +397,11 @@ int draw_before_hook(void *hook_data, void *call_data)
                 &height,
                 &hashed_process_data) == 1)
         {
+          g_assert(pid_out == 0 || pid_out != process->ppid);
           /* Process not present */
           processlist_add(process_list,
               pid_out,
+              process->ppid,
               &birth,
               tfc->t_context->index,
               name,
@@ -457,7 +459,7 @@ int draw_before_hook(void *hook_data, void *call_data)
 
           {
             /* Draw the line */
-            PropertiesLine prop_line = prepare_line(process);
+            PropertiesLine prop_line = prepare_status_line(process);
             draw_line((void*)&prop_line, (void*)&draw_context);
 
           }
@@ -497,9 +499,11 @@ int draw_before_hook(void *hook_data, void *call_data)
                 &height,
                 &hashed_process_data) == 1)
         {
+          g_assert(pid_in == 0 || pid_in != process->ppid);
           /* Process not present */
           processlist_add(process_list,
               pid_in,
+              process->ppid,
               &birth,
               tfc->t_context->index,
               name,
@@ -557,7 +561,7 @@ int draw_before_hook(void *hook_data, void *call_data)
 
           {
             /* Draw the line */
-            PropertiesLine prop_line = prepare_line(process);
+            PropertiesLine prop_line = prepare_status_line(process);
             draw_line((void*)&prop_line, (void*)&draw_context);
           }
 
@@ -835,7 +839,7 @@ int draw_before_hook(void *hook_data, void *call_data)
       prop_text_out.foreground->green = 0xffff;
       prop_text_out.foreground->blue = 0x0000;
     }
-    else if(process_out->state->s == LTTV_STATE_EXIT)
+    else if(process_out->state->s == LTTV_STATE_ZOMBIE)
     {
       prop_text_out.foreground->red = 0xffff;
       prop_text_out.foreground->green = 0x0000;
@@ -868,7 +872,7 @@ int draw_before_hook(void *hook_data, void *call_data)
       prop_text_out.text = "WF->";
     else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
       prop_text_out.text = "WC->";
-    else if(process_out->state->s == LTTV_STATE_EXIT)
+    else if(process_out->state->s == LTTV_STATE_ZOMBIE)
       prop_text_out.text = "E->";
     else if(process_out->state->s == LTTV_STATE_WAIT)
       prop_text_out.text = "W->";
@@ -911,7 +915,7 @@ int draw_before_hook(void *hook_data, void *call_data)
       prop_line_out.color->green = 0xffff;
       prop_line_out.color->blue = 0x0000;
     }
-    else if(process_out->state->s == LTTV_STATE_EXIT)
+    else if(process_out->state->s == LTTV_STATE_ZOMBIE)
     {
       prop_line_out.color->red = 0xffff;
       prop_line_out.color->green = 0x0000;
@@ -1059,7 +1063,7 @@ int draw_before_hook(void *hook_data, void *call_data)
       prop_text_in.foreground->green = 0xffff;
       prop_text_in.foreground->blue = 0x0000;
     }
-    else if(process_in->state->s == LTTV_STATE_EXIT)
+    else if(process_in->state->s == LTTV_STATE_ZOMBIE)
     {
       prop_text_in.foreground->red = 0xffff;
       prop_text_in.foreground->green = 0x0000;
@@ -1093,7 +1097,7 @@ int draw_before_hook(void *hook_data, void *call_data)
       prop_text_in.text = "WF->";
     else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
       prop_text_in.text = "WC->";
-    else if(process_in->state->s == LTTV_STATE_EXIT)
+    else if(process_in->state->s == LTTV_STATE_ZOMBIE)
       prop_text_in.text = "E->";
     else if(process_in->state->s == LTTV_STATE_WAIT)
       prop_text_in.text = "W->";
@@ -1134,7 +1138,7 @@ int draw_before_hook(void *hook_data, void *call_data)
       prop_line_in.color->green = 0xffff;
       prop_line_in.color->blue = 0x0000;
     }
-    else if(process_in->state->s == LTTV_STATE_EXIT)
+    else if(process_in->state->s == LTTV_STATE_ZOMBIE)
     {
       prop_line_in.color->red = 0xffff;
       prop_line_in.color->green = 0x0000;
@@ -1191,7 +1195,7 @@ int draw_before_hook(void *hook_data, void *call_data)
 
 }
 
-/* draw_after_hook
+/* after_schedchange_hook
  * 
  * The draw after hook is called by the reading API to have a
  * particular event drawn on the screen.
@@ -1201,7 +1205,7 @@ int draw_before_hook(void *hook_data, void *call_data)
  * This function adds items to be drawn in a queue for each process.
  * 
  */
-int draw_after_hook(void *hook_data, void *call_data)
+int after_schedchange_hook(void *hook_data, void *call_data)
 {
   EventsRequest *events_request = (EventsRequest*)hook_data;
   ControlFlowData *control_flow_data = events_request->viewer_data;
@@ -1270,9 +1274,11 @@ int draw_after_hook(void *hook_data, void *call_data)
               &height,
               &hashed_process_data_in) == 1)
       {
+        g_assert(pid_in == 0 || pid_in != process_in->ppid);
         /* Process not present */
         processlist_add(process_list,
             pid_in,
+            process_in->ppid,
             &birth,
             tfc->t_context->index,
             name,
@@ -1295,13 +1301,7 @@ int draw_after_hook(void *hook_data, void *call_data)
           width,
           &hashed_process_data_in->x);
     }
-  } else if(strcmp(
-          ltt_eventtype_name(ltt_event_eventtype(e)),"process") == 0) {
-    /* We are in a fork or exit event */
-
-
   }
-
   return 0;
 
 
@@ -1509,7 +1509,7 @@ int draw_after_hook(void *hook_data, void *call_data)
       prop_text_out.foreground->green = 0xffff;
       prop_text_out.foreground->blue = 0x0000;
     }
-    else if(process_out->state->s == LTTV_STATE_EXIT)
+    else if(process_out->state->s == LTTV_STATE_ZOMBIE)
     {
       prop_text_out.foreground->red = 0xffff;
       prop_text_out.foreground->green = 0x0000;
@@ -1541,7 +1541,7 @@ int draw_after_hook(void *hook_data, void *call_data)
       prop_text_out.text = "WF";
     else if(process_out->state->s == LTTV_STATE_WAIT_CPU)
       prop_text_out.text = "WC";
-    else if(process_out->state->s == LTTV_STATE_EXIT)
+    else if(process_out->state->s == LTTV_STATE_ZOMBIE)
       prop_text_out.text = "E";
     else if(process_out->state->s == LTTV_STATE_WAIT)
       prop_text_out.text = "W";
@@ -1650,7 +1650,7 @@ int draw_after_hook(void *hook_data, void *call_data)
       prop_text_in.foreground->green = 0xffff;
       prop_text_in.foreground->blue = 0x0000;
     }
-    else if(process_in->state->s == LTTV_STATE_EXIT)
+    else if(process_in->state->s == LTTV_STATE_ZOMBIE)
     {
       prop_text_in.foreground->red = 0xffff;
       prop_text_in.foreground->green = 0x0000;
@@ -1683,7 +1683,7 @@ int draw_after_hook(void *hook_data, void *call_data)
       prop_text_in.text = "WF";
     else if(process_in->state->s == LTTV_STATE_WAIT_CPU)
       prop_text_in.text = "WC";
-    else if(process_in->state->s == LTTV_STATE_EXIT)
+    else if(process_in->state->s == LTTV_STATE_ZOMBIE)
       prop_text_in.text = "E";
     else if(process_in->state->s == LTTV_STATE_WAIT)
       prop_text_in.text = "W";
@@ -1759,7 +1759,115 @@ int draw_after_hook(void *hook_data, void *call_data)
 #endif //0
 }
 
+/* after_fork_hook
+ * 
+ * Create the processlist entry for the child process. Put the last
+ * position in x at the current time value.
+ *
+ * @param hook_data ControlFlowData structure of the viewer. 
+ * @param call_data Event context.
+ *
+ * This function adds items to be drawn in a queue for each process.
+ * 
+ */
+int after_fork_hook(void *hook_data, void *call_data)
+{
+  EventsRequest *events_request = (EventsRequest*)hook_data;
+  ControlFlowData *control_flow_data = events_request->viewer_data;
+
+  LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+
+  LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+  LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
+
+  LttEvent *e;
+  e = tfc->e;
+
+  LttTime evtime = ltt_event_time(e);
+  TimeWindow time_window = 
+    lttvwindow_get_time_window(control_flow_data->tab);
+
+  LttTime end_time = ltt_time_add(time_window.start_time,
+                                    time_window.time_width);
+
+  if(ltt_time_compare(evtime, time_window.start_time) == -1
+        || ltt_time_compare(evtime, end_time) == 1)
+            return;
+
+  guint width = control_flow_data->drawing->width;
+
+  if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"process") == 0) {
+
+    guint sub_id;
+    guint child_pid;
+    {
+      LttField *f = ltt_event_field(e);
+      LttField *element;
+      element = ltt_field_member(f,0);
+      sub_id = ltt_event_get_long_unsigned(e,element);
+      element = ltt_field_member(f,1);
+      child_pid = ltt_event_get_long_unsigned(e,element);
+    }
+
+    if(sub_id == 2) { /* fork */
+
+      /* Add process to process list (if not present) */
+      LttvProcessState *process_child;
+      LttTime birth;
+      guint y_child = 0, height = 0, pl_height = 0;
+      HashedProcessData *hashed_process_data_child = NULL;
+
+      ProcessList *process_list =
+        guicontrolflow_get_process_list(control_flow_data);
+      
+
+      /* Find child in the list... */
+      process_child = lttv_state_find_process(tfs, child_pid);
+      /* It should exist, because we are after the state update. */
+      g_assert(process_child != NULL);
+
+      birth = process_child->creation_time;
+      const gchar *name = g_quark_to_string(process_child->name);
+
+      if(processlist_get_process_pixels(process_list,
+              child_pid,
+              &birth,
+              tfc->t_context->index,
+              &y_child,
+              &height,
+              &hashed_process_data_child) == 1)
+      {
+        g_assert(child_pid == 0 || child_pid != process_child->ppid);
+        /* Process not present */
+        processlist_add(process_list,
+            child_pid,
+            process_child->ppid,
+            &birth,
+            tfc->t_context->index,
+            name,
+            &pl_height,
+            &hashed_process_data_child);
+        processlist_get_process_pixels(process_list,
+                child_pid,
+                &birth,
+                tfc->t_context->index,
+                &y_child,
+                &height,
+                &hashed_process_data_child);
+        drawing_insert_square( control_flow_data->drawing, y_child, height);
+      }
+
+      convert_time_to_pixels(
+          time_window.start_time,
+          end_time,
+          evtime,
+          width,
+          &hashed_process_data_child->x);
+    }
+  }
+  return 0;
 
+}
 
 
 gint update_time_window_hook(void *hook_data, void *call_data)
@@ -1987,12 +2095,15 @@ gint traceset_notify(void *hook_data, void *call_data)
   Drawing_t *drawing = control_flow_data->drawing;
   GtkWidget *widget = drawing->drawing_area;
 
-  drawing->damage_begin = 0;
-  drawing->damage_end = drawing->width;
 
   drawing_clear(control_flow_data->drawing);
   processlist_clear(control_flow_data->process_list);
+  redraw_notify(control_flow_data, NULL);
 
+  request_background_data(control_flow_data);
+#if 0
+  drawing->damage_begin = 0;
+  drawing->damage_end = drawing->width;
   if(drawing->damage_begin < drawing->damage_end)
   {
     drawing_data_request(drawing,
@@ -2007,8 +2118,7 @@ gint traceset_notify(void *hook_data, void *call_data)
                              0,0,
                              drawing->width,
                              drawing->height);
-
-  request_background_data(control_flow_data);
+#endif //0
  
   return FALSE;
 }
@@ -2156,44 +2266,6 @@ typedef struct _ClosureData {
 } ClosureData;
   
 
-/* find_process
- * Input : A trace and a PID.
- * 
- * - For each CPU of the trace
- *   - Search in trace states by PID and CPU key
- *     - For each ProcessState found
- *       - If state is not LTTV_STATE_WAIT
- *        - Then this process state is the current one for this PID.
- *        - Stop search.
- * - If no ProcessState found, return NULL.
- * - If all ProcessState were in LTTV_STATE_WAIT state, return one of
- *   them arbitrarily.
- *   Than means state is LTTV_STATE_WAIT, CPU unknown.
- */
-static LttvProcessState *find_process(LttvTraceState *tstate, guint pid)
-{
-  guint cpu_num = ltt_trace_per_cpu_tracefile_number(tstate->parent.t);
-  GQuark cpu_name;
-  guint i;
-  
-  LttvProcessState *real_state = NULL;
-  
-  for(i=0;i<cpu_num;i++) {
-    cpu_name = ((LttvTracefileState*)tstate->parent.tracefiles[i])->cpu_name;
-    LttvProcessState *state = lttv_state_find_process_from_trace(tstate,
-                                                                 cpu_name,
-                                                                 pid);
-    
-    if(state != NULL) {
-      real_state = state;
-      if(state->state->s != LTTV_STATE_WAIT)
-        break;
-    }
-  }
-  return real_state;
-}
-
-
 void draw_closure(gpointer key, gpointer value, gpointer user_data)
 {
   ProcessInfo *process_info = (ProcessInfo*)key;
@@ -2229,11 +2301,14 @@ void draw_closure(gpointer key, gpointer value, gpointer user_data)
      * be added after the state update.  */
     g_assert(lttv_traceset_number(tsc->ts) > 0);
 
-    LttvTraceState *trace_state =
-      (LttvTraceState*)tsc->traces[process_info->trace_num];
+    /* tracefiles[0] is ok here, because we draw for every PID, and
+     * assume CPU 0 for PID 0 //FIXME */
+    LttvTracefileState *tfs =
+      (LttvTracefileState*)tsc->traces[process_info->trace_num]->tracefiles[0];
 
     LttvProcessState *process;
-    process = find_process(trace_state, process_info->pid);
+    process = lttv_state_find_process(tfs,
+                                      process_info->pid);
 
     if(process != NULL) {
       
@@ -2301,7 +2376,7 @@ void draw_closure(gpointer key, gpointer value, gpointer user_data)
 
         {
           /* Draw the line */
-          PropertiesLine prop_line = prepare_line(process);
+          PropertiesLine prop_line = prepare_status_line(process);
           draw_line((void*)&prop_line, (void*)&draw_context);
 
         }
This page took 0.02986 seconds and 4 git commands to generate.