X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Fmodules%2Fgui%2Finterrupts%2Finterrupts.c;h=529d74de7f3b654a8192a5a10354308795c24e9c;hb=52948a62bcf260ed1438814ad5e021a6c88b78ee;hp=97e5d0b145921edf3d0422a847d9f564bc1190e3;hpb=231a6432a55198c7ddab51af124211e2670117d2;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 97e5d0b1..529d74de 100644 --- a/ltt/branches/poly/lttv/modules/gui/interrupts/interrupts.c +++ b/ltt/branches/poly/lttv/modules/gui/interrupts/interrupts.c @@ -15,6 +15,23 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ + + /****************************************************************** + + 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 CalculateStandardDeviation() uses FirstRequestIrqExit + and SumArray arrays to calculate the standard deviation. + + *******************************************************************/ @@ -24,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -44,11 +62,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; +}MaxDuration; + typedef struct { guint cpu_id; guint id; guint frequency; LttTime total_duration; + guint average_duration; + MaxDuration max_irq_handler; + }Irq; typedef struct { @@ -57,6 +85,15 @@ typedef struct { LttTime event_time; }irq_entry; + +typedef struct +{ + guint irqId; + guint frequency; + guint64 sumOfDurations; + +}SumId; + enum type_t { IRQ_ENTRY, IRQ_EXIT @@ -83,8 +120,12 @@ typedef struct _InterruptEventData { LttvHooks * hooks_trace_before; TimeWindow time_window; LttvHooksById * event_by_id_hooks; - GArray *interrupt_counters; - GArray *active_irq_entry ; + GArray *FirstRequestIrqExit; + GArray *FirstRequestIrqEntry; + GArray *SecondRequestIrqEntry; + GArray *SecondRequestIrqExit; + GArray *SumArray; + } InterruptEventData ; @@ -94,21 +135,33 @@ static gboolean interrupt_update_time_window(void * hook_data, void * call_data) static GtkWidget *interrupts(Tab *tab); static InterruptEventData *system_info(Tab *tab); void interrupt_destructor(InterruptEventData *event_viewer_data); -static void request_event(InterruptEventData *event_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 interrupt_display (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 irq_entry_callback(void *hook_data, void *call_data); -static gboolean irq_exit_callback(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 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 CalculateStandardDeviation(gint id, InterruptEventData *event_data); +static int FrequencyInHZ(gint frequency, TimeWindow time_window); + /* Enumeration of the columns */ enum{ CPUID_COLUMN, IRQ_ID_COLUMN, FREQUENCY_COLUMN, DURATION_COLUMN, + DURATION_STANDARD_DEV_COLUMN, + MAX_IRQ_HANDLER_COLUMN, + AVERAGE_PERIOD, + PERIOD_STANDARD_DEV_COLUMN, N_COLUMNS }; @@ -153,18 +206,26 @@ static GtkWidget *interrupts(Tab * tab) */ InterruptEventData *system_info(Tab *tab) { + LttTime end; GtkTreeViewColumn *column; GtkCellRenderer *renderer; InterruptEventData* event_viewer_data = g_new(InterruptEventData,1) ; - - + 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)); + + 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); @@ -178,7 +239,11 @@ InterruptEventData *system_info(Tab *tab) 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_DOUBLE, /* Average period */ + G_TYPE_DOUBLE /* period standard deviation */ ); event_viewer_data->TreeView = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->ListStore)); @@ -205,7 +270,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); @@ -214,7 +279,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); @@ -222,6 +287,45 @@ InterruptEventData *system_info(Tab *tab) gtk_tree_view_column_set_fixed_width (column, 145); 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 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 (" Average period (nsec)", + renderer, + "text", AVERAGE_PERIOD, + NULL); + gtk_tree_view_column_set_alignment (column, 0.0); + gtk_tree_view_column_set_fixed_width (column, 200); + gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column); + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Period standard deviation (nsec)", + renderer, + "text", PERIOD_STANDARD_DEV_COLUMN, + NULL); + gtk_tree_view_column_set_alignment (column, 0.0); + gtk_tree_view_column_set_fixed_width (column, 200); + gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column); + + + event_viewer_data->SelectionTree = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data->TreeView)); gtk_tree_selection_set_mode (event_viewer_data->SelectionTree, GTK_SELECTION_SINGLE); @@ -240,7 +344,7 @@ InterruptEventData *system_info(Tab *tab) event_viewer_data); - request_event(event_viewer_data ); + FirstRequest(event_viewer_data ); return event_viewer_data; } @@ -253,7 +357,7 @@ InterruptEventData *system_info(Tab *tab) * time interval to the main window * */ -static void request_event(InterruptEventData *event_data ) +static void FirstRequest(InterruptEventData *event_data ) { guint i, k, l, nb_trace; @@ -292,8 +396,9 @@ static void request_event(InterruptEventData *event_data ) lttv_hooks_add(event_data->hooks_trace_before, trace_header, event_data, LTTV_PRIO_DEFAULT); event_data->hooks_trace_after = lttv_hooks_new(); - /* Registers a hook function */ - lttv_hooks_add(event_data->hooks_trace_after, interrupt_display, event_data, LTTV_PRIO_DEFAULT); + + /* 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 */ @@ -303,14 +408,14 @@ static void request_event(InterruptEventData *event_data ) ret = lttv_trace_find_hook(ts->parent.t, LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY, LTT_FIELD_IRQ_ID, 0, 0, - irq_entry_callback, + 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, - irq_exit_callback, + FirstRequestIrqExitCallback, events_request, &g_array_index(hooks, LttvTraceHook, 1)); @@ -363,7 +468,7 @@ static void request_event(InterruptEventData *event_data ) * This function is called whenever an irq_entry event occurs. * */ -static gboolean irq_entry_callback(void *hook_data, void *call_data) +static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data) { LttTime event_time; @@ -372,7 +477,7 @@ static gboolean irq_entry_callback(void *hook_data, void *call_data) LttvTracefileContext *tfc = (LttvTracefileContext *)call_data; LttvTracefileState *tfs = (LttvTracefileState *)call_data; InterruptEventData *event_data = (InterruptEventData *)hook_data; - GArray* active_irq_entry = event_data->active_irq_entry; + 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); @@ -381,7 +486,7 @@ static gboolean irq_entry_callback(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 (active_irq_entry, entry); + g_array_append_val (FirstRequestIrqEntry, entry); return FALSE; } @@ -411,7 +516,7 @@ static guint64 get_interrupt_id(LttEvent *e) * This function is called whenever an irq_exit event occurs. * */ -gboolean irq_exit_callback(void *hook_data, void *call_data) +gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data) { LttTime event_time; unsigned cpu_id; @@ -423,7 +528,8 @@ gboolean irq_exit_callback(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); + CalculateData( event_time, cpu_id, event_data); + return FALSE; } @@ -431,29 +537,31 @@ gboolean irq_exit_callback(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; 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++) + GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit; + GArray *FirstRequestIrqEntry = event_data->FirstRequestIrqEntry; + for(i = 0; i < FirstRequestIrqEntry->len; i++) { - element = &g_array_index(active_irq_entry,irq_entry,i); + element = &g_array_index(FirstRequestIrqEntry,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); + TotalDurationMaxIrqDuration(element,time_exit, FirstRequestIrqExit); + g_array_remove_index(FirstRequestIrqEntry, i); break; } } -} +} + /** - * This function calculates the total duration of an interrupt. + * This function calculates the total duration of an interrupt and the longest Irq handler. * */ -static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *interrupt_counters){ +static void TotalDurationMaxIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit){ Irq irq; Irq *element; guint i; @@ -462,24 +570,37 @@ static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *interrup memset ((void*)&irq, 0,sizeof(Irq)); /*first time*/ - if(interrupt_counters->len == NO_ITEMS) + if(FirstRequestIrqExit->len == NO_ITEMS) { irq.cpu_id = e->cpu_id; irq.id = e->id; irq.frequency++; 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); + + + g_array_append_val (FirstRequestIrqExit, irq); } else { - for(i = 0; i < interrupt_counters->len; i++) + for(i = 0; i < FirstRequestIrqExit->len; i++) { - element = &g_array_index(interrupt_counters,Irq,i); - if(element->id == e->id){ + 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++; + 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; + } } } if(!notFound) @@ -488,53 +609,401 @@ static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *interrup irq.id = e->id; irq.frequency++; 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); + + g_array_append_val (FirstRequestIrqExit, irq); } } } +/** + * 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; + + 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; ihooks_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; 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); + + } + } + /* 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; +} + +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; + element->average_duration = real_data / element->frequency; + } + +} + +/** + * 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; + 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); + cpu_id = ltt_event_cpu_id(e); + + + 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 time_in_ns; + + gint temp; + Irq *average; + SumId *sumItem; + SumId sum; + 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; + + 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); + sum.irqId = irq_id; + sum.frequency = average->frequency; + 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; + + } + } + if(!notFound) + { + g_array_append_val (SumArray, sum); + } + + + } + + } + } +} + /** * This function displays the result on the viewer * */ -static gboolean interrupt_display(void *hook_data, void *call_data){ +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; + double period; + char maxIrqHandler[80]; InterruptEventData *event_data = (InterruptEventData *)hook_data; - GArray *interrupt_counters = event_data->interrupt_counters; + GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit; + int FrequencyHZ = 0; + period = 0.0; gtk_list_store_clear(event_data->ListStore); - for(i = 0; i < interrupt_counters->len; i++) + for(i = 0; i < FirstRequestIrqExit->len; i++) { - element = g_array_index(interrupt_counters,Irq,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) ; + FrequencyHZ = FrequencyInHZ(element.frequency,event_data->time_window); + if(FrequencyHZ != 0) + { + period =(double)1/FrequencyHZ; + } + gtk_list_store_append (event_data->ListStore, &iter); gtk_list_store_set (event_data->ListStore, &iter, CPUID_COLUMN, element.cpu_id, IRQ_ID_COLUMN, element.id, - FREQUENCY_COLUMN, element.frequency, + FREQUENCY_COLUMN, FrequencyHZ, DURATION_COLUMN, real_data, + DURATION_STANDARD_DEV_COLUMN, CalculateStandardDeviation(element.id, event_data), + MAX_IRQ_HANDLER_COLUMN, maxIrqHandler, + AVERAGE_PERIOD , period, -1); - + + } - - if(event_data->interrupt_counters->len) + + + if(event_data->FirstRequestIrqExit->len) { - g_array_remove_range (event_data->interrupt_counters,0,event_data->interrupt_counters->len); + g_array_remove_range (event_data->FirstRequestIrqExit,0,event_data->FirstRequestIrqExit->len); } - if(event_data->active_irq_entry->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); + } - g_array_remove_range (event_data->active_irq_entry,0,event_data->active_irq_entry->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; } + + +static int FrequencyInHZ(gint frequency, TimeWindow time_window) +{ + guint64 frequencyHz = 0; + double timeSec; + + timeSec = ltt_time_to_double(time_window.time_width); + double result = (timeSec/NANOSECONDS_PER_SECOND); + frequencyHz = frequency / result; + return frequencyHz; +} + +/** + * This function calculatees the standard deviation + * + */ +static int CalculateStandardDeviation(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) + { + inner_component = sumId.sumOfDurations/ sumId.frequency; + deviation = sqrt(inner_component); + return deviation; + } + } + return deviation; +} /* * This function is called by the main window * when the time interval needs to be updated. @@ -547,7 +1016,7 @@ gboolean interrupt_update_time_window(void * hook_data, void * call_data) 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 ); + FirstRequest(event_data ); return FALSE; } @@ -585,7 +1054,9 @@ void interrupt_destructor(InterruptEventData *event_viewer_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);