X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Fmodules%2Fgui%2Finterrupts%2Finterrupts.c;h=6d0f07e3a210fba5717f69c1147a52e2e82b35f2;hb=0305fe774206ec12a98378be3cf891446b1b901c;hp=fd3ad580c2a33856a5ac9af236f1141514a1ae34;hpb=fc77fe59a3bbab809fd33d7e12441d92bcce8c38;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 fd3ad580..6d0f07e3 100644 --- a/ltt/branches/poly/lttv/modules/gui/interrupts/interrupts.c +++ b/ltt/branches/poly/lttv/modules/gui/interrupts/interrupts.c @@ -17,47 +17,49 @@ */ /****************************************************************** - - The standard deviation calculation is based on: - http://en.wikipedia.org/wiki/Standard_deviation - - Standard_deviation = sqrt(1/N Sum ((xi -Xa)^2)) - - To compute the standard deviation, we need to make EventRequests to LTTV. In - the first EventRequest, we compute the average duration (Xa) and the - frequency (N) of each IrqID. We store the information calculated in the first - EventRequest in an array called FirstRequestIrqExit. - In the second EventRequest, we compute the Sum ((xi -Xa)^2) and store this information - in a array called SumArray. The function CalculateDurationStandardDeviation() uses FirstRequestIrqExit - and SumArray arrays to calculate the standard deviation. - - - -CPUID: processor ID - -IrqId: IRQ ID -Frequency (Hz): the number of interruptions per second (Hz) - -Total Duration (nsec): the sum of each interrupt duration in nsec +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. + -Duration standard deviation (nsec): taken from http://en.wikipedia.org/wiki/Standard_deviation -Duration Standard_deviation = sqrt(1/N Sum ((xi -Xa)^2)) where -N: number of interrupts -xi: duration of an interrupt (nsec) -Xa: average duration (nsec) +- Max IRQ handler duration (nsec) [time interval]: the longest IRQ handler duration in nsec. -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 +- Average period (nsec): 1/Frequency(in HZ). The frequency is computed above. - -Period Standard_deviation = sqrt(1/N Sum ((xi -Xa)^2)) where +-Period Standard_deviation = sqrt(1/N Sum ((xi -Xa)^2)) where N: number of interrupts xi: duration of an interrupt -Xa: 1/frequency +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) + + +*******************************************************************/ @@ -71,21 +73,19 @@ Xa: 1/frequency #include #include #include -#include #include -#include #include #include #include #include #include #include +#include #include #include "hInterruptsInsert.xpm" #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) -#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) #define NO_ITEMS 0 typedef struct @@ -93,16 +93,16 @@ typedef struct LttTime duration; LttTime start_time; LttTime end_time; -}MaxDuration; +}IrqDuration; typedef struct { guint cpu_id; guint id; - guint frequency; + guint TotalNumberOfInterrupts; LttTime total_duration; guint average_duration; - MaxDuration max_irq_handler; - + IrqDuration max_irq_handler; + IrqDuration min_irq_handler; }Irq; typedef struct { @@ -115,9 +115,10 @@ typedef struct { typedef struct { guint irqId; - guint frequency; - guint64 sumOfDurations; - guint64 sumOfPeriods; + 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; @@ -130,7 +131,7 @@ enum type_t { static GSList *interrupt_data_list = NULL ; -#define TRACE_NUMBER 0 +//fixed #define TRACE_NUMBER 0 typedef struct _InterruptEventData { @@ -142,6 +143,7 @@ typedef struct _InterruptEventData { GtkTreeSelection *SelectionTree; Tab * tab; /* tab that contains this plug-in*/ + LttvPluginTab *ptab; LttvHooks * event_hooks; LttvHooks * hooks_trace_after; LttvHooks * hooks_trace_before; @@ -159,28 +161,30 @@ typedef struct _InterruptEventData { /* Function prototypes */ static gboolean interrupt_update_time_window(void * hook_data, void * call_data); -static GtkWidget *interrupts(Tab *tab); -static InterruptEventData *system_info(Tab *tab); +static GtkWidget *interrupts(LttvPlugin *plugin); +static InterruptEventData *system_info(LttvPluginTab *ptab); void interrupt_destructor(InterruptEventData *event_viewer_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 DisplayViewer (void *hook_data, void *call_data); static void CalculateData(LttTime time_exit, guint cpu_id, InterruptEventData *event_data); -static void TotalDurationMaxIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit); +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 CalculateXi(LttEvent *event, InterruptEventData *event_data, guint cpu_id); 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 frequency, TimeWindow time_window); +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, @@ -189,8 +193,10 @@ enum{ DURATION_COLUMN, DURATION_STANDARD_DEV_COLUMN, MAX_IRQ_HANDLER_COLUMN, + MIN_IRQ_HANDLER_COLUMN, AVERAGE_PERIOD, - PERIOD_STANDARD_DEV_COLUMN, + PERIOD_STANDARD_DEV_COLUMN, + FREQUENCY_STANDARD_DEV_COLUMN, N_COLUMNS }; @@ -219,10 +225,10 @@ static void init() { * Constructor hook * */ -static GtkWidget *interrupts(Tab * tab) +static GtkWidget *interrupts(LttvPlugin *plugin) { - - InterruptEventData* event_data = system_info(tab) ; + LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin); + InterruptEventData* event_data = system_info(ptab) ; if(event_data) return event_data->Hbox; else @@ -233,14 +239,15 @@ static GtkWidget *interrupts(Tab * tab) * 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) ; - + Tab *tab = ptab->tab; + event_viewer_data->ptab = ptab; event_viewer_data->tab = tab; /*Get the current time frame from the main window */ @@ -271,8 +278,11 @@ InterruptEventData *system_info(Tab *tab) 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, /* 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)); @@ -280,7 +290,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); @@ -290,7 +300,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); @@ -334,7 +344,16 @@ InterruptEventData *system_info(Tab *tab) 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, @@ -353,6 +372,14 @@ InterruptEventData *system_info(Tab *tab) 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)); @@ -405,7 +432,7 @@ static void FirstRequest(InterruptEventData *event_data ) EventsRequest *events_request; - LttvTraceHookByFacility *thf; + LttvTraceHook *th; LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab); @@ -416,13 +443,11 @@ static void FirstRequest(InterruptEventData *event_data ) nb_trace = lttv_traceset_number(traceset); /* There are many traces in a traceset. Iteration for each trace. */ - for(i = 0; ihooks_trace_before = lttv_hooks_new(); @@ -436,37 +461,34 @@ static void FirstRequest(InterruptEventData *event_data ) /* 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(); + 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, + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, + LTT_EVENT_IRQ_ENTRY, + FIELD_ARRAY(LTT_FIELD_IRQ_ID), FirstRequestIrqEntryCallback, events_request, - &g_array_index(hooks, LttvTraceHook, 0)); + &hooks); - ret = lttv_trace_find_hook(ts->parent.t, - LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT, - LTT_FIELD_IRQ_ID, 0, 0, + lttv_trace_find_hook(ts->parent.t, + LTT_FACILITY_KERNEL, + LTT_EVENT_IRQ_EXIT, + NULL, FirstRequestIrqExitCallback, events_request, - &g_array_index(hooks, LttvTraceHook, 1)); + &hooks); - 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; lfac_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); + 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; @@ -510,14 +532,16 @@ static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data) irq_entry entry; LttvTracefileContext *tfc = (LttvTracefileContext *)call_data; LttvTracefileState *tfs = (LttvTracefileState *)call_data; - InterruptEventData *event_data = (InterruptEventData *)hook_data; + LttvTraceHook *th = (LttvTraceHook*) hook_data; + EventsRequest *events_request = (EventsRequest*)th->hook_data; + InterruptEventData *event_data = events_request->viewer_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); + cpu_id = tfs->cpu; - entry.id =get_interrupt_id(e); + 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 (FirstRequestIrqEntry, entry); @@ -525,27 +549,6 @@ static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data) return FALSE; } -/** - * 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. - */ -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. * @@ -556,11 +559,12 @@ gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data) unsigned cpu_id; LttvTracefileContext *tfc = (LttvTracefileContext *)call_data; LttvTracefileState *tfs = (LttvTracefileState *)call_data; - InterruptEventData *event_data = (InterruptEventData *)hook_data; + LttvTraceHook *th = (LttvTraceHook*) hook_data; + EventsRequest *events_request = (EventsRequest*)th->hook_data; + InterruptEventData *event_data = events_request->viewer_data; 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); + cpu_id = tfs->cpu; CalculateData( event_time, cpu_id, event_data); @@ -584,18 +588,20 @@ static void CalculateData(LttTime time_exit, guint cpu_id,InterruptEventData *e element = &g_array_index(FirstRequestIrqEntry,irq_entry,i); if(element->cpu_id == cpu_id) { - TotalDurationMaxIrqDuration(element,time_exit, FirstRequestIrqExit); + CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(element,time_exit, FirstRequestIrqExit); g_array_remove_index(FirstRequestIrqEntry, i); break; } } } + /** - * This function calculates the total duration of an interrupt and the longest Irq handler. + * This function calculates the total duration of an interrupt and the longest & shortest Irq handlers. * */ -static void TotalDurationMaxIrqDuration(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; @@ -608,12 +614,16 @@ static void TotalDurationMaxIrqDuration(irq_entry *e, LttTime time_exit, GArray { 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); } @@ -627,25 +637,37 @@ static void TotalDurationMaxIrqDuration(irq_entry *e, LttTime time_exit, GArray 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); } @@ -671,7 +693,7 @@ static gboolean SecondRequest(void *hook_data, void *call_data) EventsRequest *events_request; - LttvTraceHookByFacility *thf; + LttvTraceHook *th; InterruptEventData *event_data = (InterruptEventData *)hook_data; @@ -685,14 +707,12 @@ static gboolean SecondRequest(void *hook_data, void *call_data) nb_trace = lttv_traceset_number(traceset); /* There are many traces in a traceset. Iteration for each trace. */ - for(i = 0; ihooks_trace_after = lttv_hooks_new(); /* Registers a hook function */ @@ -705,34 +725,32 @@ static gboolean SecondRequest(void *hook_data, void *call_data) /*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, + LTT_FACILITY_KERNEL, + LTT_EVENT_IRQ_ENTRY, + FIELD_ARRAY(LTT_FIELD_IRQ_ID), SecondRequestIrqEntryCallback, events_request, - &g_array_index(hooks, LttvTraceHook, 0)); + &hooks); ret = lttv_trace_find_hook(ts->parent.t, - LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT, - LTT_FIELD_IRQ_ID, 0, 0, + LTT_FACILITY_KERNEL, + LTT_EVENT_IRQ_EXIT, + NULL, SecondRequestIrqExitCallback, events_request, - &g_array_index(hooks, LttvTraceHook, 1)); + &hooks); 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; lfac_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); + 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; @@ -764,6 +782,10 @@ static gboolean SecondRequest(void *hook_data, void *call_data) return FALSE; } +/** + * This function calculates the average duration for each Irq Id + * + */ static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data) { guint64 real_data; @@ -776,7 +798,10 @@ 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; + if(element->TotalNumberOfInterrupts != 0) + element->average_duration = real_data / element->TotalNumberOfInterrupts; + else + element->average_duration = 0; } } @@ -793,14 +818,16 @@ static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data) irq_entry entry; LttvTracefileContext *tfc = (LttvTracefileContext *)call_data; LttvTracefileState *tfs = (LttvTracefileState *)call_data; - InterruptEventData *event_data = (InterruptEventData *)hook_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 = ltt_event_cpu_id(e); + cpu_id = tfs->cpu; - entry.id =get_interrupt_id(e); + 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); @@ -817,10 +844,13 @@ 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; + 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); + CalculateXi(event, event_data, tfs->cpu); return FALSE; } @@ -829,17 +859,15 @@ static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data) * This function is called whenever an irq_exit event occurs in the second request. * */ -static void CalculateXi(LttEvent *event_irq_exit, InterruptEventData *event_data) +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; - 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); @@ -870,6 +898,8 @@ static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data) gint duration_inner_part; guint64 period_inner_part; + guint64 frequency_inner_part; + Irq *average; SumId *sumItem; SumId sum; @@ -887,13 +917,22 @@ static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data) if(irq_id == average->id) { duration_inner_part = Xi_in_ns - average->average_duration; - FrequencyHZ = FrequencyInHZ(average->frequency, event_data->time_window); - + 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); @@ -908,7 +947,8 @@ 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) { @@ -921,6 +961,10 @@ static void SumItems(gint irq_id, LttTime Xi, 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) { @@ -934,12 +978,21 @@ static guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ) 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 @@ -955,9 +1008,11 @@ static gboolean DisplayViewer(void *hook_data, void *call_data) 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; @@ -978,14 +1033,23 @@ static gboolean DisplayViewer(void *hook_data, void *call_data) sprintf(maxIrqHandler, "%d [%d.%d - %d.%d]",maxIRQduration, element.max_irq_handler.start_time.tv_sec, \ element.max_irq_handler.start_time.tv_nsec, element.max_irq_handler.end_time.tv_sec, \ element.max_irq_handler.end_time.tv_nsec) ; - FrequencyHZ = FrequencyInHZ(element.frequency,event_data->time_window); + + 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; - //printf("period1:%d\n", periodInNsec); + } gtk_list_store_append (event_data->ListStore, &iter); @@ -996,11 +1060,11 @@ static gboolean DisplayViewer(void *hook_data, void *call_data) 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), - -1); - - + FREQUENCY_STANDARD_DEV_COLUMN, CalculateFrequencyStandardDeviation(element.id, event_data), + -1); } @@ -1037,20 +1101,24 @@ static gboolean DisplayViewer(void *hook_data, void *call_data) * This function converts the number of interrupts over a time window to * frequency in HZ */ -static int FrequencyInHZ(gint frequency, TimeWindow time_window) +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 = frequency / timeSec; + 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) { @@ -1063,7 +1131,10 @@ static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event sumId = g_array_index(event_data->SumArray, SumId, i); if(id == 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); return deviation; } @@ -1074,6 +1145,12 @@ static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event /** * 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) @@ -1082,18 +1159,55 @@ static int CalculatePeriodStandardDeviation(gint id, InterruptEventData *event_d SumId sumId; guint64 inner_component; guint64 period_standard_deviation = 0; + for(i = 0; i < event_data->SumArray->len; i++) { sumId = g_array_index(event_data->SumArray, SumId, i); if(id == sumId.irqId) { - inner_component = sumId.sumOfPeriods / sumId.frequency; + 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. @@ -1125,10 +1239,7 @@ void interrupt_destroy_walk(gpointer data, gpointer user_data) { g_info("interrupt_destroy_walk"); InterruptEventData *event_data = (InterruptEventData*) data; - - interrupt_destructor((InterruptEventData*)data); - }