add plugin interface to objects
[lttv.git] / ltt / branches / poly / lttv / modules / gui / interrupts / interrupts.c
index 1afe46a3c618666ba4b2194c6c455be537d0d4bf..35011cb4a37b34542a88bd738dfc11582ec6fea4 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, 
  * MA 02111-1307, USA.
  */
+ /******************************************************************
+
+Each field of the interrupt viewer is summarized as follows:
+   
+- CPUID: processor ID
+
+- IrqId: IRQ ID
+
+- Frequency (Hz): the number of interrupts per second (Hz). 
+                  We compute the total number of interrupts. Then 
+                 we divide it by the time interval.
+
+- Total Duration (nsec): the sum of each interrupt duration in nsec. 
+                For a given Irq ID, we sum the duration of each interrupt
+                to give us the total duration 
+
+- 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)
+  The formula is taken from wikipedia: http://en.wikipedia.org/wiki/Standard_deviation.        
+  To calculate the duration standard deviation, we make two EventsRequest passes to the main window.
+  In the first EventsRequest pass, we calculate the total number of interrupts to compute for 
+  the average Xa. In the second  EventsRequest pass, calculate the standard deviation.
+  
+
+- Max IRQ handler duration (nsec) [time interval]:   the longest IRQ handler duration in nsec.  
+
+- Min IRQ handler duration (nsec) [time interval]:   the shortest IRQ handler duration in nsec.  
+
+- Average period (nsec): 1/Frequency(in HZ). The frequency is computed above.
+
+-Period Standard_deviation  = sqrt(1/N Sum ((xi -Xa)^2)) where
+N: number of interrupts 
+xi: duration of an interrupt
+Xa: Period = 1/Frequency  (in Hz)
+-Frequency Standard_deviation  = sqrt(1/N Sum ((xi -Xa)^2)) 
+N:  number of interrupts 
+xi: duration of an interrupt
+Xa: Frequency  (Hz)
+
+  
+*******************************************************************/
 
  
 
@@ -24,6 +69,7 @@
 #include <gdk/gdk.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <math.h>
 #include <string.h>
 #include <ltt/ltt.h>
 #include <ltt/event.h>
@@ -36,6 +82,7 @@
 #include <lttv/state.h>
 #include <lttv/filter.h>
 #include <lttvwindow/lttvwindow.h>
+#include <lttvwindow/lttv_plugin_tab.h>
 #include <ltt/time.h>
 
 #include "hInterruptsInsert.xpm" 
 #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
 #define NO_ITEMS 0
   
+typedef struct 
+{
+  LttTime duration;
+  LttTime start_time;  
+  LttTime end_time;    
+}IrqDuration;
+
 typedef struct {
        guint cpu_id;
        guint id;
-       guint frequency;
+       guint TotalNumberOfInterrupts;
        LttTime total_duration; 
+       guint average_duration;
+       IrqDuration max_irq_handler;
+       IrqDuration min_irq_handler;
 }Irq;
 
 typedef struct {
@@ -57,6 +114,17 @@ typedef struct {
        LttTime event_time;
 }irq_entry;
 
+
+typedef struct 
+{
+       guint irqId;
+       guint TotalNumberOfInterrupts;//frequency;// 
+       guint64 sumOfDurations; // to store the Sum ((xi -Xa)^2) of the duration Standard deviation
+       guint64 sumOfPeriods;   // to store  the Sum ((xi -Xa)^2) of the period Standard deviation
+       guint64 sumOfFrequencies;// to store the Sum ((xi -Xa)^2) of the frequency Standard deviation
+       
+}SumId;
+
 enum type_t {
    IRQ_ENTRY,
    IRQ_EXIT            
@@ -66,261 +134,501 @@ enum type_t {
 static GSList *interrupt_data_list = NULL ;
  
 
+#define TRACE_NUMBER 0
+
 typedef struct _InterruptEventData {
 
-  Tab       * tab;
+  /*Graphical Widgets */ 
+  GtkWidget * ScrollWindow;
+  GtkListStore *ListStore;
+  GtkWidget *Hbox;
+  GtkWidget *TreeView;
+  GtkTreeSelection *SelectionTree;
+  
+  Tab       * tab; /* tab that contains this plug-in*/ 
+  LttvPluginTab *ptab;
   LttvHooks  * event_hooks;
   LttvHooks  * hooks_trace_after;
   LttvHooks  * hooks_trace_before;
-  TimeWindow   time_window;            // time window
-  GtkWidget * scroll_win;
-  /* Model containing list data */
-  GtkListStore *store_m;
-  GtkWidget *hbox_v;
-  /* Widget to display the data in a columned list */
-  GtkWidget *tree_v;
-  /* Selection handler */
-  GtkTreeSelection *select_c;
-  GtkWidget *container;
-  GArray *interrupt_counters;
-  GArray *active_irq_entry ;
+  TimeWindow   time_window;
+  LttvHooksById * event_by_id_hooks;
+  GArray *FirstRequestIrqExit;
+  GArray *FirstRequestIrqEntry;
+  GArray *SecondRequestIrqEntry;
+  GArray *SecondRequestIrqExit;
+  GArray *SumArray;
+  
 } InterruptEventData ;
 
 
+/* Function prototypes */
  
 static gboolean interrupt_update_time_window(void * hook_data, void * call_data);
-// Event Viewer's constructor hook
-GtkWidget *interrupts(Tab *tab);
-// Event Viewer's constructor
-InterruptEventData *system_info(Tab *tab);
-// Event Viewer's destructor
+static GtkWidget *interrupts(LttvPlugin *plugin);
+static InterruptEventData *system_info(LttvPluginTab *ptab);
 void interrupt_destructor(InterruptEventData *event_viewer_data);
-void gui_events_free(InterruptEventData *event_viewer_data);
-static void request_event(  InterruptEventData *event_data);  
-  /* Prototype for selection handler callback */
-static void v_scroll_cb (GtkAdjustment *adjustment, gpointer data);
-
+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 parse_event(void *hook_data, void *call_data);
-static gboolean interrupt_show(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 *interrupt_counters);
+static gboolean DisplayViewer (void *hook_data, void *call_data);
+static void CalculateData(LttTime time_exit,  guint cpu_id,  InterruptEventData *event_data);
+static void CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(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);
+static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data);
+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 CalculateDurationStandardDeviation(gint id, InterruptEventData *event_data);
+static int CalculatePeriodStandardDeviation(gint id, InterruptEventData *event_data);
+static int FrequencyInHZ(gint NumberOfInterruptions, TimeWindow time_window);
+static  guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ);
+static  guint64 CalculateFrequencyInnerPart(guint Xi_in_ns,  guint FrequencyHZ); 
+static void InterruptFree(InterruptEventData *event_viewer_data);
+static int CalculateFrequencyStandardDeviation(gint id, InterruptEventData *event_data);
+
 /* Enumeration of the columns */
 enum{
   CPUID_COLUMN,
   IRQ_ID_COLUMN,
   FREQUENCY_COLUMN,
   DURATION_COLUMN,
+  DURATION_STANDARD_DEV_COLUMN,
+  MAX_IRQ_HANDLER_COLUMN,
+  MIN_IRQ_HANDLER_COLUMN,
+  AVERAGE_PERIOD,
+  PERIOD_STANDARD_DEV_COLUMN,
+  FREQUENCY_STANDARD_DEV_COLUMN, 
   N_COLUMNS
 };
+/**
+ *  init function
+ *
+ * 
+ * This is the entry point of the viewer.
+ *
+ */
+static void init() {
+  g_info("interrupts: init()");
+  lttvwindow_register_constructor("interrupts",
+                                  "/",
+                                  "Insert  Interrupts View",
+                                  hInterruptsInsert_xpm,
+                                  "Insert Interrupts View",
+                                  interrupts);
+   
+}
 
 
 /**
- * Event Viewer's constructor hook
+ *  Constructor hook
  *
- * This constructor is given as a parameter to the menuitem and toolbar button
- * registration. It creates the list.
- * @param parent_window A pointer to the parent window.
- * @return The widget created.
  */
-GtkWidget *interrupts(Tab * tab){
-  InterruptEventData* event_data = system_info(tab) ;
+static GtkWidget *interrupts(LttvPlugin *plugin)
+{
+  LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
+  InterruptEventData* event_data = system_info(ptab) ;
   if(event_data)
-    return event_data->hbox_v;
+    return event_data->Hbox;
   else 
     return NULL; 
 }
 
 /**
- * Event Viewer's constructor
- *
- * This constructor is used to create InterruptEventData data structure.
- * @return The Event viewer data created.
+ * This function initializes the Event Viewer functionnality through the
+ * GTK  API. 
  */
-InterruptEventData *system_info(Tab *tab)
+InterruptEventData *system_info(LttvPluginTab *ptab)
 {
+  
   LttTime end;
   GtkTreeViewColumn *column;
   GtkCellRenderer *renderer;
   InterruptEventData* event_viewer_data = g_new(InterruptEventData,1) ;
-  g_info("system_info \n");
-  
+  Tab *tab = ptab->tab;   
+  event_viewer_data->ptab = ptab;
   event_viewer_data->tab = tab;
+  
+  /*Get the current time frame from the main window */
   event_viewer_data->time_window  =  lttvwindow_get_time_window(tab);
-  event_viewer_data->interrupt_counters = g_array_new(FALSE, FALSE, sizeof(Irq));
-  event_viewer_data->active_irq_entry   =  g_array_new(FALSE, FALSE, sizeof(irq_entry));
   
-  lttvwindow_register_time_window_notify(tab,
-                                         interrupt_update_time_window,
-                                         event_viewer_data);   
-                                               
-  event_viewer_data->scroll_win = gtk_scrolled_window_new (NULL, NULL);
-  gtk_widget_show (event_viewer_data->scroll_win);
+  event_viewer_data->FirstRequestIrqExit = g_array_new(FALSE, FALSE, sizeof(Irq));
+  event_viewer_data->FirstRequestIrqEntry   =  g_array_new(FALSE, FALSE, sizeof(irq_entry));
+  
+  event_viewer_data->SecondRequestIrqEntry   =  g_array_new(FALSE, FALSE, sizeof(irq_entry));
+  event_viewer_data->SecondRequestIrqExit = g_array_new(FALSE, FALSE, sizeof(Irq));
+   
+  event_viewer_data->SumArray = g_array_new(FALSE, FALSE, sizeof(SumId));
+  
+  
+  /*Create tha main window for the viewer */                                           
+  event_viewer_data->ScrollWindow = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_show (event_viewer_data->ScrollWindow);
   gtk_scrolled_window_set_policy(
-      GTK_SCROLLED_WINDOW(event_viewer_data->scroll_win), 
+      GTK_SCROLLED_WINDOW(event_viewer_data->ScrollWindow), 
       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC/*GTK_POLICY_NEVER*/);
  
   /* Create a model for storing the data list */
-  event_viewer_data->store_m = gtk_list_store_new (
+  event_viewer_data->ListStore = gtk_list_store_new (
     N_COLUMNS,      /* Total number of columns     */
     G_TYPE_INT,     /* CPUID                       */
     G_TYPE_INT,     /* IRQ_ID                      */
     G_TYPE_INT,     /* Frequency                  */
-    G_TYPE_UINT64   /* Duration                    */
+    G_TYPE_UINT64,   /* Duration                   */
+    G_TYPE_INT,            /* standard deviation          */
+    G_TYPE_STRING,         /* Max IRQ handler             */
+    G_TYPE_STRING,         /* Min IRQ handler             */
+    G_TYPE_INT,                    /* Average period              */
+    G_TYPE_INT,            /* period standard deviation   */
+    G_TYPE_INT                     /* frequency standard deviation   */
+    
     );  
  
-  event_viewer_data->tree_v = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->store_m)); 
+  event_viewer_data->TreeView = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->ListStore)); 
    
-  g_object_unref (G_OBJECT (event_viewer_data->store_m));
+  g_object_unref (G_OBJECT (event_viewer_data->ListStore));
     
   renderer = gtk_cell_renderer_text_new ();
-  column = gtk_tree_view_column_new_with_attributes ("CPUID",
+  column = gtk_tree_view_column_new_with_attributes ("CPU ID",
                  renderer,
                  "text", CPUID_COLUMN,
                  NULL);
   gtk_tree_view_column_set_alignment (column, 0.0);
   gtk_tree_view_column_set_fixed_width (column, 45);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v), column);
+  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 ("IrqId",
+  column = gtk_tree_view_column_new_with_attributes ("IRQ ID",
                  renderer,
                  "text", IRQ_ID_COLUMN,
                  NULL);
   gtk_tree_view_column_set_alignment (column, 0.0);
   gtk_tree_view_column_set_fixed_width (column,  220);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v), column);
+  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);
   gtk_tree_view_column_set_alignment (column, 1.0);
   gtk_tree_view_column_set_fixed_width (column, 220);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v), column);
+  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);
   gtk_tree_view_column_set_alignment (column, 0.0);
   gtk_tree_view_column_set_fixed_width (column, 145);
-  gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v), column);
+  gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
 
-  event_viewer_data->select_c = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data->tree_v));
-  gtk_tree_selection_set_mode (event_viewer_data->select_c, GTK_SELECTION_SINGLE);
+  
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes ("Duration standard deviation  (nsec)",
+                 renderer,
+                 "text", DURATION_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);
+  
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes ("Max IRQ handler duration (nsec) [time interval]",
+                 renderer,
+                 "text", MAX_IRQ_HANDLER_COLUMN,
+                 NULL);
+  gtk_tree_view_column_set_alignment (column, 0.0);
+  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 ("Min IRQ handler duration (nsec) [time interval]",
+                 renderer,
+                 "text", MIN_IRQ_HANDLER_COLUMN,
+                 NULL);
+  gtk_tree_view_column_set_alignment (column, 0.0);
+  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);
+  
+  renderer = gtk_cell_renderer_text_new ();
+  column = gtk_tree_view_column_new_with_attributes ("Frequency standard deviation (Hz)",
+                 renderer,
+                 "text", FREQUENCY_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);
    
-  gtk_container_add (GTK_CONTAINER (event_viewer_data->scroll_win), event_viewer_data->tree_v);
+  gtk_container_add (GTK_CONTAINER (event_viewer_data->ScrollWindow), event_viewer_data->TreeView);
    
-  event_viewer_data->hbox_v = gtk_hbox_new(0, 0);
-  gtk_box_pack_start(GTK_BOX(event_viewer_data->hbox_v), event_viewer_data->scroll_win, TRUE, TRUE, 0);
+  event_viewer_data->Hbox = gtk_hbox_new(0, 0);
+  gtk_box_pack_start(GTK_BOX(event_viewer_data->Hbox), event_viewer_data->ScrollWindow, TRUE, TRUE, 0);
  
-  gtk_widget_show(event_viewer_data->hbox_v);
-  gtk_widget_show(event_viewer_data->tree_v);
+  gtk_widget_show(event_viewer_data->Hbox);
+  gtk_widget_show(event_viewer_data->TreeView);
 
-   interrupt_data_list = g_slist_append(interrupt_data_list, event_viewer_data);
+  interrupt_data_list = g_slist_append(interrupt_data_list, event_viewer_data);
+  /* Registration for time notification */
+  lttvwindow_register_time_window_notify(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);  
   
-  request_event(event_viewer_data);
+  FirstRequest(event_viewer_data );
   return event_viewer_data;
 }
+
+
+/**
+ * 
+ * For each trace in the traceset, this function:
+ *  - registers a callback function to each hook
+ *  - calls lttv_trace_find_hook() registers a hook function to event_by_id_hooks
+ *  - calls lttvwindow_events_request() to request data in a specific 
+ *    time interval to the main window
+ * 
+ */
+static void FirstRequest(InterruptEventData *event_data )
+{
+  guint i, k, l, nb_trace;
+  LttvTraceHook *hook;
+   
+  guint ret; 
   
-void v_scroll_cb(GtkAdjustment *adjustment, gpointer data){
-  InterruptEventData *event_data = (InterruptEventData*)data;
-  GtkTreePath *tree_path;
-  g_info("enter v_scroll_cb\n");
-}
+  LttvTraceState *ts;
+    
+  GArray *hooks;
+   
+  EventsRequest *events_request;
+  
+  LttvTraceHookByFacility *thf;
+  
+  LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
+  
+  
+  /* Get the traceset */
+  LttvTraceset *traceset = tsc->ts;
  
-void gui_events_free(InterruptEventData *event_viewer_data)
-{
-  Tab *tab = event_viewer_data->tab;
+  nb_trace = lttv_traceset_number(traceset);
+  
+  /* There are many traces in a traceset. Iteration for each trace. */  
+  for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++)
+  {
+        events_request = g_new(EventsRequest, 1); 
+       
+       hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
+       
+       hooks = g_array_set_size(hooks, 2);
+    
+       event_data->hooks_trace_before = lttv_hooks_new();
+       
+       /* Registers a hook function */
+       lttv_hooks_add(event_data->hooks_trace_before, trace_header, event_data, LTTV_PRIO_DEFAULT);    
 
-  if(event_viewer_data){
-    lttv_hooks_remove(event_viewer_data->event_hooks,parse_event);
-    lttv_hooks_destroy(event_viewer_data->event_hooks);
+       event_data->hooks_trace_after = lttv_hooks_new();
+       
+       /* Registers a hook function */
+       lttv_hooks_add(event_data->hooks_trace_after,  SecondRequest, event_data, LTTV_PRIO_DEFAULT);
+       /* Get a trace state */
+       ts = (LttvTraceState *)tsc->traces[i];
+       /* Create event_by_Id hooks */
+       event_data->event_by_id_hooks = lttv_hooks_by_id_new();
+  
+       /*Register event_by_id_hooks with a callback function*/ 
+          ret = lttv_trace_find_hook(ts->parent.t,
+               LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
+               LTT_FIELD_IRQ_ID, 0, 0,
+               FirstRequestIrqEntryCallback,
+               events_request,
+               &g_array_index(hooks, LttvTraceHook, 0));
+        
+        ret = lttv_trace_find_hook(ts->parent.t,
+               LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
+               LTT_FIELD_IRQ_ID, 0, 0,
+               FirstRequestIrqExitCallback,
+               events_request,
+               &g_array_index(hooks, LttvTraceHook, 1));
+               
+         g_assert(!ret);
+        /*iterate through the facility list*/
+       for(k = 0 ; k < hooks->len; k++) 
+       { 
+               hook = &g_array_index(hooks, LttvTraceHook, k);
+               for(l=0; l<hook->fac_list->len; l++) 
+               {
+                       thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l); 
+                       lttv_hooks_add(lttv_hooks_by_id_find(event_data->event_by_id_hooks, thf->id),
+                               thf->h,
+                               event_data,
+                               LTTV_PRIO_DEFAULT);
+                        
+               }
+       }
+       /* Initalize the EventsRequest structure */
+       events_request->owner       = event_data; 
+       events_request->viewer_data = event_data; 
+       events_request->servicing   = FALSE;     
+       events_request->start_time  = event_data->time_window.start_time; 
+       events_request->start_position  = NULL;
+       events_request->stop_flag          = FALSE;
+       events_request->end_time           = event_data->time_window.end_time;
+       events_request->num_events         = G_MAXUINT;      
+       events_request->end_position       = NULL; 
+       events_request->trace      = i;    
+       
+       events_request->hooks = hooks;
+       
+       events_request->before_chunk_traceset = NULL; 
+       events_request->before_chunk_trace    = event_data->hooks_trace_before; 
+       events_request->before_chunk_tracefile= NULL; 
+       events_request->event                   = NULL;  
+       events_request->event_by_id             = event_data->event_by_id_hooks; 
+       events_request->after_chunk_tracefile = NULL; 
+       events_request->after_chunk_trace     = NULL;    
+       events_request->after_chunk_traceset    = NULL; 
+       events_request->before_request          = NULL; 
+       events_request->after_request           = event_data->hooks_trace_after; 
+       
+       lttvwindow_events_request(event_data->tab, events_request);   
+   }
    
-    interrupt_data_list = g_slist_remove(interrupt_data_list, event_viewer_data);
-    g_free(event_viewer_data);
-  }
 }
 
-void interrupt_destructor(InterruptEventData *event_viewer_data)
+/**
+ *  This function is called whenever an irq_entry event occurs.  
+ *  
+ */ 
+static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data)
 {
-  /* May already been done by GTK window closing */
-  g_info("enter interrupt_destructor \n");
-  if(GTK_IS_WIDGET(event_viewer_data->hbox_v)){
-    gtk_widget_destroy(event_viewer_data->hbox_v);
-  }
-}
+  
+  LttTime  event_time; 
+  unsigned cpu_id;
+  irq_entry entry;
+  LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+  LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+  InterruptEventData *event_data = (InterruptEventData *)hook_data;
+  GArray* FirstRequestIrqEntry  = event_data->FirstRequestIrqEntry; 
+  LttEvent *e = ltt_tracefile_get_event(tfc->tf); 
+  event_time = ltt_event_time(e);
+  cpu_id = ltt_event_cpu_id(e);
    
-static guint64 get_event_detail(LttEvent *e, LttField *f){
-
-  LttType *type;
-  LttField *element;
-  GQuark name;
-  int nb, i;
-  guint64  irq_id;
-  type = ltt_field_type(f);
-  nb = ltt_type_member_number(type);
-  for(i = 0 ; i < nb-1 ; i++) {
-       element = ltt_field_member(f,i);
-       ltt_type_member_type(type, i, &name);
-       irq_id = ltt_event_get_long_unsigned(e,element);
-  }
-  return  irq_id;
-} 
-
-
-
-
-gboolean trace_header(void *hook_data, void *call_data){
+  
+  entry.id =get_interrupt_id(e);         
+  entry.cpu_id = cpu_id;
+  entry.event_time =  event_time;              
+  g_array_append_val (FirstRequestIrqEntry, entry);
 
-  InterruptEventData *event_data = (InterruptEventData *)hook_data;
-  LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
-  LttEvent *e;
-  LttTime event_time;
   return FALSE;
 }
 
-static gboolean interrupt_show(void *hook_data, void *call_data){
-  
-  gint i;      
-  Irq element; 
-  LttTime average_duration;
-  GtkTreeIter    iter;
-  guint64 real_data;
+/**
+ *  This function gets the id of the interrupt. The id is stored in a dynamic structure. 
+ *  Refer to the print.c file for how to extract data from a dynamic structure.
+ */ 
+static guint64 get_interrupt_id(LttEvent *e)
+{
+  guint i, num_fields;
+  LttEventType *event_type;
+  LttField *element;  
+  LttField *field;
+   guint64  irq_id;
+  event_type = ltt_event_eventtype(e);
+  num_fields = ltt_eventtype_num_fields(event_type);
+  for(i = 0 ; i < num_fields-1 ; i++) 
+  {   
+        field = ltt_eventtype_field(event_type, i);
+       irq_id = ltt_event_get_long_unsigned(e,field);
+  }
+  return  irq_id;
+
+} 
+/**
+ *  This function is called whenever an irq_exit event occurs.  
+ *  
+ */ 
+gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data)
+{
+  LttTime  event_time; 
+  unsigned cpu_id;
+  LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+  LttvTracefileState *tfs = (LttvTracefileState *)call_data;
   InterruptEventData *event_data = (InterruptEventData *)hook_data;
-  GArray *interrupt_counters = event_data->interrupt_counters;  
-  g_info("interrupts: interrupt_show() \n");
-  gtk_list_store_clear(event_data->store_m);
-  for(i = 0; i < interrupt_counters->len; i++){  
-    element = g_array_index(interrupt_counters,Irq,i);  
-    real_data = element.total_duration.tv_sec;
-    real_data *= NANOSECONDS_PER_SECOND;
-    real_data += element.total_duration.tv_nsec;
-    //printf("total_duration:%ld\n",  element.total_duration.tv_nsec);
-    gtk_list_store_append (event_data->store_m, &iter);
-    gtk_list_store_set (event_data->store_m, &iter,
-      CPUID_COLUMN, element.cpu_id,
-      IRQ_ID_COLUMN,  element.id,
-      FREQUENCY_COLUMN, element.frequency,
-      DURATION_COLUMN, real_data,
-      -1);
-  } 
+  LttEvent *e = ltt_tracefile_get_event(tfc->tf);
+  LttEventType *type = ltt_event_eventtype(e);
+  event_time = ltt_event_time(e);
+  cpu_id = ltt_event_cpu_id(e);
   
-  if(event_data->interrupt_counters->len)
-     g_array_remove_range (event_data->interrupt_counters,0,event_data->interrupt_counters->len);
+  CalculateData( event_time,  cpu_id, event_data);
    
-  if(event_data->active_irq_entry->len)
-    g_array_remove_range (event_data->active_irq_entry,0,event_data->active_irq_entry->len);
   return FALSE;
 }
 
-static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *interrupt_counters){
+/**
+ *  This function calculates the duration of an interrupt.  
+ *  
+ */ 
+static void CalculateData(LttTime time_exit,  guint cpu_id,InterruptEventData *event_data)
+{
+  
+  gint i, irq_id;
+  irq_entry *element; 
+  LttTime duration;
+  GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
+  GArray *FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
+  for(i = 0; i < FirstRequestIrqEntry->len; i++)
+  {
+    element = &g_array_index(FirstRequestIrqEntry,irq_entry,i);
+    if(element->cpu_id == cpu_id)
+    {
+      CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(element,time_exit,  FirstRequestIrqExit);    
+      g_array_remove_index(FirstRequestIrqEntry, i);
+      break;
+    }
+  }
+} 
+
+/**
+ *  This function calculates the total duration  of an interrupt and the longest & shortest Irq handlers.  
+ *  
+ */ 
+static void CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit)
+{
   Irq irq;
   Irq *element; 
   guint i;
@@ -328,166 +636,675 @@ static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *interrup
   gboolean  notFound = FALSE;
   memset ((void*)&irq, 0,sizeof(Irq));
   
-  //printf("time_exit: %ld.%ld\n",time_exit.tv_sec,time_exit.tv_nsec); 
-  if(interrupt_counters->len == NO_ITEMS){
+  /*first time*/
+  if(FirstRequestIrqExit->len == NO_ITEMS)
+  {
     irq.cpu_id = e->cpu_id;
     irq.id    =  e->id;
-    irq.frequency++;
+    irq.TotalNumberOfInterrupts++;
     irq.total_duration =  ltt_time_sub(time_exit, e->event_time);
-    g_array_append_val (interrupt_counters, irq);
+     
+    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.min_irq_handler.start_time = e->event_time;
+    irq.min_irq_handler.end_time = time_exit;
+    irq.min_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
+     
+    g_array_append_val (FirstRequestIrqExit, irq);
   }
-  else{
-    for(i = 0; i < interrupt_counters->len; i++){
-      element = &g_array_index(interrupt_counters,Irq,i);
-      if(element->id == e->id){
+  else
+  {
+    for(i = 0; i < FirstRequestIrqExit->len; i++)
+    {
+      element = &g_array_index(FirstRequestIrqExit,Irq,i);
+      if(element->id == e->id)
+      {
        notFound = TRUE;
        duration =  ltt_time_sub(time_exit, e->event_time);
        element->total_duration = ltt_time_add(element->total_duration, duration);
-       element->frequency++;
+       element->TotalNumberOfInterrupts++;
+       // Max irq handler
+       if(ltt_time_compare(duration,element->max_irq_handler.duration) > 0)
+       {
+           element->max_irq_handler.duration = duration;
+           element->max_irq_handler.start_time = e->event_time;
+           element->max_irq_handler.end_time  = time_exit;
+       }
+       // Min irq handler
+       if(ltt_time_compare(duration,element->min_irq_handler.duration) < 0)
+       {
+           element->min_irq_handler.duration = duration;
+           element->min_irq_handler.start_time = e->event_time;
+           element->min_irq_handler.end_time  = time_exit;
+       }
       }
     }
-    if(!notFound){
+    if(!notFound)
+    {
       irq.cpu_id = e->cpu_id;
       irq.id    =  e->id;
-      irq.frequency++;
+      irq.TotalNumberOfInterrupts++;
       irq.total_duration =  ltt_time_sub(time_exit, e->event_time);
-      g_array_append_val (interrupt_counters, irq);
+      // Max irq handler
+      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);
+      // Min irq handler
+      irq.min_irq_handler.start_time = e->event_time;
+      irq.min_irq_handler.end_time = time_exit;
+      irq.min_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
+      
+      g_array_append_val (FirstRequestIrqExit, irq);
     }
   } 
 }
+
+/**
+ *  This function  passes the second EventsRequest to LTTV
+ *  
+ */ 
+static gboolean SecondRequest(void *hook_data, void *call_data)
+{
  
-static void calcul_duration(LttTime time_exit,  guint cpu_id,InterruptEventData *event_data){
+  guint i, k, l, nb_trace;
+  LttvTraceHook *hook;
+   
+  guint ret; 
   
-  gint i, irq_id;
-  irq_entry *element; 
-  LttTime duration;
-  GArray *interrupt_counters = event_data->interrupt_counters;
-  GArray *active_irq_entry = event_data->active_irq_entry;
-  for(i = 0; i < active_irq_entry->len; i++){
-    element = &g_array_index(active_irq_entry,irq_entry,i);
-    if(element->cpu_id == cpu_id){
-      sum_interrupt_data(element,time_exit,  interrupt_counters);    
-      g_array_remove_index(active_irq_entry, i);
-     // printf("array length:%d\n",active_irq_entry->len);
-      break;
-    }
+  LttvTraceState *ts;
+    
+  GArray *hooks;
+   
+  EventsRequest *events_request;
+  
+  LttvTraceHookByFacility *thf;
+  
+  InterruptEventData *event_data = (InterruptEventData *)hook_data;
+  
+  LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
+  
+  CalculateAverageDurationForEachIrqId(event_data);
+   
+  /* Get the traceset */
+  LttvTraceset *traceset = tsc->ts;
+  nb_trace = lttv_traceset_number(traceset);
+  
+  /* There are many traces in a traceset. Iteration for each trace. */  
+  for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++)
+  {
+        events_request = g_new(EventsRequest, 1); 
+       
+       hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
+       
+       hooks = g_array_set_size(hooks, 2);
+    
+       event_data->hooks_trace_after = lttv_hooks_new();
+       
+       /* Registers a hook function */
+       lttv_hooks_add(event_data->hooks_trace_after, DisplayViewer, event_data, LTTV_PRIO_DEFAULT);
+       
+       /* Get a trace state */
+       ts = (LttvTraceState *)tsc->traces[i];
+       /* Create event_by_Id hooks */
+       event_data->event_by_id_hooks = lttv_hooks_by_id_new();
+  
+       /*Register event_by_id_hooks with a callback function*/ 
+          ret = lttv_trace_find_hook(ts->parent.t,
+               LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
+               LTT_FIELD_IRQ_ID, 0, 0,
+               SecondRequestIrqEntryCallback,
+               events_request,
+               &g_array_index(hooks, LttvTraceHook, 0));
+        
+        ret = lttv_trace_find_hook(ts->parent.t,
+               LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
+               LTT_FIELD_IRQ_ID, 0, 0,
+               SecondRequestIrqExitCallback,
+               events_request,
+               &g_array_index(hooks, LttvTraceHook, 1));
+               
+         g_assert(!ret);
+         
+       /* iterate through the facility list */
+       for(k = 0 ; k < hooks->len; k++) 
+       { 
+               hook = &g_array_index(hooks, LttvTraceHook, k);
+               for(l=0; l<hook->fac_list->len; l++) 
+               {
+                       thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l); 
+                       lttv_hooks_add(lttv_hooks_by_id_find(event_data->event_by_id_hooks, thf->id),
+                               thf->h,
+                               event_data,
+                               LTTV_PRIO_DEFAULT);
+                        
+               }
+       }
+       /* Initalize the EventsRequest structure */
+       events_request->owner       = event_data; 
+       events_request->viewer_data = event_data; 
+       events_request->servicing   = FALSE;     
+       events_request->start_time  = event_data->time_window.start_time; 
+       events_request->start_position  = NULL;
+       events_request->stop_flag          = FALSE;
+       events_request->end_time           = event_data->time_window.end_time;
+       events_request->num_events         = G_MAXUINT;      
+       events_request->end_position       = NULL; 
+       events_request->trace      = i;    
+       
+       events_request->hooks = hooks;
+       
+       events_request->before_chunk_traceset = NULL; 
+       events_request->before_chunk_trace    = NULL; 
+       events_request->before_chunk_tracefile= NULL; 
+       events_request->event                   = NULL;  
+       events_request->event_by_id             = event_data->event_by_id_hooks; 
+       events_request->after_chunk_tracefile = NULL; 
+       events_request->after_chunk_trace     = NULL;    
+       events_request->after_chunk_traceset    = NULL; 
+       events_request->before_request          = NULL; 
+       events_request->after_request           = event_data->hooks_trace_after; 
+       
+       lttvwindow_events_request(event_data->tab, events_request);   
+   }
+   return FALSE;
+}
+
+/**
+ *  This function calculates the average  duration for each Irq Id
+ *  
+ */ 
+static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data)
+{
+  guint64 real_data;
+  Irq *element; 
+  gint i;
+  GArray* FirstRequestIrqExit  = event_data->FirstRequestIrqExit; 
+  for(i = 0; i < FirstRequestIrqExit->len; i++)
+  {  
+    element = &g_array_index(FirstRequestIrqExit,Irq,i);  
+    real_data = element->total_duration.tv_sec;
+    real_data *= NANOSECONDS_PER_SECOND;
+    real_data += element->total_duration.tv_nsec;
+    if(element->TotalNumberOfInterrupts != 0)
+       element->average_duration = real_data / element->TotalNumberOfInterrupts;
+    else
+       element->average_duration = 0;
   }
+
 }
 
-gboolean parse_event(void *hook_data, void *call_data){
+/**
+ *  This function is called whenever an irq_entry event occurs.  Use in the second request
+ *  
+ */ 
+static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data)
+{
 
   LttTime  event_time; 
-  LttEvent *e;
-  LttField *field;
-  LttEventType *event_type;
   unsigned cpu_id;
   irq_entry entry;
-  irq_entry *element; 
-  guint i;
- // g_info("interrupts: parse_event() \n");
-  InterruptEventData *event_data = (InterruptEventData *)hook_data;
-  GArray* active_irq_entry  = event_data->active_irq_entry; 
   LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
   LttvTracefileState *tfs = (LttvTracefileState *)call_data;
-  //e = tfc->e; 
-  e = ltt_tracefile_get_event(tfc->tf);
-  
-  field = ltt_event_field(e);
+  InterruptEventData *event_data = (InterruptEventData *)hook_data;
+  GArray* SecondRequestIrqEntry  = event_data->SecondRequestIrqEntry; 
+  LttEvent *e = ltt_tracefile_get_event(tfc->tf); 
   event_time = ltt_event_time(e);
-  event_type = ltt_event_eventtype(e);
   cpu_id = ltt_event_cpu_id(e);
-  GString * detail_event = g_string_new("");
-  if ((ltt_time_compare(event_time,event_data->time_window.start_time) == TRUE) &&    
-     (ltt_time_compare(event_data->time_window.end_time,event_time) == TRUE)){
-       if (strcmp( g_quark_to_string(ltt_eventtype_name(event_type)),"irq_entry") == 0) {  
-           entry.id = get_event_detail(e, field);
-           entry.cpu_id = cpu_id;
-           entry.event_time =  event_time;
-           g_array_append_val (active_irq_entry, entry);
+   
+  
+  entry.id =get_interrupt_id(e);         
+  entry.cpu_id = cpu_id;
+  entry.event_time =  event_time;              
+  g_array_append_val (SecondRequestIrqEntry, entry);
+  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)
+{
+   
+  LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+  LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+  InterruptEventData *event_data = (InterruptEventData *)hook_data;
+  LttEvent *event = ltt_tracefile_get_event(tfc->tf);
+  
+  CalculateXi(event, event_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;
+  irq_entry *element; 
+  LttTime Xi;
+  LttTime  exit_time; 
+  unsigned cpu_id;
+  
+  GArray *SecondRequestIrqExit = event_data->SecondRequestIrqExit;
+  GArray *SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
+  cpu_id = ltt_event_cpu_id(event_irq_exit);
+  for(i = 0; i < SecondRequestIrqEntry->len; i++)
+  {
+    element = &g_array_index(SecondRequestIrqEntry,irq_entry,i);
+    if(element->cpu_id == cpu_id)
+    {
+     
+      /* time calculation */   
+      exit_time = ltt_event_time(event_irq_exit);
+      Xi   =  ltt_time_sub(exit_time, element->event_time);
+      irq_id    =  element->id;
+         
+      SumItems(irq_id, Xi,event_data);
+      g_array_remove_index(SecondRequestIrqEntry, i);
+      break;
+    }
+  }
+}
+
+
+/**
+ *  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 Xi_in_ns;
+   
+  gint duration_inner_part;
+  guint64 period_inner_part;
+  guint64 frequency_inner_part;
+  
+  Irq *average; 
+  SumId *sumItem; 
+  SumId sum;
+  int FrequencyHZ =  0; 
+  gboolean  notFound = FALSE;
+  GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
+  GArray *SumArray = event_data->SumArray;
+  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)
+       {
+           duration_inner_part = Xi_in_ns - average->average_duration;
+           FrequencyHZ = FrequencyInHZ(average->TotalNumberOfInterrupts, event_data->time_window);
+           sum.irqId = irq_id;
+           // compute  (xi -Xa)^2 of the duration Standard deviation
+           sum.TotalNumberOfInterrupts = average->TotalNumberOfInterrupts;
+           sum.sumOfDurations =  pow (duration_inner_part , 2);
+            
+           // compute  (xi -Xa)^2 of the period Standard deviation
+           period_inner_part = CalculatePeriodInnerPart(Xi_in_ns, FrequencyHZ); 
            
+           // compute (xi -Xa)^2 of the frequency Standard deviation
+           frequency_inner_part =  CalculateFrequencyInnerPart(Xi_in_ns, FrequencyHZ); 
+           
+           sum.sumOfPeriods = period_inner_part;
+           
+           sum.sumOfFrequencies = frequency_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);
+                 if(sumItem->irqId == irq_id)
+                 { 
+                    notFound = TRUE;
+                    sumItem->sumOfDurations  += sum.sumOfDurations;
+                    sumItem->sumOfPeriods += sum.sumOfPeriods;
+                    sumItem->sumOfFrequencies += sum.sumOfFrequencies;
+                 }
+               }
+               if(!notFound)
+               {
+                  g_array_append_val (SumArray, sum);
+               }
+     
+           }
+         
        }
-       if(strcmp( g_quark_to_string(ltt_eventtype_name(event_type)),"irq_exit") == 0) {
-         //printf("event_time: %ld.%ld\n",event_time.tv_sec,event_time.tv_nsec);       
-         calcul_duration( event_time,  cpu_id, event_data);
-        }
-   } 
-   g_string_free(detail_event, TRUE);
-   return FALSE;
+  }    
 }
 
-static void request_event(  InterruptEventData *event_data){
+/**
+ *  This function computes the inner part of the period standard deviation  = sqrt(1/N Sum ((xi -Xa)^2))  
+ *  The inner part is: (xi -Xa)^2
+ */  
+static  guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ)
+{
 
-  event_data->event_hooks = lttv_hooks_new();
-  lttv_hooks_add(event_data->event_hooks, parse_event, event_data, LTTV_PRIO_DEFAULT);
+  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 computes the inner part of the frequency standard deviation  = sqrt(1/N Sum ((xi -Xa)^2))  
+ *  The inner part is: (xi -Xa)^2
+ */  
+static  guint64 CalculateFrequencyInnerPart(guint Xi_in_ns,  guint FrequencyHZ)
+{
+  guint64 result;
+  gint difference;
+  
+  difference = Xi_in_ns - FrequencyHZ;
+  result = pow (difference , 2);
+  return result;
+}
+/**
+ *  This function displays the result on the viewer 
+ *  
+ */ 
+static gboolean DisplayViewer(void *hook_data, void *call_data)
+{
+  
+  guint average;
+  gint i;      
+  Irq element; 
+  LttTime average_duration;
+  GtkTreeIter    iter;
+  guint64 real_data;
+  guint maxIRQduration;
+  guint minIRQduration;
+  double periodInSec;
+  int periodInNsec;
+  char maxIrqHandler[80];
+  char minIrqHandler[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++)
+  {  
+    element = g_array_index(FirstRequestIrqExit,Irq,i);  
+    real_data = element.total_duration.tv_sec;
+    real_data *= NANOSECONDS_PER_SECOND;
+    real_data += element.total_duration.tv_nsec;
+    
+    
+    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) ;
+    
+    minIRQduration  =  element.min_irq_handler.duration.tv_sec;
+    minIRQduration *= NANOSECONDS_PER_SECOND;
+    minIRQduration += element.min_irq_handler.duration.tv_nsec;
+    sprintf(minIrqHandler, "%d [%d.%d - %d.%d]",minIRQduration, element.min_irq_handler.start_time.tv_sec, \
+    element.min_irq_handler.start_time.tv_nsec, element.min_irq_handler.end_time.tv_sec, \
+    element.min_irq_handler.end_time.tv_nsec) ;
  
-  event_data->hooks_trace_after = lttv_hooks_new();
-  lttv_hooks_add(event_data->hooks_trace_after, interrupt_show, event_data, LTTV_PRIO_DEFAULT);
     
-  event_data->hooks_trace_before = lttv_hooks_new();
-  lttv_hooks_add(event_data->hooks_trace_before, trace_header, event_data, LTTV_PRIO_DEFAULT);
-
-  EventsRequest *events_request = g_new(EventsRequest, 1); 
-  events_request->owner       = event_data; 
-  events_request->viewer_data = event_data; 
-  events_request->servicing   = FALSE;     
-  events_request->start_time  = event_data->time_window.start_time; 
-  events_request->start_position  = NULL;
-  events_request->stop_flag       = FALSE;
-  events_request->end_time        = event_data->time_window.end_time;
-  events_request->num_events      = G_MAXUINT;      
-  events_request->end_position     = NULL; 
-  events_request->trace           = 0;    
-  events_request->hooks           = NULL; 
-  events_request->before_chunk_traceset = NULL; 
-  events_request->before_chunk_trace    = event_data->hooks_trace_before; 
-  events_request->before_chunk_tracefile= NULL; 
-  events_request->event                        = event_data->event_hooks; 
-  events_request->event_by_id          = NULL; 
-  events_request->after_chunk_tracefile = NULL; 
-  events_request->after_chunk_trace     = NULL;   
-  events_request->after_chunk_traceset = NULL; 
-  events_request->before_request       = NULL; 
-  events_request->after_request                = event_data->hooks_trace_after; 
-  
-  lttvwindow_events_request(event_data->tab, events_request);   
+    FrequencyHZ = FrequencyInHZ(element.TotalNumberOfInterrupts,event_data->time_window);
+   
+   if(FrequencyHZ != 0)
+   {
+      periodInSec = (double)1/FrequencyHZ;
+      periodInSec *= NANOSECONDS_PER_SECOND;
+      periodInNsec = (int)periodInSec;
+     
+   }
+     
+    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, FrequencyHZ,
+      DURATION_COLUMN, real_data,
+      DURATION_STANDARD_DEV_COLUMN, CalculateDurationStandardDeviation(element.id, event_data),
+      MAX_IRQ_HANDLER_COLUMN, maxIrqHandler,
+      MIN_IRQ_HANDLER_COLUMN, minIrqHandler,
+      AVERAGE_PERIOD , periodInNsec,
+      PERIOD_STANDARD_DEV_COLUMN,  CalculatePeriodStandardDeviation(element.id, event_data),
+      FREQUENCY_STANDARD_DEV_COLUMN, CalculateFrequencyStandardDeviation(element.id, event_data),
+      -1); 
+  } 
+   
+   
+  if(event_data->FirstRequestIrqExit->len)
+  {
+     g_array_remove_range (event_data->FirstRequestIrqExit,0,event_data->FirstRequestIrqExit->len);
+  }
+  
+  if(event_data->FirstRequestIrqEntry->len)
+  {
+    g_array_remove_range (event_data->FirstRequestIrqEntry,0,event_data->FirstRequestIrqEntry->len);
+  }
+   
+  if(event_data->SecondRequestIrqEntry->len)
+  {
+    g_array_remove_range (event_data->SecondRequestIrqEntry,0,event_data->SecondRequestIrqEntry->len);
+  }
+  
+  if(event_data->SecondRequestIrqExit->len)
+  {
+    g_array_remove_range (event_data->SecondRequestIrqExit,0, event_data->SecondRequestIrqExit->len);
+  } 
+    
+  if(event_data->SumArray->len)
+  {
+    g_array_remove_range (event_data->SumArray,0, event_data->SumArray->len);
+  }
+    
+  return FALSE;
+}
+
+
+/**
+ *  This function converts the number of interrupts over a time window to
+ *  frequency in HZ
+ */ 
+static int FrequencyInHZ(gint NumerofInterruptions, 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 = NumerofInterruptions / timeSec;  
+  return  frequencyHz;
+}
+
+/**
+ *  This function calculates the duration standard deviation
+ *  Duration standard deviation = sqrt(1/N Sum ((xi -Xa)^2)) 
+ *  Where: 
+ *   sumId.sumOfDurations -> Sum ((xi -Xa)^2)
+ *   inner_component -> 1/N Sum ((xi -Xa)^2)
+ *   deviation-> sqrt(1/N Sum ((xi -Xa)^2)) 
+ */ 
+static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event_data)
+{
+  int i;
+  SumId sumId;
+  double inner_component;
+  int deviation = 0;
+  for(i = 0; i < event_data->SumArray->len; i++)
+  {  
+    sumId  = g_array_index(event_data->SumArray, SumId, i);  
+    if(id == sumId.irqId)
+    {
+        if(sumId.TotalNumberOfInterrupts != 0)
+         inner_component = sumId.sumOfDurations/ sumId.TotalNumberOfInterrupts;
+        else  
+         inner_component = 0.0;
+       deviation =  sqrt(inner_component);
+       return deviation;
+    }    
+  }
+  return deviation; 
 }
 
-gboolean interrupt_update_time_window(void * hook_data, void * call_data){
+
+/**
+ *  This function calculates the period standard deviation
+ *  Period standard deviation = sqrt(1/N Sum ((xi -Xa)^2)) 
+ *  Where: 
+ *   sumId.sumOfPeriods -> Sum ((xi -Xa)^2)
+ *   inner_component -> 1/N Sum ((xi -Xa)^2)
+ *   period_standard_deviation-> sqrt(1/N Sum ((xi -Xa)^2)) 
  
+ *  
+ */ 
+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)
+      {
+        if(sumId.TotalNumberOfInterrupts != 0)
+           inner_component = sumId.sumOfPeriods / sumId.TotalNumberOfInterrupts;
+       else
+          inner_component = 0;
+          
+       period_standard_deviation =  sqrt(inner_component);
+      }
+   }
+   
+   return period_standard_deviation;
+}
+
+/**
+ *  This function calculates the frequency standard deviation
+ *  Frequency standard deviation = sqrt(1/N Sum ((xi -Xa)^2)) 
+ *  Where: 
+ *   sumId.sumOfFrequencies -> Sum ((xi -Xa)^2)
+ *   inner_component -> 1/N Sum ((xi -Xa)^2)
+ *   frequency_standard_deviation-> sqrt(1/N Sum ((xi -Xa)^2)) 
+ *  
+ */ 
+static int CalculateFrequencyStandardDeviation(gint id, InterruptEventData *event_data)
+{
+   int i;
+   SumId sumId;
+   guint64 inner_component;
+   guint64 frequency_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)
+     {
+        if(sumId.TotalNumberOfInterrupts != 0)
+           inner_component = sumId.sumOfFrequencies / sumId.TotalNumberOfInterrupts;
+       else
+          inner_component = 0;
+       
+        frequency_standard_deviation =  sqrt(inner_component);    
+     }
+   }
+   return frequency_standard_deviation;
+}
+/*
+ * This function is called by the main window
+ * when the time interval needs to be updated.
+ **/ 
+gboolean interrupt_update_time_window(void * hook_data, void * call_data)
+{
   InterruptEventData *event_data = (InterruptEventData *) hook_data;
   const TimeWindowNotifyData *time_window_nofify_data =  ((const TimeWindowNotifyData *)call_data);
   event_data->time_window = *time_window_nofify_data->new_time_window;
   g_info("interrupts: interrupt_update_time_window()\n");
   Tab *tab = event_data->tab;
   lttvwindow_events_request_remove_all(tab, event_data);
-  request_event(event_data);
-   
-  
-    return FALSE;
+  FirstRequest(event_data );
+  return FALSE;
 }
 
-/**
- * plugin's init function
- *
- * This function initializes the Event Viewer functionnality through the
- * gtkTraceSet API.
- */
-static void init() {
-  g_info("interrupts: init()");
-  
-  lttvwindow_register_constructor("interrupts",
-                                  "/",
-                                  "Insert  Interrupts View",
-                                  hInterruptsInsert_xpm,
-                                  "Insert Interrupts View",
-                                  interrupts);
-   
+
+gboolean trace_header(void *hook_data, void *call_data)
+{
+
+  InterruptEventData *event_data = (InterruptEventData *)hook_data;
+  LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+  LttEvent *e;
+  LttTime event_time;
+  return FALSE;
 }
 
-void interrupt_destroy_walk(gpointer data, gpointer user_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 */
+  g_info("enter interrupt_destructor \n");
+  if(GTK_IS_WIDGET(event_viewer_data->Hbox))
+  {
+    gtk_widget_destroy(event_viewer_data->Hbox);
+  }
+}
+
+/**
+    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);                                       
+      
+  }
+       
 }
 
 /**
@@ -496,7 +1313,9 @@ void interrupt_destroy_walk(gpointer data, gpointer user_data){
  * This function releases the memory reserved by the module and unregisters
  * everything that has been registered in the gtkTraceSet API.
  */
-static void destroy() {
+static void destroy() 
+{
+    
   g_info("Destroy  interrupts");
   g_slist_foreach(interrupt_data_list, interrupt_destroy_walk, NULL );
   g_slist_free(interrupt_data_list); 
This page took 0.036789 seconds and 4 git commands to generate.