X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Fmodules%2Fgui%2Finterrupts%2Finterrupts.c;h=2818875f650edc6553354be2bb7ef0db7994c6a9;hb=8eddb7504fe51321ac56a0de6d5a82f7a94a5feb;hp=d1e3845845a00947034a7a5926ef471564af1fc0;hpb=dc06b1bcae2cc428473b0ff4d95447c637caa251;p=lttv.git diff --git a/ltt/branches/poly/lttv/modules/gui/interrupts/interrupts.c b/ltt/branches/poly/lttv/modules/gui/interrupts/interrupts.c index d1e38458..2818875f 100644 --- a/ltt/branches/poly/lttv/modules/gui/interrupts/interrupts.c +++ b/ltt/branches/poly/lttv/modules/gui/interrupts/interrupts.c @@ -17,25 +17,49 @@ */ /****************************************************************** - CPUID | IRQID | Frequency | - - The standard deviation (sigma) 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) + +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) + + +*******************************************************************/ @@ -66,13 +90,21 @@ #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 { @@ -85,8 +117,10 @@ typedef struct { typedef struct { guint irqId; - guint frequency; - guint64 sumOfDurations; + 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; @@ -135,8 +169,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 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); @@ -145,8 +179,14 @@ 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(); +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, @@ -154,6 +194,11 @@ enum{ 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 }; @@ -232,7 +277,13 @@ InterruptEventData *system_info(Tab *tab) G_TYPE_INT, /* IRQ_ID */ G_TYPE_INT, /* Frequency */ G_TYPE_UINT64, /* Duration */ - G_TYPE_INT /* standard deviation */ + 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->TreeView = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->ListStore)); @@ -240,7 +291,7 @@ InterruptEventData *system_info(Tab *tab) 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); @@ -250,7 +301,7 @@ InterruptEventData *system_info(Tab *tab) 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); @@ -259,7 +310,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); @@ -268,7 +319,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); @@ -283,9 +334,53 @@ InterruptEventData *system_info(Tab *tab) "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)); @@ -305,11 +400,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: @@ -455,7 +555,7 @@ static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data) /** * This function gets the id of the interrupt. The id is stored in a dynamic structure. - * Refer to the print.c file for howto extract data from 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) { @@ -490,8 +590,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(); + CalculateData( event_time, cpu_id, event_data); + return FALSE; } @@ -499,7 +599,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; @@ -512,23 +612,20 @@ 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); + CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(element,time_exit, FirstRequestIrqExit); g_array_remove_index(FirstRequestIrqEntry, i); break; } } -} - -static void CalculateMaxIRQHandler() -{ - -} +} + /** - * This function calculates the total duration of an interrupt. + * This function calculates the total duration of an interrupt and the longest & shortest Irq handlers. * */ -static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit){ +static void CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit) +{ Irq irq; Irq *element; guint i; @@ -541,8 +638,17 @@ static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *FirstReq { 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); + + 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 @@ -555,20 +661,47 @@ static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *FirstReq 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) { 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); + // 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) { @@ -632,7 +765,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); @@ -673,11 +807,13 @@ static gboolean SecondRequest(void *hook_data, void *call_data) lttvwindow_events_request(event_data->tab, events_request); } - - - return FALSE; + return FALSE; } +/** + * This function calculates the average duration for each Irq Id + * + */ static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data) { guint64 real_data; @@ -690,12 +826,18 @@ static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data) real_data = element->total_duration.tv_sec; 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); + 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) { @@ -719,6 +861,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) { @@ -731,6 +877,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; @@ -760,39 +911,59 @@ 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; + 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; - 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->TotalNumberOfInterrupts, event_data->time_window); sum.irqId = irq_id; - sum.frequency = average->frequency; + // 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); @@ -800,21 +971,54 @@ static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data) { 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; +} /** * This function displays the result on the viewer * @@ -828,8 +1032,16 @@ static gboolean DisplayViewer(void *hook_data, void *call_data) 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++) { @@ -837,18 +1049,49 @@ static gboolean DisplayViewer(void *hook_data, void *call_data) 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) ; + + + 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, element.frequency, + FREQUENCY_COLUMN, FrequencyHZ, DURATION_COLUMN, real_data, - DURATION_STANDARD_DEV_COLUMN, CalculateStandardDeviation(element.id, event_data), - -1); - + 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) { @@ -878,7 +1121,31 @@ 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 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; @@ -889,16 +1156,83 @@ 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; + if(sumId.TotalNumberOfInterrupts != 0) + inner_component = sumId.sumOfDurations/ sumId.TotalNumberOfInterrupts; + else + inner_component = 0.0; deviation = sqrt(inner_component); - printf("deviation: %d\n", deviation); - return deviation; - + return deviation; } } return deviation; } + + +/** + * 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. @@ -929,10 +1263,11 @@ 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 */ @@ -943,6 +1278,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 *