+
+/**
+ * This function passes the second EventsRequest to LTTV
+ *
+ */
+static gboolean SecondRequest(void *hook_data, void *call_data)
+{
+
+ guint i, k, l, nb_trace;
+
+ LttvTraceHook *hook;
+
+ guint ret;
+
+ LttvTraceState *ts;
+
+ GArray *hooks;
+
+ EventsRequest *events_request;
+
+ LttvTraceHook *th;
+
+ 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 < nb_trace ; i++) {
+ // fixed for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++) {
+ events_request = g_new(EventsRequest, 1);
+
+ hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 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,
+ FIELD_ARRAY(LTT_FIELD_IRQ_ID),
+ SecondRequestIrqEntryCallback,
+ events_request,
+ &hooks);
+
+ ret = lttv_trace_find_hook(ts->parent.t,
+ LTT_FACILITY_KERNEL,
+ LTT_EVENT_IRQ_EXIT,
+ NULL,
+ SecondRequestIrqExitCallback,
+ events_request,
+ &hooks);
+
+ g_assert(!ret);
+
+ /* iterate through the facility list */
+ for(k = 0 ; k < hooks->len; k++)
+ {
+ th = &g_array_index(hooks, LttvTraceHook, k);
+ lttv_hooks_add(lttv_hooks_by_id_find(event_data->event_by_id_hooks, th->id),
+ th->h,
+ th,
+ 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;
+ }
+
+}
+
+/**
+ * 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;
+ unsigned cpu_id;
+ irq_entry entry;
+ LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
+ LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+ LttvTraceHook *th = (LttvTraceHook *)hook_data;
+ EventsRequest *events_request = (EventsRequest*)th->hook_data;
+ InterruptEventData *event_data = events_request->viewer_data;
+ GArray* SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
+ LttEvent *e = ltt_tracefile_get_event(tfc->tf);
+ event_time = ltt_event_time(e);
+ cpu_id = tfs->cpu;
+
+
+ entry.id = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
+ 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;
+ LttvTraceHook *th = (LttvTraceHook *)hook_data;
+ EventsRequest *events_request = (EventsRequest*)th->hook_data;
+ InterruptEventData *event_data = events_request->viewer_data;
+
+ LttEvent *event = ltt_tracefile_get_event(tfc->tf);
+
+ CalculateXi(event, event_data, tfs->cpu);
+ 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, guint cpu_id)
+{
+ gint i, irq_id;
+ irq_entry *element;
+ LttTime Xi;
+ LttTime exit_time;
+
+ GArray *SecondRequestIrqExit = event_data->SecondRequestIrqExit;
+ GArray *SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
+ 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);
+ }
+
+ }
+
+ }
+ }
+}
+
+/**
+ * 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)
+{
+
+ 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;
+}