Update FSF address
[lttv.git] / lttv / modules / gui / interrupts / interrupts.c
CommitLineData
5f5119ee 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2005 Peter Ho
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
b9ce0bad
YB
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 * MA 02110-1301, USA.
5f5119ee 17 */
dc06b1bc 18
19 /******************************************************************
31935b31 20
21Each field of the interrupt viewer is summarized as follows:
e5258c09 22
ecafd9df 23- CPUID: processor ID
24
25- IrqId: IRQ ID
26
31935b31 27- Frequency (Hz): the number of interrupts per second (Hz).
28 We compute the total number of interrupts. Then
29 we divide it by the time interval.
ecafd9df 30
31935b31 31- Total Duration (nsec): the sum of each interrupt duration in nsec.
32 For a given Irq ID, we sum the duration of each interrupt
33 to give us the total duration
ecafd9df 34
35- Duration Standard_deviation = sqrt(1/N Sum ((xi -Xa)^2)) where
36 N: number of interrupts
37 xi: duration of an interrupt (nsec)
38 Xa: average duration (nsec)
31935b31 39 The formula is taken from wikipedia: http://en.wikipedia.org/wiki/Standard_deviation.
40 To calculate the duration standard deviation, we make two EventsRequest passes to the main window.
41 In the first EventsRequest pass, we calculate the total number of interrupts to compute for
42 the average Xa. In the second EventsRequest pass, calculate the standard deviation.
43
ecafd9df 44
45- Max IRQ handler duration (nsec) [time interval]: the longest IRQ handler duration in nsec.
46
31935b31 47- Min IRQ handler duration (nsec) [time interval]: the shortest IRQ handler duration in nsec.
48
49- Average period (nsec): 1/Frequency(in HZ). The frequency is computed above.
ecafd9df 50
51-Period Standard_deviation = sqrt(1/N Sum ((xi -Xa)^2)) where
31935b31 52N: number of interrupts
ecafd9df 53xi: duration of an interrupt
31935b31 54Xa: Period = 1/Frequency (in Hz)
ecafd9df 55
56-Frequency Standard_deviation = sqrt(1/N Sum ((xi -Xa)^2))
31935b31 57N: number of interrupts
ecafd9df 58xi: duration of an interrupt
59Xa: Frequency (Hz)
60
05600f3b 61
31935b31 62*******************************************************************/
5f5119ee 63
64
65
66#include <math.h>
67#include <glib.h>
68#include <gtk/gtk.h>
69#include <gdk/gdk.h>
70#include <stdio.h>
71#include <stdlib.h>
dc06b1bc 72#include <math.h>
5f5119ee 73#include <string.h>
74#include <ltt/ltt.h>
75#include <ltt/event.h>
5f5119ee 76#include <ltt/trace.h>
5f5119ee 77#include <lttv/module.h>
78#include <lttv/hook.h>
79#include <lttv/tracecontext.h>
80#include <lttv/state.h>
81#include <lttv/filter.h>
82#include <lttvwindow/lttvwindow.h>
e433e6d6 83#include <lttvwindow/lttv_plugin_tab.h>
5f5119ee 84#include <ltt/time.h>
85
86#include "hInterruptsInsert.xpm"
87
88#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
5f5119ee 89#define NO_ITEMS 0
90
446b4179 91typedef struct
92{
93 LttTime duration;
94 LttTime start_time;
95 LttTime end_time;
ecafd9df 96}IrqDuration;
446b4179 97
5f5119ee 98typedef struct {
99 guint cpu_id;
100 guint id;
31935b31 101 guint TotalNumberOfInterrupts;
5f5119ee 102 LttTime total_duration;
dc06b1bc 103 guint average_duration;
ecafd9df 104 IrqDuration max_irq_handler;
105 IrqDuration min_irq_handler;
5f5119ee 106}Irq;
107
108typedef struct {
109 guint id;
110 guint cpu_id;
111 LttTime event_time;
112}irq_entry;
113
dc06b1bc 114
115typedef struct
116{
117 guint irqId;
31935b31 118 guint TotalNumberOfInterrupts;//frequency;//
ecafd9df 119 guint64 sumOfDurations; // to store the Sum ((xi -Xa)^2) of the duration Standard deviation
120 guint64 sumOfPeriods; // to store the Sum ((xi -Xa)^2) of the period Standard deviation
121 guint64 sumOfFrequencies;// to store the Sum ((xi -Xa)^2) of the frequency Standard deviation
dc06b1bc 122
123}SumId;
124
5f5119ee 125enum type_t {
126 IRQ_ENTRY,
127 IRQ_EXIT
128};
129
130/** Array containing instanced objects. Used when module is unloaded */
131static GSList *interrupt_data_list = NULL ;
132
133
8402f27d 134//fixed #define TRACE_NUMBER 0
f2ec7aa9 135
5f5119ee 136typedef struct _InterruptEventData {
137
b3e7b125 138 /*Graphical Widgets */
139 GtkWidget * ScrollWindow;
140 GtkListStore *ListStore;
141 GtkWidget *Hbox;
142 GtkWidget *TreeView;
143 GtkTreeSelection *SelectionTree;
144
145 Tab * tab; /* tab that contains this plug-in*/
e433e6d6 146 LttvPluginTab *ptab;
5f5119ee 147 LttvHooks * event_hooks;
148 LttvHooks * hooks_trace_after;
149 LttvHooks * hooks_trace_before;
b3e7b125 150 TimeWindow time_window;
750eb11a 151 LttvHooksByIdChannelArray * event_by_id_hooks;
dc06b1bc 152 GArray *FirstRequestIrqExit;
153 GArray *FirstRequestIrqEntry;
154 GArray *SecondRequestIrqEntry;
155 GArray *SecondRequestIrqExit;
156 GArray *SumArray;
157
5f5119ee 158} InterruptEventData ;
159
f2ec7aa9 160
b3e7b125 161/* Function prototypes */
5f5119ee 162
163static gboolean interrupt_update_time_window(void * hook_data, void * call_data);
e433e6d6 164static GtkWidget *interrupts(LttvPlugin *plugin);
165static InterruptEventData *system_info(LttvPluginTab *ptab);
5f5119ee 166void interrupt_destructor(InterruptEventData *event_viewer_data);
dc06b1bc 167static void FirstRequest(InterruptEventData *event_data );
5f5119ee 168static gboolean trace_header(void *hook_data, void *call_data);
dc06b1bc 169static gboolean DisplayViewer (void *hook_data, void *call_data);
e5258c09 170static void CalculateData(LttTime time_exit, guint cpu_id, InterruptEventData *event_data);
ecafd9df 171static void CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit);
dc06b1bc 172static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data);
173static gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data);
174static gboolean SecondRequest(void *hook_data, void *call_data);
175static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data);
176static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data);
177static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data);
c88429fb 178static void CalculateXi(LttEvent *event, InterruptEventData *event_data, guint cpu_id);
dc06b1bc 179static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data);
6b0817c2 180static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event_data);
181static int CalculatePeriodStandardDeviation(gint id, InterruptEventData *event_data);
31935b31 182static int FrequencyInHZ(gint NumberOfInterruptions, TimeWindow time_window);
6b0817c2 183static guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ);
ecafd9df 184static guint64 CalculateFrequencyInnerPart(guint Xi_in_ns, guint FrequencyHZ);
fc77fe59 185static void InterruptFree(InterruptEventData *event_viewer_data);
ecafd9df 186static int CalculateFrequencyStandardDeviation(gint id, InterruptEventData *event_data);
187
5f5119ee 188/* Enumeration of the columns */
189enum{
190 CPUID_COLUMN,
191 IRQ_ID_COLUMN,
192 FREQUENCY_COLUMN,
193 DURATION_COLUMN,
dc06b1bc 194 DURATION_STANDARD_DEV_COLUMN,
446b4179 195 MAX_IRQ_HANDLER_COLUMN,
05600f3b 196 MIN_IRQ_HANDLER_COLUMN,
52948a62 197 AVERAGE_PERIOD,
ecafd9df 198 PERIOD_STANDARD_DEV_COLUMN,
199 FREQUENCY_STANDARD_DEV_COLUMN,
5f5119ee 200 N_COLUMNS
201};
f2ec7aa9 202
203
204
205/**
206 * init function
207 *
208 *
209 * This is the entry point of the viewer.
210 *
211 */
212static void init() {
213 g_info("interrupts: init()");
214 lttvwindow_register_constructor("interrupts",
215 "/",
216 "Insert Interrupts View",
217 hInterruptsInsert_xpm,
218 "Insert Interrupts View",
219 interrupts);
220
221}
222
5f5119ee 223
5f5119ee 224/**
f2ec7aa9 225 * Constructor hook
5f5119ee 226 *
5f5119ee 227 */
e433e6d6 228static GtkWidget *interrupts(LttvPlugin *plugin)
f2ec7aa9 229{
e433e6d6 230 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
231 InterruptEventData* event_data = system_info(ptab) ;
5f5119ee 232 if(event_data)
b3e7b125 233 return event_data->Hbox;
5f5119ee 234 else
235 return NULL;
236}
237
f2ec7aa9 238/**
239 * This function initializes the Event Viewer functionnality through the
240 * GTK API.
241 */
e433e6d6 242InterruptEventData *system_info(LttvPluginTab *ptab)
5f5119ee 243{
5f5119ee 244 GtkTreeViewColumn *column;
245 GtkCellRenderer *renderer;
246 InterruptEventData* event_viewer_data = g_new(InterruptEventData,1) ;
e433e6d6 247 Tab *tab = ptab->tab;
248 event_viewer_data->ptab = ptab;
5f5119ee 249 event_viewer_data->tab = tab;
f2ec7aa9 250
251 /*Get the current time frame from the main window */
5f5119ee 252 event_viewer_data->time_window = lttvwindow_get_time_window(tab);
dc06b1bc 253
254 event_viewer_data->FirstRequestIrqExit = g_array_new(FALSE, FALSE, sizeof(Irq));
255 event_viewer_data->FirstRequestIrqEntry = g_array_new(FALSE, FALSE, sizeof(irq_entry));
256
257 event_viewer_data->SecondRequestIrqEntry = g_array_new(FALSE, FALSE, sizeof(irq_entry));
258 event_viewer_data->SecondRequestIrqExit = g_array_new(FALSE, FALSE, sizeof(Irq));
259
260 event_viewer_data->SumArray = g_array_new(FALSE, FALSE, sizeof(SumId));
261
262
f2ec7aa9 263 /*Create tha main window for the viewer */
b3e7b125 264 event_viewer_data->ScrollWindow = gtk_scrolled_window_new (NULL, NULL);
265 gtk_widget_show (event_viewer_data->ScrollWindow);
5f5119ee 266 gtk_scrolled_window_set_policy(
b3e7b125 267 GTK_SCROLLED_WINDOW(event_viewer_data->ScrollWindow),
5f5119ee 268 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC/*GTK_POLICY_NEVER*/);
269
270 /* Create a model for storing the data list */
b3e7b125 271 event_viewer_data->ListStore = gtk_list_store_new (
5f5119ee 272 N_COLUMNS, /* Total number of columns */
273 G_TYPE_INT, /* CPUID */
274 G_TYPE_INT, /* IRQ_ID */
275 G_TYPE_INT, /* Frequency */
dc06b1bc 276 G_TYPE_UINT64, /* Duration */
446b4179 277 G_TYPE_INT, /* standard deviation */
52948a62 278 G_TYPE_STRING, /* Max IRQ handler */
05600f3b 279 G_TYPE_STRING, /* Min IRQ handler */
6b0817c2 280 G_TYPE_INT, /* Average period */
ecafd9df 281 G_TYPE_INT, /* period standard deviation */
282 G_TYPE_INT /* frequency standard deviation */
283
5f5119ee 284 );
285
b3e7b125 286 event_viewer_data->TreeView = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->ListStore));
5f5119ee 287
b3e7b125 288 g_object_unref (G_OBJECT (event_viewer_data->ListStore));
5f5119ee 289
290 renderer = gtk_cell_renderer_text_new ();
ecafd9df 291 column = gtk_tree_view_column_new_with_attributes ("CPU ID",
5f5119ee 292 renderer,
293 "text", CPUID_COLUMN,
294 NULL);
295 gtk_tree_view_column_set_alignment (column, 0.0);
296 gtk_tree_view_column_set_fixed_width (column, 45);
b3e7b125 297 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 298
299
300 renderer = gtk_cell_renderer_text_new ();
ecafd9df 301 column = gtk_tree_view_column_new_with_attributes ("IRQ ID",
5f5119ee 302 renderer,
303 "text", IRQ_ID_COLUMN,
304 NULL);
305 gtk_tree_view_column_set_alignment (column, 0.0);
306 gtk_tree_view_column_set_fixed_width (column, 220);
b3e7b125 307 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 308
309 renderer = gtk_cell_renderer_text_new ();
52948a62 310 column = gtk_tree_view_column_new_with_attributes ("Frequency (Hz)",
5f5119ee 311 renderer,
312 "text", FREQUENCY_COLUMN,
313 NULL);
314 gtk_tree_view_column_set_alignment (column, 1.0);
315 gtk_tree_view_column_set_fixed_width (column, 220);
b3e7b125 316 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 317
318 renderer = gtk_cell_renderer_text_new ();
25c6412d 319 column = gtk_tree_view_column_new_with_attributes ("Total Duration (nsec)",
5f5119ee 320 renderer,
321 "text", DURATION_COLUMN,
322 NULL);
323 gtk_tree_view_column_set_alignment (column, 0.0);
324 gtk_tree_view_column_set_fixed_width (column, 145);
b3e7b125 325 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 326
dc06b1bc 327
328 renderer = gtk_cell_renderer_text_new ();
329 column = gtk_tree_view_column_new_with_attributes ("Duration standard deviation (nsec)",
330 renderer,
331 "text", DURATION_STANDARD_DEV_COLUMN,
332 NULL);
333 gtk_tree_view_column_set_alignment (column, 0.0);
446b4179 334 gtk_tree_view_column_set_fixed_width (column, 200);
dc06b1bc 335 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
336
446b4179 337 renderer = gtk_cell_renderer_text_new ();
25c6412d 338 column = gtk_tree_view_column_new_with_attributes ("Max IRQ handler duration (nsec) [time interval]",
446b4179 339 renderer,
340 "text", MAX_IRQ_HANDLER_COLUMN,
341 NULL);
342 gtk_tree_view_column_set_alignment (column, 0.0);
343 gtk_tree_view_column_set_fixed_width (column, 250);
344 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
05600f3b 345
346 renderer = gtk_cell_renderer_text_new ();
347 column = gtk_tree_view_column_new_with_attributes ("Min IRQ handler duration (nsec) [time interval]",
348 renderer,
349 "text", MIN_IRQ_HANDLER_COLUMN,
350 NULL);
351 gtk_tree_view_column_set_alignment (column, 0.0);
352 gtk_tree_view_column_set_fixed_width (column, 250);
353 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
354
52948a62 355 renderer = gtk_cell_renderer_text_new ();
356 column = gtk_tree_view_column_new_with_attributes (" Average period (nsec)",
357 renderer,
358 "text", AVERAGE_PERIOD,
359 NULL);
360 gtk_tree_view_column_set_alignment (column, 0.0);
361 gtk_tree_view_column_set_fixed_width (column, 200);
362 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
363
364 renderer = gtk_cell_renderer_text_new ();
365 column = gtk_tree_view_column_new_with_attributes ("Period standard deviation (nsec)",
366 renderer,
367 "text", PERIOD_STANDARD_DEV_COLUMN,
368 NULL);
369 gtk_tree_view_column_set_alignment (column, 0.0);
370 gtk_tree_view_column_set_fixed_width (column, 200);
371 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
372
ecafd9df 373 renderer = gtk_cell_renderer_text_new ();
374 column = gtk_tree_view_column_new_with_attributes ("Frequency standard deviation (Hz)",
375 renderer,
376 "text", FREQUENCY_STANDARD_DEV_COLUMN,
377 NULL);
378 gtk_tree_view_column_set_alignment (column, 0.0);
379 gtk_tree_view_column_set_fixed_width (column, 200);
380 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
52948a62 381
dc06b1bc 382
b3e7b125 383 event_viewer_data->SelectionTree = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data->TreeView));
384 gtk_tree_selection_set_mode (event_viewer_data->SelectionTree, GTK_SELECTION_SINGLE);
5f5119ee 385
b3e7b125 386 gtk_container_add (GTK_CONTAINER (event_viewer_data->ScrollWindow), event_viewer_data->TreeView);
5f5119ee 387
b3e7b125 388 event_viewer_data->Hbox = gtk_hbox_new(0, 0);
389 gtk_box_pack_start(GTK_BOX(event_viewer_data->Hbox), event_viewer_data->ScrollWindow, TRUE, TRUE, 0);
5f5119ee 390
b3e7b125 391 gtk_widget_show(event_viewer_data->Hbox);
392 gtk_widget_show(event_viewer_data->TreeView);
5f5119ee 393
b3e7b125 394 interrupt_data_list = g_slist_append(interrupt_data_list, event_viewer_data);
f2ec7aa9 395 /* Registration for time notification */
b3e7b125 396 lttvwindow_register_time_window_notify(tab,
397 interrupt_update_time_window,
398 event_viewer_data);
f2ec7aa9 399
fc77fe59 400 g_object_set_data_full(G_OBJECT(event_viewer_data->Hbox),
401 "event_data",
402 event_viewer_data,
403 (GDestroyNotify) InterruptFree);
f2ec7aa9 404
dc06b1bc 405 FirstRequest(event_viewer_data );
5f5119ee 406 return event_viewer_data;
407}
b3e7b125 408
fc77fe59 409
f2ec7aa9 410/**
411 *
412 * For each trace in the traceset, this function:
413 * - registers a callback function to each hook
414 * - calls lttv_trace_find_hook() registers a hook function to event_by_id_hooks
415 * - calls lttvwindow_events_request() to request data in a specific
416 * time interval to the main window
417 *
418 */
dc06b1bc 419static void FirstRequest(InterruptEventData *event_data )
f2ec7aa9 420{
8d8c5ea7 421 guint i, k, nb_trace;
f2ec7aa9 422 LttvTraceState *ts;
f2ec7aa9 423 GArray *hooks;
f2ec7aa9 424 EventsRequest *events_request;
c88429fb 425 LttvTraceHook *th;
f2ec7aa9 426 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
8d8c5ea7 427
f2ec7aa9 428 /* Get the traceset */
429 LttvTraceset *traceset = tsc->ts;
5f5119ee 430
f2ec7aa9 431 nb_trace = lttv_traceset_number(traceset);
432
433 /* There are many traces in a traceset. Iteration for each trace. */
8402f27d 434 //for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++) {
435 for(i = 0 ; i < nb_trace ; i++) {
f2ec7aa9 436 events_request = g_new(EventsRequest, 1);
437
c88429fb 438 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 2);
b3e7b125 439
f2ec7aa9 440 event_data->hooks_trace_before = lttv_hooks_new();
441
442 /* Registers a hook function */
443 lttv_hooks_add(event_data->hooks_trace_before, trace_header, event_data, LTTV_PRIO_DEFAULT);
444
445 event_data->hooks_trace_after = lttv_hooks_new();
dc06b1bc 446
447 /* Registers a hook function */
448 lttv_hooks_add(event_data->hooks_trace_after, SecondRequest, event_data, LTTV_PRIO_DEFAULT);
f2ec7aa9 449 /* Get a trace state */
450 ts = (LttvTraceState *)tsc->traces[i];
451 /* Create event_by_Id hooks */
750eb11a 452 event_data->event_by_id_hooks = lttv_hooks_by_id_channel_new();
b3e7b125 453
f2ec7aa9 454 /*Register event_by_id_hooks with a callback function*/
c88429fb 455 lttv_trace_find_hook(ts->parent.t,
750eb11a 456 LTT_CHANNEL_KERNEL,
c88429fb 457 LTT_EVENT_IRQ_ENTRY,
458 FIELD_ARRAY(LTT_FIELD_IRQ_ID),
dc06b1bc 459 FirstRequestIrqEntryCallback,
f2ec7aa9 460 events_request,
c88429fb 461 &hooks);
f2ec7aa9 462
c88429fb 463 lttv_trace_find_hook(ts->parent.t,
750eb11a 464 LTT_CHANNEL_KERNEL,
c88429fb 465 LTT_EVENT_IRQ_EXIT,
466 NULL,
dc06b1bc 467 FirstRequestIrqExitCallback,
f2ec7aa9 468 events_request,
c88429fb 469 &hooks);
f2ec7aa9 470
f2ec7aa9 471 /*iterate through the facility list*/
472 for(k = 0 ; k < hooks->len; k++)
473 {
c88429fb 474 th = &g_array_index(hooks, LttvTraceHook, k);
750eb11a 475 lttv_hooks_add(lttv_hooks_by_id_channel_find(
476 event_data->event_by_id_hooks,
477 th->channel, th->id),
c88429fb 478 th->h,
479 th,
480 LTTV_PRIO_DEFAULT);
f2ec7aa9 481
f2ec7aa9 482 }
483 /* Initalize the EventsRequest structure */
484 events_request->owner = event_data;
485 events_request->viewer_data = event_data;
486 events_request->servicing = FALSE;
487 events_request->start_time = event_data->time_window.start_time;
488 events_request->start_position = NULL;
489 events_request->stop_flag = FALSE;
490 events_request->end_time = event_data->time_window.end_time;
491 events_request->num_events = G_MAXUINT;
492 events_request->end_position = NULL;
493 events_request->trace = i;
494
495 events_request->hooks = hooks;
496
497 events_request->before_chunk_traceset = NULL;
498 events_request->before_chunk_trace = event_data->hooks_trace_before;
499 events_request->before_chunk_tracefile= NULL;
500 events_request->event = NULL;
750eb11a 501 events_request->event_by_id_channel = event_data->event_by_id_hooks;
f2ec7aa9 502 events_request->after_chunk_tracefile = NULL;
231a6432 503 events_request->after_chunk_trace = NULL;
f2ec7aa9 504 events_request->after_chunk_traceset = NULL;
231a6432 505 events_request->before_request = NULL;
f2ec7aa9 506 events_request->after_request = event_data->hooks_trace_after;
507
508 lttvwindow_events_request(event_data->tab, events_request);
509 }
510
b3e7b125 511}
5f5119ee 512
f2ec7aa9 513/**
514 * This function is called whenever an irq_entry event occurs.
515 *
516 */
dc06b1bc 517static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data)
f2ec7aa9 518{
519
b3e7b125 520 LttTime event_time;
b3e7b125 521 unsigned cpu_id;
522 irq_entry entry;
b3e7b125 523 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
524 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
c88429fb 525 LttvTraceHook *th = (LttvTraceHook*) hook_data;
526 EventsRequest *events_request = (EventsRequest*)th->hook_data;
527 InterruptEventData *event_data = events_request->viewer_data;
dc06b1bc 528 GArray* FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
f2ec7aa9 529 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
b3e7b125 530 event_time = ltt_event_time(e);
c88429fb 531 cpu_id = tfs->cpu;
f2ec7aa9 532
231a6432 533
c88429fb 534 entry.id = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
231a6432 535 entry.cpu_id = cpu_id;
536 entry.event_time = event_time;
dc06b1bc 537 g_array_append_val (FirstRequestIrqEntry, entry);
231a6432 538
f2ec7aa9 539 return FALSE;
5f5119ee 540}
541
f2ec7aa9 542/**
543 * This function is called whenever an irq_exit event occurs.
544 *
545 */
dc06b1bc 546gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data)
f2ec7aa9 547{
548 LttTime event_time;
549 unsigned cpu_id;
5f5119ee 550 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
f2ec7aa9 551 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
c88429fb 552 LttvTraceHook *th = (LttvTraceHook*) hook_data;
553 EventsRequest *events_request = (EventsRequest*)th->hook_data;
554 InterruptEventData *event_data = events_request->viewer_data;
f2ec7aa9 555 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
f2ec7aa9 556 event_time = ltt_event_time(e);
c88429fb 557 cpu_id = tfs->cpu;
231a6432 558
e5258c09 559 CalculateData( event_time, cpu_id, event_data);
560
231a6432 561 return FALSE;
5f5119ee 562}
563
f2ec7aa9 564/**
565 * This function calculates the duration of an interrupt.
566 *
567 */
e5258c09 568static void CalculateData(LttTime time_exit, guint cpu_id,InterruptEventData *event_data)
dc06b1bc 569{
5f5119ee 570
8d8c5ea7 571 gint i;
f2ec7aa9 572 irq_entry *element;
dc06b1bc 573 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
574 GArray *FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
1f8ff56f 575 for(i = FirstRequestIrqEntry->len-1; i >=0; i--)
231a6432 576 {
dc06b1bc 577 element = &g_array_index(FirstRequestIrqEntry,irq_entry,i);
231a6432 578 if(element->cpu_id == cpu_id)
579 {
ecafd9df 580 CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(element,time_exit, FirstRequestIrqExit);
dc06b1bc 581 g_array_remove_index(FirstRequestIrqEntry, i);
f2ec7aa9 582 break;
583 }
584 }
e5258c09 585}
ecafd9df 586
dc06b1bc 587
f2ec7aa9 588/**
ecafd9df 589 * This function calculates the total duration of an interrupt and the longest & shortest Irq handlers.
f2ec7aa9 590 *
591 */
ecafd9df 592static void CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit)
593{
5f5119ee 594 Irq irq;
595 Irq *element;
596 guint i;
597 LttTime duration;
598 gboolean notFound = FALSE;
599 memset ((void*)&irq, 0,sizeof(Irq));
600
231a6432 601 /*first time*/
dc06b1bc 602 if(FirstRequestIrqExit->len == NO_ITEMS)
231a6432 603 {
5f5119ee 604 irq.cpu_id = e->cpu_id;
605 irq.id = e->id;
31935b31 606 irq.TotalNumberOfInterrupts++;
5f5119ee 607 irq.total_duration = ltt_time_sub(time_exit, e->event_time);
e5258c09 608
446b4179 609 irq.max_irq_handler.start_time = e->event_time;
610 irq.max_irq_handler.end_time = time_exit;
611 irq.max_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
ecafd9df 612
613 irq.min_irq_handler.start_time = e->event_time;
614 irq.min_irq_handler.end_time = time_exit;
615 irq.min_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
e5258c09 616
dc06b1bc 617 g_array_append_val (FirstRequestIrqExit, irq);
5f5119ee 618 }
231a6432 619 else
620 {
dc06b1bc 621 for(i = 0; i < FirstRequestIrqExit->len; i++)
231a6432 622 {
dc06b1bc 623 element = &g_array_index(FirstRequestIrqExit,Irq,i);
624 if(element->id == e->id)
625 {
5f5119ee 626 notFound = TRUE;
627 duration = ltt_time_sub(time_exit, e->event_time);
628 element->total_duration = ltt_time_add(element->total_duration, duration);
31935b31 629 element->TotalNumberOfInterrupts++;
ecafd9df 630 // Max irq handler
446b4179 631 if(ltt_time_compare(duration,element->max_irq_handler.duration) > 0)
632 {
633 element->max_irq_handler.duration = duration;
634 element->max_irq_handler.start_time = e->event_time;
635 element->max_irq_handler.end_time = time_exit;
636 }
ecafd9df 637 // Min irq handler
638 if(ltt_time_compare(duration,element->min_irq_handler.duration) < 0)
639 {
640 element->min_irq_handler.duration = duration;
641 element->min_irq_handler.start_time = e->event_time;
642 element->min_irq_handler.end_time = time_exit;
643 }
5f5119ee 644 }
645 }
231a6432 646 if(!notFound)
647 {
5f5119ee 648 irq.cpu_id = e->cpu_id;
649 irq.id = e->id;
31935b31 650 irq.TotalNumberOfInterrupts++;
5f5119ee 651 irq.total_duration = ltt_time_sub(time_exit, e->event_time);
ecafd9df 652 // Max irq handler
446b4179 653 irq.max_irq_handler.start_time = e->event_time;
654 irq.max_irq_handler.end_time = time_exit;
655 irq.max_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
ecafd9df 656 // Min irq handler
657 irq.min_irq_handler.start_time = e->event_time;
658 irq.min_irq_handler.end_time = time_exit;
659 irq.min_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
446b4179 660
dc06b1bc 661 g_array_append_val (FirstRequestIrqExit, irq);
5f5119ee 662 }
663 }
664}
231a6432 665
e5258c09 666/**
667 * This function passes the second EventsRequest to LTTV
668 *
669 */
dc06b1bc 670static gboolean SecondRequest(void *hook_data, void *call_data)
671{
8d8c5ea7 672 guint i, k, nb_trace;
dc06b1bc 673 guint ret;
dc06b1bc 674 LttvTraceState *ts;
dc06b1bc 675 GArray *hooks;
dc06b1bc 676 EventsRequest *events_request;
c88429fb 677 LttvTraceHook *th;
dc06b1bc 678 InterruptEventData *event_data = (InterruptEventData *)hook_data;
dc06b1bc 679 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
dc06b1bc 680 CalculateAverageDurationForEachIrqId(event_data);
681
682 /* Get the traceset */
683 LttvTraceset *traceset = tsc->ts;
684
685 nb_trace = lttv_traceset_number(traceset);
686
687 /* There are many traces in a traceset. Iteration for each trace. */
8402f27d 688 for(i = 0 ; i < nb_trace ; i++) {
689 // fixed for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++) {
dc06b1bc 690 events_request = g_new(EventsRequest, 1);
691
c88429fb 692 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 2);
dc06b1bc 693
dc06b1bc 694 event_data->hooks_trace_after = lttv_hooks_new();
695
696 /* Registers a hook function */
697 lttv_hooks_add(event_data->hooks_trace_after, DisplayViewer, event_data, LTTV_PRIO_DEFAULT);
698
699 /* Get a trace state */
700 ts = (LttvTraceState *)tsc->traces[i];
701 /* Create event_by_Id hooks */
750eb11a 702 event_data->event_by_id_hooks = lttv_hooks_by_id_channel_new();
dc06b1bc 703
704 /*Register event_by_id_hooks with a callback function*/
705 ret = lttv_trace_find_hook(ts->parent.t,
750eb11a 706 LTT_CHANNEL_KERNEL,
c88429fb 707 LTT_EVENT_IRQ_ENTRY,
708 FIELD_ARRAY(LTT_FIELD_IRQ_ID),
dc06b1bc 709 SecondRequestIrqEntryCallback,
710 events_request,
c88429fb 711 &hooks);
dc06b1bc 712
713 ret = lttv_trace_find_hook(ts->parent.t,
750eb11a 714 LTT_CHANNEL_KERNEL,
c88429fb 715 LTT_EVENT_IRQ_EXIT,
716 NULL,
dc06b1bc 717 SecondRequestIrqExitCallback,
718 events_request,
c88429fb 719 &hooks);
dc06b1bc 720
721 g_assert(!ret);
e5258c09 722
723 /* iterate through the facility list */
dc06b1bc 724 for(k = 0 ; k < hooks->len; k++)
725 {
c88429fb 726 th = &g_array_index(hooks, LttvTraceHook, k);
750eb11a 727 lttv_hooks_add(lttv_hooks_by_id_channel_find(
728 event_data->event_by_id_hooks,
729 th->channel, th->id),
c88429fb 730 th->h,
731 th,
732 LTTV_PRIO_DEFAULT);
dc06b1bc 733
dc06b1bc 734 }
735 /* Initalize the EventsRequest structure */
736 events_request->owner = event_data;
737 events_request->viewer_data = event_data;
738 events_request->servicing = FALSE;
739 events_request->start_time = event_data->time_window.start_time;
740 events_request->start_position = NULL;
741 events_request->stop_flag = FALSE;
742 events_request->end_time = event_data->time_window.end_time;
743 events_request->num_events = G_MAXUINT;
744 events_request->end_position = NULL;
745 events_request->trace = i;
746
747 events_request->hooks = hooks;
748
749 events_request->before_chunk_traceset = NULL;
750 events_request->before_chunk_trace = NULL;
751 events_request->before_chunk_tracefile= NULL;
752 events_request->event = NULL;
750eb11a 753 events_request->event_by_id_channel = event_data->event_by_id_hooks;
dc06b1bc 754 events_request->after_chunk_tracefile = NULL;
755 events_request->after_chunk_trace = NULL;
756 events_request->after_chunk_traceset = NULL;
757 events_request->before_request = NULL;
758 events_request->after_request = event_data->hooks_trace_after;
759
760 lttvwindow_events_request(event_data->tab, events_request);
761 }
e5258c09 762 return FALSE;
dc06b1bc 763}
764
ecafd9df 765/**
766 * This function calculates the average duration for each Irq Id
767 *
768 */
dc06b1bc 769static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data)
770{
771 guint64 real_data;
772 Irq *element;
773 gint i;
774 GArray* FirstRequestIrqExit = event_data->FirstRequestIrqExit;
775 for(i = 0; i < FirstRequestIrqExit->len; i++)
776 {
777 element = &g_array_index(FirstRequestIrqExit,Irq,i);
778 real_data = element->total_duration.tv_sec;
779 real_data *= NANOSECONDS_PER_SECOND;
780 real_data += element->total_duration.tv_nsec;
31935b31 781 if(element->TotalNumberOfInterrupts != 0)
782 element->average_duration = real_data / element->TotalNumberOfInterrupts;
ecafd9df 783 else
784 element->average_duration = 0;
dc06b1bc 785 }
786
787}
788
e5258c09 789/**
790 * This function is called whenever an irq_entry event occurs. Use in the second request
791 *
792 */
dc06b1bc 793static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data)
794{
795
796 LttTime event_time;
797 unsigned cpu_id;
798 irq_entry entry;
799 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
800 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
c88429fb 801 LttvTraceHook *th = (LttvTraceHook *)hook_data;
802 EventsRequest *events_request = (EventsRequest*)th->hook_data;
803 InterruptEventData *event_data = events_request->viewer_data;
dc06b1bc 804 GArray* SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
805 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
806 event_time = ltt_event_time(e);
c88429fb 807 cpu_id = tfs->cpu;
dc06b1bc 808
809
c88429fb 810 entry.id = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
dc06b1bc 811 entry.cpu_id = cpu_id;
812 entry.event_time = event_time;
813 g_array_append_val (SecondRequestIrqEntry, entry);
814
815 return FALSE;
816}
817
e5258c09 818/**
819 * This function is called whenever an irq_exit event occurs in the second request.
820 *
821 */
dc06b1bc 822static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data)
823{
824
825 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
826 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
c88429fb 827 LttvTraceHook *th = (LttvTraceHook *)hook_data;
828 EventsRequest *events_request = (EventsRequest*)th->hook_data;
829 InterruptEventData *event_data = events_request->viewer_data;
830
dc06b1bc 831 LttEvent *event = ltt_tracefile_get_event(tfc->tf);
832
c88429fb 833 CalculateXi(event, event_data, tfs->cpu);
dc06b1bc 834 return FALSE;
835}
836
e5258c09 837
838/**
839 * This function is called whenever an irq_exit event occurs in the second request.
840 *
841 */
c88429fb 842static void CalculateXi(LttEvent *event_irq_exit, InterruptEventData *event_data, guint cpu_id)
dc06b1bc 843{
844 gint i, irq_id;
845 irq_entry *element;
846 LttTime Xi;
847 LttTime exit_time;
dc06b1bc 848
dc06b1bc 849 GArray *SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
dc06b1bc 850 for(i = 0; i < SecondRequestIrqEntry->len; i++)
851 {
852 element = &g_array_index(SecondRequestIrqEntry,irq_entry,i);
853 if(element->cpu_id == cpu_id)
854 {
855
856 /* time calculation */
857 exit_time = ltt_event_time(event_irq_exit);
858 Xi = ltt_time_sub(exit_time, element->event_time);
859 irq_id = element->id;
860
861 SumItems(irq_id, Xi,event_data);
862 g_array_remove_index(SecondRequestIrqEntry, i);
863 break;
864 }
865 }
866}
867
e5258c09 868
869/**
870 * This function computes the Sum ((xi -Xa)^2) and store the result in SumArray
871 *
872 */
dc06b1bc 873static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data)
874{
875 gint i;
6b0817c2 876 guint Xi_in_ns;
dc06b1bc 877
6b0817c2 878 gint duration_inner_part;
879 guint64 period_inner_part;
ecafd9df 880 guint64 frequency_inner_part;
881
dc06b1bc 882 Irq *average;
883 SumId *sumItem;
884 SumId sum;
6b0817c2 885 int FrequencyHZ = 0;
dc06b1bc 886 gboolean notFound = FALSE;
887 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
888 GArray *SumArray = event_data->SumArray;
6b0817c2 889 Xi_in_ns = Xi.tv_sec;
890 Xi_in_ns *= NANOSECONDS_PER_SECOND;
891 Xi_in_ns += Xi.tv_nsec;
dc06b1bc 892
893 for(i = 0; i < FirstRequestIrqExit->len; i++)
894 {
895 average = &g_array_index(FirstRequestIrqExit,Irq,i);
896 if(irq_id == average->id)
897 {
6b0817c2 898 duration_inner_part = Xi_in_ns - average->average_duration;
31935b31 899 FrequencyHZ = FrequencyInHZ(average->TotalNumberOfInterrupts, event_data->time_window);
dc06b1bc 900 sum.irqId = irq_id;
ecafd9df 901 // compute (xi -Xa)^2 of the duration Standard deviation
31935b31 902 sum.TotalNumberOfInterrupts = average->TotalNumberOfInterrupts;
6b0817c2 903 sum.sumOfDurations = pow (duration_inner_part , 2);
ecafd9df 904
905 // compute (xi -Xa)^2 of the period Standard deviation
6b0817c2 906 period_inner_part = CalculatePeriodInnerPart(Xi_in_ns, FrequencyHZ);
ecafd9df 907
908 // compute (xi -Xa)^2 of the frequency Standard deviation
909 frequency_inner_part = CalculateFrequencyInnerPart(Xi_in_ns, FrequencyHZ);
910
6b0817c2 911 sum.sumOfPeriods = period_inner_part;
ecafd9df 912
913 sum.sumOfFrequencies = frequency_inner_part;
914
dc06b1bc 915 if(event_data->SumArray->len == NO_ITEMS)
916 {
917 g_array_append_val (SumArray, sum);
918 }
919 else
6b0817c2 920 {
dc06b1bc 921 for(i = 0; i < SumArray->len; i++)
922 {
923 sumItem = &g_array_index(SumArray, SumId, i);
924 if(sumItem->irqId == irq_id)
925 {
926 notFound = TRUE;
927 sumItem->sumOfDurations += sum.sumOfDurations;
6b0817c2 928 sumItem->sumOfPeriods += sum.sumOfPeriods;
ecafd9df 929 sumItem->sumOfFrequencies += sum.sumOfFrequencies;
930 }
dc06b1bc 931 }
932 if(!notFound)
933 {
934 g_array_append_val (SumArray, sum);
935 }
6b0817c2 936
dc06b1bc 937 }
938
939 }
940 }
941}
942
ecafd9df 943/**
944 * This function computes the inner part of the period standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
945 * The inner part is: (xi -Xa)^2
946 */
6b0817c2 947static guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ)
948{
949
950 double periodInSec; /*period in sec*/
951 int periodInNSec;
952 gint difference;
953 guint64 result;
954 periodInSec = (double)1/FrequencyHZ;
955 periodInSec *= NANOSECONDS_PER_SECOND;
956 periodInNSec = (int)periodInSec;
957
958 difference = Xi - periodInNSec;
959 result = pow (difference , 2);
6b0817c2 960 return result;
ecafd9df 961}
6b0817c2 962
ecafd9df 963/**
964 * This function computes the inner part of the frequency standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
965 * The inner part is: (xi -Xa)^2
966 */
967static guint64 CalculateFrequencyInnerPart(guint Xi_in_ns, guint FrequencyHZ)
968{
969 guint64 result;
970 gint difference;
971
972 difference = Xi_in_ns - FrequencyHZ;
973 result = pow (difference , 2);
974 return result;
6b0817c2 975}
f2ec7aa9 976/**
977 * This function displays the result on the viewer
978 *
979 */
dc06b1bc 980static gboolean DisplayViewer(void *hook_data, void *call_data)
981{
f2ec7aa9 982 gint i;
983 Irq element;
f2ec7aa9 984 GtkTreeIter iter;
985 guint64 real_data;
446b4179 986 guint maxIRQduration;
05600f3b 987 guint minIRQduration;
6b0817c2 988 double periodInSec;
43ed82b5 989 int periodInNsec = 0;
e5258c09 990 char maxIrqHandler[80];
05600f3b 991 char minIrqHandler[80];
f2ec7aa9 992 InterruptEventData *event_data = (InterruptEventData *)hook_data;
dc06b1bc 993 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
52948a62 994 int FrequencyHZ = 0;
6b0817c2 995 periodInSec = 0;
f2ec7aa9 996 gtk_list_store_clear(event_data->ListStore);
dc06b1bc 997 for(i = 0; i < FirstRequestIrqExit->len; i++)
231a6432 998 {
dc06b1bc 999 element = g_array_index(FirstRequestIrqExit,Irq,i);
f2ec7aa9 1000 real_data = element.total_duration.tv_sec;
1001 real_data *= NANOSECONDS_PER_SECOND;
1002 real_data += element.total_duration.tv_nsec;
446b4179 1003
1004
1005 maxIRQduration = element.max_irq_handler.duration.tv_sec;
1006 maxIRQduration *= NANOSECONDS_PER_SECOND;
1007 maxIRQduration += element.max_irq_handler.duration.tv_nsec;
e5258c09 1008
43ed82b5 1009 sprintf(maxIrqHandler, "%d [%lu.%lu - %lu.%lu]",maxIRQduration, element.max_irq_handler.start_time.tv_sec, \
fc77fe59 1010 element.max_irq_handler.start_time.tv_nsec, element.max_irq_handler.end_time.tv_sec, \
1011 element.max_irq_handler.end_time.tv_nsec) ;
05600f3b 1012
1013 minIRQduration = element.min_irq_handler.duration.tv_sec;
1014 minIRQduration *= NANOSECONDS_PER_SECOND;
1015 minIRQduration += element.min_irq_handler.duration.tv_nsec;
43ed82b5 1016 sprintf(minIrqHandler, "%d [%lu.%lu - %lu.%lu]",minIRQduration, element.min_irq_handler.start_time.tv_sec, \
05600f3b 1017 element.min_irq_handler.start_time.tv_nsec, element.min_irq_handler.end_time.tv_sec, \
1018 element.min_irq_handler.end_time.tv_nsec) ;
1019
1020
31935b31 1021 FrequencyHZ = FrequencyInHZ(element.TotalNumberOfInterrupts,event_data->time_window);
6b0817c2 1022
8d8c5ea7
AM
1023 if(FrequencyHZ != 0)
1024 {
6b0817c2 1025 periodInSec = (double)1/FrequencyHZ;
1026 periodInSec *= NANOSECONDS_PER_SECOND;
1027 periodInNsec = (int)periodInSec;
ecafd9df 1028
8d8c5ea7 1029 }
6b0817c2 1030
f2ec7aa9 1031 gtk_list_store_append (event_data->ListStore, &iter);
1032 gtk_list_store_set (event_data->ListStore, &iter,
1033 CPUID_COLUMN, element.cpu_id,
1034 IRQ_ID_COLUMN, element.id,
52948a62 1035 FREQUENCY_COLUMN, FrequencyHZ,
f2ec7aa9 1036 DURATION_COLUMN, real_data,
6b0817c2 1037 DURATION_STANDARD_DEV_COLUMN, CalculateDurationStandardDeviation(element.id, event_data),
e5258c09 1038 MAX_IRQ_HANDLER_COLUMN, maxIrqHandler,
05600f3b 1039 MIN_IRQ_HANDLER_COLUMN, minIrqHandler,
6b0817c2 1040 AVERAGE_PERIOD , periodInNsec,
1041 PERIOD_STANDARD_DEV_COLUMN, CalculatePeriodStandardDeviation(element.id, event_data),
ecafd9df 1042 FREQUENCY_STANDARD_DEV_COLUMN, CalculateFrequencyStandardDeviation(element.id, event_data),
8f72bb94 1043 -1);
f2ec7aa9 1044 }
dc06b1bc 1045
dc06b1bc 1046
1047 if(event_data->FirstRequestIrqExit->len)
231a6432 1048 {
dc06b1bc 1049 g_array_remove_range (event_data->FirstRequestIrqExit,0,event_data->FirstRequestIrqExit->len);
231a6432 1050 }
1051
dc06b1bc 1052 if(event_data->FirstRequestIrqEntry->len)
231a6432 1053 {
dc06b1bc 1054 g_array_remove_range (event_data->FirstRequestIrqEntry,0,event_data->FirstRequestIrqEntry->len);
1055 }
1056
1057 if(event_data->SecondRequestIrqEntry->len)
1058 {
1059 g_array_remove_range (event_data->SecondRequestIrqEntry,0,event_data->SecondRequestIrqEntry->len);
1060 }
231a6432 1061
dc06b1bc 1062 if(event_data->SecondRequestIrqExit->len)
1063 {
1064 g_array_remove_range (event_data->SecondRequestIrqExit,0, event_data->SecondRequestIrqExit->len);
1065 }
1066
1067 if(event_data->SumArray->len)
1068 {
1069 g_array_remove_range (event_data->SumArray,0, event_data->SumArray->len);
231a6432 1070 }
dc06b1bc 1071
f2ec7aa9 1072 return FALSE;
5f5119ee 1073}
dc06b1bc 1074
25c6412d 1075
6b0817c2 1076/**
1077 * This function converts the number of interrupts over a time window to
1078 * frequency in HZ
1079 */
ecafd9df 1080static int FrequencyInHZ(gint NumerofInterruptions, TimeWindow time_window)
25c6412d 1081{
1082 guint64 frequencyHz = 0;
6b0817c2 1083 double timeSec; // time in second
1084 double result;
1085 result = ltt_time_to_double(time_window.time_width);
1086 timeSec = (result/NANOSECONDS_PER_SECOND); //time in second
ecafd9df 1087 frequencyHz = NumerofInterruptions / timeSec;
25c6412d 1088 return frequencyHz;
1089}
1090
e5258c09 1091/**
6b0817c2 1092 * This function calculates the duration standard deviation
ecafd9df 1093 * Duration standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
1094 * Where:
1095 * sumId.sumOfDurations -> Sum ((xi -Xa)^2)
1096 * inner_component -> 1/N Sum ((xi -Xa)^2)
1097 * deviation-> sqrt(1/N Sum ((xi -Xa)^2))
e5258c09 1098 */
6b0817c2 1099static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event_data)
dc06b1bc 1100{
1101 int i;
1102 SumId sumId;
1103 double inner_component;
1104 int deviation = 0;
1105 for(i = 0; i < event_data->SumArray->len; i++)
1106 {
1107 sumId = g_array_index(event_data->SumArray, SumId, i);
1108 if(id == sumId.irqId)
1109 {
31935b31 1110 if(sumId.TotalNumberOfInterrupts != 0)
1111 inner_component = sumId.sumOfDurations/ sumId.TotalNumberOfInterrupts;
ecafd9df 1112 else
1113 inner_component = 0.0;
dc06b1bc 1114 deviation = sqrt(inner_component);
25c6412d 1115 return deviation;
dc06b1bc 1116 }
1117 }
1118 return deviation;
1119}
6b0817c2 1120
1121
1122/**
1123 * This function calculates the period standard deviation
ecafd9df 1124 * Period standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
1125 * Where:
1126 * sumId.sumOfPeriods -> Sum ((xi -Xa)^2)
1127 * inner_component -> 1/N Sum ((xi -Xa)^2)
1128 * period_standard_deviation-> sqrt(1/N Sum ((xi -Xa)^2))
1129
6b0817c2 1130 *
1131 */
1132static int CalculatePeriodStandardDeviation(gint id, InterruptEventData *event_data)
1133{
1134 int i;
1135 SumId sumId;
1136 guint64 inner_component;
1137 guint64 period_standard_deviation = 0;
ecafd9df 1138
6b0817c2 1139 for(i = 0; i < event_data->SumArray->len; i++)
1140 {
1141 sumId = g_array_index(event_data->SumArray, SumId, i);
1142 if(id == sumId.irqId)
1143 {
31935b31 1144 if(sumId.TotalNumberOfInterrupts != 0)
1145 inner_component = sumId.sumOfPeriods / sumId.TotalNumberOfInterrupts;
ecafd9df 1146 else
1147 inner_component = 0;
1148
6b0817c2 1149 period_standard_deviation = sqrt(inner_component);
1150 }
1151 }
1152
1153 return period_standard_deviation;
1154}
ecafd9df 1155
1156/**
1157 * This function calculates the frequency standard deviation
1158 * Frequency standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
1159 * Where:
1160 * sumId.sumOfFrequencies -> Sum ((xi -Xa)^2)
1161 * inner_component -> 1/N Sum ((xi -Xa)^2)
1162 * frequency_standard_deviation-> sqrt(1/N Sum ((xi -Xa)^2))
1163 *
1164 */
1165static int CalculateFrequencyStandardDeviation(gint id, InterruptEventData *event_data)
1166{
1167 int i;
1168 SumId sumId;
1169 guint64 inner_component;
1170 guint64 frequency_standard_deviation = 0;
1171 for(i = 0; i < event_data->SumArray->len; i++)
1172 {
1173 sumId = g_array_index(event_data->SumArray, SumId, i);
1174 if(id == sumId.irqId)
1175 {
31935b31 1176 if(sumId.TotalNumberOfInterrupts != 0)
1177 inner_component = sumId.sumOfFrequencies / sumId.TotalNumberOfInterrupts;
ecafd9df 1178 else
1179 inner_component = 0;
1180
1181 frequency_standard_deviation = sqrt(inner_component);
1182 }
1183 }
1184 return frequency_standard_deviation;
1185}
1186
f2ec7aa9 1187/*
1188 * This function is called by the main window
1189 * when the time interval needs to be updated.
1190 **/
1191gboolean interrupt_update_time_window(void * hook_data, void * call_data)
1192{
5f5119ee 1193 InterruptEventData *event_data = (InterruptEventData *) hook_data;
1194 const TimeWindowNotifyData *time_window_nofify_data = ((const TimeWindowNotifyData *)call_data);
1195 event_data->time_window = *time_window_nofify_data->new_time_window;
1196 g_info("interrupts: interrupt_update_time_window()\n");
1197 Tab *tab = event_data->tab;
1198 lttvwindow_events_request_remove_all(tab, event_data);
dc06b1bc 1199 FirstRequest(event_data );
f2ec7aa9 1200 return FALSE;
5f5119ee 1201}
1202
f2ec7aa9 1203
1204gboolean trace_header(void *hook_data, void *call_data)
1205{
f2ec7aa9 1206 return FALSE;
5f5119ee 1207}
1208
f2ec7aa9 1209void interrupt_destroy_walk(gpointer data, gpointer user_data)
1210{
5f5119ee 1211 g_info("interrupt_destroy_walk");
1212 interrupt_destructor((InterruptEventData*)data);
5f5119ee 1213}
1214
fc77fe59 1215
f2ec7aa9 1216void interrupt_destructor(InterruptEventData *event_viewer_data)
1217{
1218 /* May already been done by GTK window closing */
1219 g_info("enter interrupt_destructor \n");
1220 if(GTK_IS_WIDGET(event_viewer_data->Hbox))
1221 {
1222 gtk_widget_destroy(event_viewer_data->Hbox);
1223 }
1224}
1225
fc77fe59 1226/**
1227 This function is called when the viewer is destroyed to free hooks and memory
1228*/
1229static void InterruptFree(InterruptEventData *event_viewer_data)
1230{
1231 Tab *tab = event_viewer_data->tab;
1232 if(tab != NULL)
1233 {
1234
1235 g_array_free(event_viewer_data->FirstRequestIrqExit, TRUE);
1236 g_array_free(event_viewer_data->FirstRequestIrqEntry, TRUE);
1237 g_array_free(event_viewer_data->SecondRequestIrqEntry, TRUE);
1238 g_array_free(event_viewer_data->SecondRequestIrqExit, TRUE);
1239 g_array_free(event_viewer_data->SumArray, TRUE);
1240
1241 lttvwindow_unregister_time_window_notify(tab, interrupt_update_time_window, event_viewer_data);
1242
1243 lttvwindow_events_request_remove_all(event_viewer_data->tab,
1244 event_viewer_data);
1245
1246 interrupt_data_list = g_slist_remove(interrupt_data_list, event_viewer_data);
1247
1248 }
1249
1250}
1251
5f5119ee 1252/**
1253 * plugin's destroy function
1254 *
1255 * This function releases the memory reserved by the module and unregisters
1256 * everything that has been registered in the gtkTraceSet API.
1257 */
dc06b1bc 1258static void destroy()
1259{
1260
5f5119ee 1261 g_info("Destroy interrupts");
1262 g_slist_foreach(interrupt_data_list, interrupt_destroy_walk, NULL );
1263 g_slist_free(interrupt_data_list);
1264 lttvwindow_unregister_constructor(interrupts);
1265
1266}
1267
1268LTTV_MODULE("interrupts", "interrupts info view", \
1269 "Graphical module to display interrupts performance", \
1270 init, destroy, "lttvwindow")
This page took 0.121508 seconds and 4 git commands to generate.