add InterruptFree()
[lttv.git] / ltt / branches / poly / lttv / modules / gui / interrupts / interrupts.c
index 718fa1bf49becdc3cbb3e5e2d4cc3fd094a0cd45..fd3ad580c2a33856a5ac9af236f1141514a1ae34 100644 (file)
  */
  
  /******************************************************************
- CPUID  | IRQID | Frequency | 
- The standard deviation (sigma) is based on: 
+   
+ The standard deviation  calculation is based on: 
  http://en.wikipedia.org/wiki/Standard_deviation
  
- sigma = sqrt(1/N Sum ((xi -Xa)^2))
- To compute the standard deviation, we pass  two EventRequests to LTTV. In 
- the first EventRequest, we  compute the average duration (Xa) of and the 
- frequency (N) each IrqID.  We store the information in an array  called 
- FirstRequestIrqExit.
- In the second  EventRequest, we compute the Sum ((xi -Xa)^2) 
-  
-    
+ Standard_deviation  = sqrt(1/N Sum ((xi -Xa)^2))
  
+ To compute the standard deviation, we need to make  EventRequests to LTTV. In 
+ the first EventRequest, we  compute the average duration (Xa)  and the 
+ frequency (N) of each IrqID.  We store the information calculated in the first 
+ EventRequest in an array  called  FirstRequestIrqExit.
+ In the second  EventRequest, we compute the Sum ((xi -Xa)^2) and store this information 
+ in a array called SumArray. The function CalculateDurationStandardDeviation() uses FirstRequestIrqExit 
+ and SumArray arrays to calculate the standard deviation.
+   
+
+
+CPUID: processor ID
+
+IrqId: IRQ ID
+
+Frequency (Hz): the number of interruptions per second (Hz)
+
+Total Duration (nsec): the sum of each interrupt duration in nsec
+
+Duration standard deviation (nsec):   taken from http://en.wikipedia.org/wiki/Standard_deviation
+Duration Standard_deviation  = sqrt(1/N Sum ((xi -Xa)^2)) where
+N: number of interrupts 
+xi: duration of an interrupt (nsec)
+Xa: average duration (nsec)
+
+Max IRQ handler duration (nsec) [time interval]:   the longest IRQ handler duration in nsec.  
+
+Average period (nsec): 1/frequency
+
  
+Period Standard_deviation  = sqrt(1/N Sum ((xi -Xa)^2)) where
+N: number of interrupts 
+xi: duration of an interrupt
+Xa: 1/frequency  
  
  *******************************************************************/
 
@@ -95,6 +117,7 @@ typedef struct
        guint irqId;
        guint frequency;
        guint64 sumOfDurations;
+       guint64 sumOfPeriods;
        
 }SumId;
 
@@ -143,8 +166,8 @@ static void FirstRequest(InterruptEventData *event_data );
 static guint64 get_interrupt_id(LttEvent *e);
 static gboolean trace_header(void *hook_data, void *call_data);
 static gboolean DisplayViewer (void *hook_data, void *call_data);
-static void calcul_duration(LttTime time_exit,  guint cpu_id,  InterruptEventData *event_data);
-static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit);
+static void CalculateData(LttTime time_exit,  guint cpu_id,  InterruptEventData *event_data);
+static void TotalDurationMaxIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit);
 static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data);
 static gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data);
 static gboolean SecondRequest(void *hook_data, void *call_data);
@@ -153,8 +176,11 @@ static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data);
 static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data);
 static void CalculateXi(LttEvent *event, InterruptEventData *event_data);
 static void  SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data);
-static int CalculateStandardDeviation(gint id, InterruptEventData *event_data);
-static void CalculateMaxIRQHandler(LttEvent *event);
+static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event_data);
+static int CalculatePeriodStandardDeviation(gint id, InterruptEventData *event_data);
+static int FrequencyInHZ(gint frequency, TimeWindow time_window);
+static  guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ);
+static void InterruptFree(InterruptEventData *event_viewer_data);
 /* Enumeration of the columns */
 enum{
   CPUID_COLUMN,
@@ -163,6 +189,8 @@ enum{
   DURATION_COLUMN,
   DURATION_STANDARD_DEV_COLUMN,
   MAX_IRQ_HANDLER_COLUMN,
+  AVERAGE_PERIOD,
+  PERIOD_STANDARD_DEV_COLUMN, 
   N_COLUMNS
 };
  
@@ -242,7 +270,9 @@ InterruptEventData *system_info(Tab *tab)
     G_TYPE_INT,     /* Frequency                  */
     G_TYPE_UINT64,   /* Duration                   */
     G_TYPE_INT,            /* standard deviation          */
-    G_TYPE_INT     /* Max IRQ handler             */
+    G_TYPE_STRING,         /* Max IRQ handler             */
+    G_TYPE_INT,                    /* Average period              */
+    G_TYPE_INT             /* period standard deviation   */
     );  
  
   event_viewer_data->TreeView = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->ListStore)); 
@@ -269,7 +299,7 @@ InterruptEventData *system_info(Tab *tab)
   gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
 
   renderer = gtk_cell_renderer_text_new ();
-  column = gtk_tree_view_column_new_with_attributes ("Frequency",
+  column = gtk_tree_view_column_new_with_attributes ("Frequency (Hz)",
                  renderer,
                  "text", FREQUENCY_COLUMN,
                  NULL);
@@ -278,7 +308,7 @@ InterruptEventData *system_info(Tab *tab)
   gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
 
   renderer = gtk_cell_renderer_text_new ();
-  column = gtk_tree_view_column_new_with_attributes ("Duration (nsec)",
+  column = gtk_tree_view_column_new_with_attributes ("Total Duration (nsec)",
                  renderer,
                  "text", DURATION_COLUMN,
                  NULL);
@@ -297,7 +327,7 @@ InterruptEventData *system_info(Tab *tab)
   gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
   
   renderer = gtk_cell_renderer_text_new ();
-  column = gtk_tree_view_column_new_with_attributes ("Max IRQ handler duration (nsec)",
+  column = gtk_tree_view_column_new_with_attributes ("Max IRQ handler duration (nsec) [time interval]",
                  renderer,
                  "text", MAX_IRQ_HANDLER_COLUMN,
                  NULL);
@@ -305,6 +335,25 @@ InterruptEventData *system_info(Tab *tab)
   gtk_tree_view_column_set_fixed_width (column, 250);
   gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
   
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes (" Average period (nsec)",
+                 renderer,
+                 "text", AVERAGE_PERIOD,
+                 NULL);
+  gtk_tree_view_column_set_alignment (column, 0.0);
+  gtk_tree_view_column_set_fixed_width (column, 200);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
+  
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes ("Period standard deviation (nsec)",
+                 renderer,
+                 "text", PERIOD_STANDARD_DEV_COLUMN,
+                 NULL);
+  gtk_tree_view_column_set_alignment (column, 0.0);
+  gtk_tree_view_column_set_fixed_width (column, 200);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
+  
+  
   
   event_viewer_data->SelectionTree = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data->TreeView));
   gtk_tree_selection_set_mode (event_viewer_data->SelectionTree, GTK_SELECTION_SINGLE);
@@ -323,11 +372,16 @@ InterruptEventData *system_info(Tab *tab)
                                          interrupt_update_time_window,
                                          event_viewer_data);   
                                         
+  g_object_set_data_full(G_OBJECT(event_viewer_data->Hbox),
+      "event_data",
+       event_viewer_data,
+      (GDestroyNotify) InterruptFree);  
   
   FirstRequest(event_viewer_data );
   return event_viewer_data;
 }
 
+
 /**
  * 
  * For each trace in the traceset, this function:
@@ -508,8 +562,8 @@ gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data)
   event_time = ltt_event_time(e);
   cpu_id = ltt_event_cpu_id(e);
   
-  calcul_duration( event_time,  cpu_id, event_data);
-  CalculateMaxIRQHandler(e);
+  CalculateData( event_time,  cpu_id, event_data);
+   
   return FALSE;
 }
 
@@ -517,7 +571,7 @@ gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data)
  *  This function calculates the duration of an interrupt.  
  *  
  */ 
-static void calcul_duration(LttTime time_exit,  guint cpu_id,InterruptEventData *event_data)
+static void CalculateData(LttTime time_exit,  guint cpu_id,InterruptEventData *event_data)
 {
   
   gint i, irq_id;
@@ -530,23 +584,18 @@ static void calcul_duration(LttTime time_exit,  guint cpu_id,InterruptEventData
     element = &g_array_index(FirstRequestIrqEntry,irq_entry,i);
     if(element->cpu_id == cpu_id)
     {
-      sum_interrupt_data(element,time_exit,  FirstRequestIrqExit);    
+      TotalDurationMaxIrqDuration(element,time_exit,  FirstRequestIrqExit);    
       g_array_remove_index(FirstRequestIrqEntry, i);
       break;
     }
   }
-}
-
-static void CalculateMaxIRQHandler(LttEvent *event)
-{
-
-}
+} 
 
 /**
- *  This function calculates the total duration of an interrupt.  
+ *  This function calculates the total duration  of an interrupt and the longest Irq handler.  
  *  
  */ 
-static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit){
+static void TotalDurationMaxIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit){
   Irq irq;
   Irq *element; 
   guint i;
@@ -561,18 +610,11 @@ static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *FirstReq
     irq.id    =  e->id;
     irq.frequency++;
     irq.total_duration =  ltt_time_sub(time_exit, e->event_time);
-    
-    /* test code */
+     
     irq.max_irq_handler.start_time = e->event_time;
     irq.max_irq_handler.end_time = time_exit;
     irq.max_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
-    /*
-    irq.max_irq_handler.duration = duration.tv_sec;
-    irq.max_irq_handler.duration *= NANOSECONDS_PER_SECOND;
-    irq.max_irq_handler.duration += element.total_duration.tv_nsec;
-    */
-    /* test code */
-    
+     
     g_array_append_val (FirstRequestIrqExit, irq);
   }
   else
@@ -610,6 +652,10 @@ static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *FirstReq
   } 
 }
 
+/**
+ *  This function  passes the second EventsRequest to LTTV
+ *  
+ */ 
 static gboolean SecondRequest(void *hook_data, void *call_data)
 {
  
@@ -673,7 +719,8 @@ static gboolean SecondRequest(void *hook_data, void *call_data)
                &g_array_index(hooks, LttvTraceHook, 1));
                
          g_assert(!ret);
-        /*iterate through the facility list*/
+         
+       /* iterate through the facility list */
        for(k = 0 ; k < hooks->len; k++) 
        { 
                hook = &g_array_index(hooks, LttvTraceHook, k);
@@ -714,9 +761,7 @@ static gboolean SecondRequest(void *hook_data, void *call_data)
        
        lttvwindow_events_request(event_data->tab, events_request);   
    }
-    
-
-  return FALSE;
+   return FALSE;
 }
 
 static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data)
@@ -732,11 +777,14 @@ static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data)
     real_data *= NANOSECONDS_PER_SECOND;
     real_data += element->total_duration.tv_nsec;
     element->average_duration = real_data / element->frequency;
-    printf("average duration: %d\n",  element->average_duration);
   }
 
 }
 
+/**
+ *  This function is called whenever an irq_entry event occurs.  Use in the second request
+ *  
+ */ 
 static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data)
 {
 
@@ -760,6 +808,10 @@ static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data)
   return FALSE;
 }
 
+/**
+ *  This function is called whenever an irq_exit event occurs in the second request. 
+ *  
+ */ 
 static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data)
 {
    
@@ -772,6 +824,11 @@ static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data)
   return FALSE;
 } 
 
+
+/**
+ *  This function is called whenever an irq_exit event occurs in the second request.  
+ *  
+ */ 
 static void CalculateXi(LttEvent *event_irq_exit, InterruptEventData *event_data)
 {
   gint i, irq_id;
@@ -801,39 +858,48 @@ static void CalculateXi(LttEvent *event_irq_exit, InterruptEventData *event_data
   }
 }
 
+
+/**
+ *  This function computes the Sum ((xi -Xa)^2) and store the result in SumArray
+ *  
+ */ 
 static void  SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data)
 {
   gint i;
-  guint time_in_ns;
+  guint Xi_in_ns;
    
-  gint temp;
+  gint duration_inner_part;
+  guint64 period_inner_part;
   Irq *average; 
   SumId *sumItem; 
   SumId sum;
+  int FrequencyHZ =  0; 
   gboolean  notFound = FALSE;
   GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
   GArray *SumArray = event_data->SumArray;
-  time_in_ns  = Xi.tv_sec;
-  time_in_ns *= NANOSECONDS_PER_SECOND;
-  time_in_ns += Xi.tv_nsec;
+  Xi_in_ns  = Xi.tv_sec;
+  Xi_in_ns *= NANOSECONDS_PER_SECOND;
+  Xi_in_ns += Xi.tv_nsec;
     
   for(i = 0; i < FirstRequestIrqExit->len; i++)
   {
        average = &g_array_index(FirstRequestIrqExit,Irq,i);
        if(irq_id == average->id)
        {
-           temp = time_in_ns - average->average_duration;
-           sum.sumOfDurations =  pow (temp , 2);
-           //printf("one : %d\n", sum.sumOfDurations);     
+           duration_inner_part = Xi_in_ns - average->average_duration;
+           FrequencyHZ = FrequencyInHZ(average->frequency, event_data->time_window);
+            
            sum.irqId = irq_id;
            sum.frequency = average->frequency;
+           sum.sumOfDurations =  pow (duration_inner_part , 2);
+           period_inner_part = CalculatePeriodInnerPart(Xi_in_ns, FrequencyHZ); 
+           sum.sumOfPeriods = period_inner_part;
            if(event_data->SumArray->len == NO_ITEMS)            
            {   
                g_array_append_val (SumArray, sum);
            }
            else
-           {
-               
+           { 
                for(i = 0; i < SumArray->len; i++)
                {
                  sumItem = &g_array_index(SumArray, SumId, i);
@@ -841,21 +907,40 @@ static void  SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data)
                  { 
                     notFound = TRUE;
                     sumItem->sumOfDurations  += sum.sumOfDurations;
-                    
-                 }
+                    sumItem->sumOfPeriods += sum.sumOfPeriods;
+                 }
                }
                if(!notFound)
                {
                   g_array_append_val (SumArray, sum);
                }
-    
-          
+     
            }
          
        }
   }    
 }
 
+static  guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ)
+{
+
+  double periodInSec; /*period  in sec*/
+  int periodInNSec;
+  gint difference;
+  guint64 result;
+  periodInSec = (double)1/FrequencyHZ;
+  periodInSec *= NANOSECONDS_PER_SECOND;
+  periodInNSec = (int)periodInSec; 
+  
+  difference = Xi - periodInNSec;
+  result = pow (difference , 2);
+  
+  
+  return result; 
+  
+   
+
+}
 /**
  *  This function displays the result on the viewer 
  *  
@@ -870,8 +955,13 @@ static gboolean DisplayViewer(void *hook_data, void *call_data)
   GtkTreeIter    iter;
   guint64 real_data;
   guint maxIRQduration;
+  double periodInSec;
+  int periodInNsec;
+  char maxIrqHandler[80];
   InterruptEventData *event_data = (InterruptEventData *)hook_data;
   GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;  
+  int FrequencyHZ =  0; 
+  periodInSec = 0;
   gtk_list_store_clear(event_data->ListStore);
   for(i = 0; i < FirstRequestIrqExit->len; i++)
   {  
@@ -884,21 +974,35 @@ static gboolean DisplayViewer(void *hook_data, void *call_data)
     maxIRQduration  = element.max_irq_handler.duration.tv_sec;
     maxIRQduration *= NANOSECONDS_PER_SECOND;
     maxIRQduration += element.max_irq_handler.duration.tv_nsec;
-      
+    
+    sprintf(maxIrqHandler, "%d [%d.%d - %d.%d]",maxIRQduration, element.max_irq_handler.start_time.tv_sec, \
+    element.max_irq_handler.start_time.tv_nsec, element.max_irq_handler.end_time.tv_sec, \
+    element.max_irq_handler.end_time.tv_nsec) ;
+   FrequencyHZ = FrequencyInHZ(element.frequency,event_data->time_window);
+   
+   if(FrequencyHZ != 0)
+   {
+      periodInSec = (double)1/FrequencyHZ;
+      periodInSec *= NANOSECONDS_PER_SECOND;
+      periodInNsec = (int)periodInSec;
+      //printf("period1:%d\n", periodInNsec);
+   }
+     
     gtk_list_store_append (event_data->ListStore, &iter);
     gtk_list_store_set (event_data->ListStore, &iter,
       CPUID_COLUMN, element.cpu_id,
       IRQ_ID_COLUMN,  element.id,
-      FREQUENCY_COLUMN, element.frequency,
+      FREQUENCY_COLUMN, FrequencyHZ,
       DURATION_COLUMN, real_data,
-      DURATION_STANDARD_DEV_COLUMN, CalculateStandardDeviation(element.id, event_data),
-      MAX_IRQ_HANDLER_COLUMN, maxIRQduration,
+      DURATION_STANDARD_DEV_COLUMN, CalculateDurationStandardDeviation(element.id, event_data),
+      MAX_IRQ_HANDLER_COLUMN, maxIrqHandler,
+      AVERAGE_PERIOD , periodInNsec,
+      PERIOD_STANDARD_DEV_COLUMN,  CalculatePeriodStandardDeviation(element.id, event_data),
       -1);
      
      
   } 
    
-  
    
   if(event_data->FirstRequestIrqExit->len)
   {
@@ -928,7 +1032,27 @@ static gboolean DisplayViewer(void *hook_data, void *call_data)
   return FALSE;
 }
 
-static int CalculateStandardDeviation(gint id, InterruptEventData *event_data)
+
+/**
+ *  This function converts the number of interrupts over a time window to
+ *  frequency in HZ
+ */ 
+static int FrequencyInHZ(gint frequency, TimeWindow time_window)
+{
+  guint64 frequencyHz = 0;
+  double timeSec;  // time in second
+  double result; 
+  result  = ltt_time_to_double(time_window.time_width);
+  timeSec = (result/NANOSECONDS_PER_SECOND);  //time in second
+  frequencyHz = frequency / timeSec;  
+  return  frequencyHz;
+}
+
+/**
+ *  This function calculates the duration standard deviation
+ *  
+ */ 
+static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event_data)
 {
   int i;
   SumId sumId;
@@ -939,16 +1063,37 @@ static int CalculateStandardDeviation(gint id, InterruptEventData *event_data)
     sumId  = g_array_index(event_data->SumArray, SumId, i);  
     if(id == sumId.irqId)
     {
-       printf("id: %d\n", sumId.irqId);             
-       inner_component = sumId.sumOfDurations/ sumId.frequency;
+       inner_component = sumId.sumOfDurations/ sumId.frequency;
        deviation =  sqrt(inner_component);
-       printf("deviation: %d\n", deviation);       
-       return deviation;
-       
+       return deviation;
     }    
   }
   return deviation; 
 }
+
+
+/**
+ *  This function calculates the period standard deviation
+ *  
+ */ 
+static int CalculatePeriodStandardDeviation(gint id, InterruptEventData *event_data)
+{
+   int i;
+   SumId sumId;
+   guint64 inner_component;
+   guint64 period_standard_deviation = 0;
+   for(i = 0; i < event_data->SumArray->len; i++)
+   {  
+      sumId  = g_array_index(event_data->SumArray, SumId, i);  
+      if(id == sumId.irqId)
+      {
+        inner_component = sumId.sumOfPeriods / sumId.frequency;
+       period_standard_deviation =  sqrt(inner_component);
+      }
+   }
+   
+   return period_standard_deviation;
+}
 /*
  * This function is called by the main window
  * when the time interval needs to be updated.
@@ -979,10 +1124,14 @@ gboolean trace_header(void *hook_data, void *call_data)
 void interrupt_destroy_walk(gpointer data, gpointer user_data)
 {
   g_info("interrupt_destroy_walk");
+  InterruptEventData *event_data = (InterruptEventData*) data;
+
+    
   interrupt_destructor((InterruptEventData*)data);
 
 }
 
+
 void interrupt_destructor(InterruptEventData *event_viewer_data)
 {
   /* May already been done by GTK window closing */
@@ -993,6 +1142,32 @@ void interrupt_destructor(InterruptEventData *event_viewer_data)
   }
 }
 
+/**
+    This function is called when the viewer is destroyed to free hooks and memory
+*/
+static void InterruptFree(InterruptEventData *event_viewer_data)
+{
+  Tab *tab = event_viewer_data->tab;
+  if(tab != NULL)
+  {
+  
+     g_array_free(event_viewer_data->FirstRequestIrqExit, TRUE);
+     g_array_free(event_viewer_data->FirstRequestIrqEntry, TRUE);
+     g_array_free(event_viewer_data->SecondRequestIrqEntry, TRUE);
+     g_array_free(event_viewer_data->SecondRequestIrqExit, TRUE);
+     g_array_free(event_viewer_data->SumArray, TRUE);
+     
+     lttvwindow_unregister_time_window_notify(tab, interrupt_update_time_window, event_viewer_data);
+       
+     lttvwindow_events_request_remove_all(event_viewer_data->tab,
+                                          event_viewer_data);  
+                                         
+     interrupt_data_list = g_slist_remove(interrupt_data_list, event_viewer_data);                                       
+      
+  }
+       
+}
+
 /**
  * plugin's destroy function
  *
This page took 0.03163 seconds and 4 git commands to generate.