update compat
[lttv.git] / trunk / lttv / 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
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
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;
f2ec7aa9 151 LttvHooksById * 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{
dc06b1bc 244
5f5119ee 245 LttTime end;
246 GtkTreeViewColumn *column;
247 GtkCellRenderer *renderer;
248 InterruptEventData* event_viewer_data = g_new(InterruptEventData,1) ;
e433e6d6 249 Tab *tab = ptab->tab;
250 event_viewer_data->ptab = ptab;
5f5119ee 251 event_viewer_data->tab = tab;
f2ec7aa9 252
253 /*Get the current time frame from the main window */
5f5119ee 254 event_viewer_data->time_window = lttvwindow_get_time_window(tab);
dc06b1bc 255
256 event_viewer_data->FirstRequestIrqExit = g_array_new(FALSE, FALSE, sizeof(Irq));
257 event_viewer_data->FirstRequestIrqEntry = g_array_new(FALSE, FALSE, sizeof(irq_entry));
258
259 event_viewer_data->SecondRequestIrqEntry = g_array_new(FALSE, FALSE, sizeof(irq_entry));
260 event_viewer_data->SecondRequestIrqExit = g_array_new(FALSE, FALSE, sizeof(Irq));
261
262 event_viewer_data->SumArray = g_array_new(FALSE, FALSE, sizeof(SumId));
263
264
f2ec7aa9 265 /*Create tha main window for the viewer */
b3e7b125 266 event_viewer_data->ScrollWindow = gtk_scrolled_window_new (NULL, NULL);
267 gtk_widget_show (event_viewer_data->ScrollWindow);
5f5119ee 268 gtk_scrolled_window_set_policy(
b3e7b125 269 GTK_SCROLLED_WINDOW(event_viewer_data->ScrollWindow),
5f5119ee 270 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC/*GTK_POLICY_NEVER*/);
271
272 /* Create a model for storing the data list */
b3e7b125 273 event_viewer_data->ListStore = gtk_list_store_new (
5f5119ee 274 N_COLUMNS, /* Total number of columns */
275 G_TYPE_INT, /* CPUID */
276 G_TYPE_INT, /* IRQ_ID */
277 G_TYPE_INT, /* Frequency */
dc06b1bc 278 G_TYPE_UINT64, /* Duration */
446b4179 279 G_TYPE_INT, /* standard deviation */
52948a62 280 G_TYPE_STRING, /* Max IRQ handler */
05600f3b 281 G_TYPE_STRING, /* Min IRQ handler */
6b0817c2 282 G_TYPE_INT, /* Average period */
ecafd9df 283 G_TYPE_INT, /* period standard deviation */
284 G_TYPE_INT /* frequency standard deviation */
285
5f5119ee 286 );
287
b3e7b125 288 event_viewer_data->TreeView = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->ListStore));
5f5119ee 289
b3e7b125 290 g_object_unref (G_OBJECT (event_viewer_data->ListStore));
5f5119ee 291
292 renderer = gtk_cell_renderer_text_new ();
ecafd9df 293 column = gtk_tree_view_column_new_with_attributes ("CPU ID",
5f5119ee 294 renderer,
295 "text", CPUID_COLUMN,
296 NULL);
297 gtk_tree_view_column_set_alignment (column, 0.0);
298 gtk_tree_view_column_set_fixed_width (column, 45);
b3e7b125 299 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 300
301
302 renderer = gtk_cell_renderer_text_new ();
ecafd9df 303 column = gtk_tree_view_column_new_with_attributes ("IRQ ID",
5f5119ee 304 renderer,
305 "text", IRQ_ID_COLUMN,
306 NULL);
307 gtk_tree_view_column_set_alignment (column, 0.0);
308 gtk_tree_view_column_set_fixed_width (column, 220);
b3e7b125 309 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 310
311 renderer = gtk_cell_renderer_text_new ();
52948a62 312 column = gtk_tree_view_column_new_with_attributes ("Frequency (Hz)",
5f5119ee 313 renderer,
314 "text", FREQUENCY_COLUMN,
315 NULL);
316 gtk_tree_view_column_set_alignment (column, 1.0);
317 gtk_tree_view_column_set_fixed_width (column, 220);
b3e7b125 318 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 319
320 renderer = gtk_cell_renderer_text_new ();
25c6412d 321 column = gtk_tree_view_column_new_with_attributes ("Total Duration (nsec)",
5f5119ee 322 renderer,
323 "text", DURATION_COLUMN,
324 NULL);
325 gtk_tree_view_column_set_alignment (column, 0.0);
326 gtk_tree_view_column_set_fixed_width (column, 145);
b3e7b125 327 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 328
dc06b1bc 329
330 renderer = gtk_cell_renderer_text_new ();
331 column = gtk_tree_view_column_new_with_attributes ("Duration standard deviation (nsec)",
332 renderer,
333 "text", DURATION_STANDARD_DEV_COLUMN,
334 NULL);
335 gtk_tree_view_column_set_alignment (column, 0.0);
446b4179 336 gtk_tree_view_column_set_fixed_width (column, 200);
dc06b1bc 337 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
338
446b4179 339 renderer = gtk_cell_renderer_text_new ();
25c6412d 340 column = gtk_tree_view_column_new_with_attributes ("Max IRQ handler duration (nsec) [time interval]",
446b4179 341 renderer,
342 "text", MAX_IRQ_HANDLER_COLUMN,
343 NULL);
344 gtk_tree_view_column_set_alignment (column, 0.0);
345 gtk_tree_view_column_set_fixed_width (column, 250);
346 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
05600f3b 347
348 renderer = gtk_cell_renderer_text_new ();
349 column = gtk_tree_view_column_new_with_attributes ("Min IRQ handler duration (nsec) [time interval]",
350 renderer,
351 "text", MIN_IRQ_HANDLER_COLUMN,
352 NULL);
353 gtk_tree_view_column_set_alignment (column, 0.0);
354 gtk_tree_view_column_set_fixed_width (column, 250);
355 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
356
52948a62 357 renderer = gtk_cell_renderer_text_new ();
358 column = gtk_tree_view_column_new_with_attributes (" Average period (nsec)",
359 renderer,
360 "text", AVERAGE_PERIOD,
361 NULL);
362 gtk_tree_view_column_set_alignment (column, 0.0);
363 gtk_tree_view_column_set_fixed_width (column, 200);
364 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
365
366 renderer = gtk_cell_renderer_text_new ();
367 column = gtk_tree_view_column_new_with_attributes ("Period standard deviation (nsec)",
368 renderer,
369 "text", PERIOD_STANDARD_DEV_COLUMN,
370 NULL);
371 gtk_tree_view_column_set_alignment (column, 0.0);
372 gtk_tree_view_column_set_fixed_width (column, 200);
373 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
374
ecafd9df 375 renderer = gtk_cell_renderer_text_new ();
376 column = gtk_tree_view_column_new_with_attributes ("Frequency standard deviation (Hz)",
377 renderer,
378 "text", FREQUENCY_STANDARD_DEV_COLUMN,
379 NULL);
380 gtk_tree_view_column_set_alignment (column, 0.0);
381 gtk_tree_view_column_set_fixed_width (column, 200);
382 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
52948a62 383
dc06b1bc 384
b3e7b125 385 event_viewer_data->SelectionTree = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data->TreeView));
386 gtk_tree_selection_set_mode (event_viewer_data->SelectionTree, GTK_SELECTION_SINGLE);
5f5119ee 387
b3e7b125 388 gtk_container_add (GTK_CONTAINER (event_viewer_data->ScrollWindow), event_viewer_data->TreeView);
5f5119ee 389
b3e7b125 390 event_viewer_data->Hbox = gtk_hbox_new(0, 0);
391 gtk_box_pack_start(GTK_BOX(event_viewer_data->Hbox), event_viewer_data->ScrollWindow, TRUE, TRUE, 0);
5f5119ee 392
b3e7b125 393 gtk_widget_show(event_viewer_data->Hbox);
394 gtk_widget_show(event_viewer_data->TreeView);
5f5119ee 395
b3e7b125 396 interrupt_data_list = g_slist_append(interrupt_data_list, event_viewer_data);
f2ec7aa9 397 /* Registration for time notification */
b3e7b125 398 lttvwindow_register_time_window_notify(tab,
399 interrupt_update_time_window,
400 event_viewer_data);
f2ec7aa9 401
fc77fe59 402 g_object_set_data_full(G_OBJECT(event_viewer_data->Hbox),
403 "event_data",
404 event_viewer_data,
405 (GDestroyNotify) InterruptFree);
f2ec7aa9 406
dc06b1bc 407 FirstRequest(event_viewer_data );
5f5119ee 408 return event_viewer_data;
409}
b3e7b125 410
fc77fe59 411
f2ec7aa9 412/**
413 *
414 * For each trace in the traceset, this function:
415 * - registers a callback function to each hook
416 * - calls lttv_trace_find_hook() registers a hook function to event_by_id_hooks
417 * - calls lttvwindow_events_request() to request data in a specific
418 * time interval to the main window
419 *
420 */
dc06b1bc 421static void FirstRequest(InterruptEventData *event_data )
f2ec7aa9 422{
423 guint i, k, l, nb_trace;
424
425 LttvTraceHook *hook;
426
427 guint ret;
428
429 LttvTraceState *ts;
430
431 GArray *hooks;
432
433 EventsRequest *events_request;
434
c88429fb 435 LttvTraceHook *th;
f2ec7aa9 436
437 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
5f5119ee 438
f2ec7aa9 439
440 /* Get the traceset */
441 LttvTraceset *traceset = tsc->ts;
5f5119ee 442
f2ec7aa9 443 nb_trace = lttv_traceset_number(traceset);
444
445 /* There are many traces in a traceset. Iteration for each trace. */
8402f27d 446 //for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++) {
447 for(i = 0 ; i < nb_trace ; i++) {
f2ec7aa9 448 events_request = g_new(EventsRequest, 1);
449
c88429fb 450 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 2);
b3e7b125 451
f2ec7aa9 452 event_data->hooks_trace_before = lttv_hooks_new();
453
454 /* Registers a hook function */
455 lttv_hooks_add(event_data->hooks_trace_before, trace_header, event_data, LTTV_PRIO_DEFAULT);
456
457 event_data->hooks_trace_after = lttv_hooks_new();
dc06b1bc 458
459 /* Registers a hook function */
460 lttv_hooks_add(event_data->hooks_trace_after, SecondRequest, event_data, LTTV_PRIO_DEFAULT);
f2ec7aa9 461 /* Get a trace state */
462 ts = (LttvTraceState *)tsc->traces[i];
463 /* Create event_by_Id hooks */
c88429fb 464 event_data->event_by_id_hooks = lttv_hooks_by_id_new();
b3e7b125 465
f2ec7aa9 466 /*Register event_by_id_hooks with a callback function*/
c88429fb 467 lttv_trace_find_hook(ts->parent.t,
468 LTT_FACILITY_KERNEL,
469 LTT_EVENT_IRQ_ENTRY,
470 FIELD_ARRAY(LTT_FIELD_IRQ_ID),
dc06b1bc 471 FirstRequestIrqEntryCallback,
f2ec7aa9 472 events_request,
c88429fb 473 &hooks);
f2ec7aa9 474
c88429fb 475 lttv_trace_find_hook(ts->parent.t,
476 LTT_FACILITY_KERNEL,
477 LTT_EVENT_IRQ_EXIT,
478 NULL,
dc06b1bc 479 FirstRequestIrqExitCallback,
f2ec7aa9 480 events_request,
c88429fb 481 &hooks);
f2ec7aa9 482
f2ec7aa9 483 /*iterate through the facility list*/
484 for(k = 0 ; k < hooks->len; k++)
485 {
c88429fb 486 th = &g_array_index(hooks, LttvTraceHook, k);
487 lttv_hooks_add(lttv_hooks_by_id_find(event_data->event_by_id_hooks, th->id),
488 th->h,
489 th,
490 LTTV_PRIO_DEFAULT);
f2ec7aa9 491
f2ec7aa9 492 }
493 /* Initalize the EventsRequest structure */
494 events_request->owner = event_data;
495 events_request->viewer_data = event_data;
496 events_request->servicing = FALSE;
497 events_request->start_time = event_data->time_window.start_time;
498 events_request->start_position = NULL;
499 events_request->stop_flag = FALSE;
500 events_request->end_time = event_data->time_window.end_time;
501 events_request->num_events = G_MAXUINT;
502 events_request->end_position = NULL;
503 events_request->trace = i;
504
505 events_request->hooks = hooks;
506
507 events_request->before_chunk_traceset = NULL;
508 events_request->before_chunk_trace = event_data->hooks_trace_before;
509 events_request->before_chunk_tracefile= NULL;
510 events_request->event = NULL;
511 events_request->event_by_id = event_data->event_by_id_hooks;
512 events_request->after_chunk_tracefile = NULL;
231a6432 513 events_request->after_chunk_trace = NULL;
f2ec7aa9 514 events_request->after_chunk_traceset = NULL;
231a6432 515 events_request->before_request = NULL;
f2ec7aa9 516 events_request->after_request = event_data->hooks_trace_after;
517
518 lttvwindow_events_request(event_data->tab, events_request);
519 }
520
b3e7b125 521}
5f5119ee 522
f2ec7aa9 523/**
524 * This function is called whenever an irq_entry event occurs.
525 *
526 */
dc06b1bc 527static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data)
f2ec7aa9 528{
529
b3e7b125 530 LttTime event_time;
b3e7b125 531 unsigned cpu_id;
532 irq_entry entry;
b3e7b125 533 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
534 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
c88429fb 535 LttvTraceHook *th = (LttvTraceHook*) hook_data;
536 EventsRequest *events_request = (EventsRequest*)th->hook_data;
537 InterruptEventData *event_data = events_request->viewer_data;
dc06b1bc 538 GArray* FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
f2ec7aa9 539 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
b3e7b125 540 event_time = ltt_event_time(e);
c88429fb 541 cpu_id = tfs->cpu;
f2ec7aa9 542
231a6432 543
c88429fb 544 entry.id = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
231a6432 545 entry.cpu_id = cpu_id;
546 entry.event_time = event_time;
dc06b1bc 547 g_array_append_val (FirstRequestIrqEntry, entry);
231a6432 548
f2ec7aa9 549 return FALSE;
5f5119ee 550}
551
f2ec7aa9 552/**
553 * This function is called whenever an irq_exit event occurs.
554 *
555 */
dc06b1bc 556gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data)
f2ec7aa9 557{
558 LttTime event_time;
559 unsigned cpu_id;
5f5119ee 560 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
f2ec7aa9 561 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
c88429fb 562 LttvTraceHook *th = (LttvTraceHook*) hook_data;
563 EventsRequest *events_request = (EventsRequest*)th->hook_data;
564 InterruptEventData *event_data = events_request->viewer_data;
f2ec7aa9 565 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
f2ec7aa9 566 event_time = ltt_event_time(e);
c88429fb 567 cpu_id = tfs->cpu;
231a6432 568
e5258c09 569 CalculateData( event_time, cpu_id, event_data);
570
231a6432 571 return FALSE;
5f5119ee 572}
573
f2ec7aa9 574/**
575 * This function calculates the duration of an interrupt.
576 *
577 */
e5258c09 578static void CalculateData(LttTime time_exit, guint cpu_id,InterruptEventData *event_data)
dc06b1bc 579{
5f5119ee 580
f2ec7aa9 581 gint i, irq_id;
582 irq_entry *element;
583 LttTime duration;
dc06b1bc 584 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
585 GArray *FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
586 for(i = 0; i < FirstRequestIrqEntry->len; i++)
231a6432 587 {
dc06b1bc 588 element = &g_array_index(FirstRequestIrqEntry,irq_entry,i);
231a6432 589 if(element->cpu_id == cpu_id)
590 {
ecafd9df 591 CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(element,time_exit, FirstRequestIrqExit);
dc06b1bc 592 g_array_remove_index(FirstRequestIrqEntry, i);
f2ec7aa9 593 break;
594 }
595 }
e5258c09 596}
ecafd9df 597
dc06b1bc 598
f2ec7aa9 599/**
ecafd9df 600 * This function calculates the total duration of an interrupt and the longest & shortest Irq handlers.
f2ec7aa9 601 *
602 */
ecafd9df 603static void CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit)
604{
5f5119ee 605 Irq irq;
606 Irq *element;
607 guint i;
608 LttTime duration;
609 gboolean notFound = FALSE;
610 memset ((void*)&irq, 0,sizeof(Irq));
611
231a6432 612 /*first time*/
dc06b1bc 613 if(FirstRequestIrqExit->len == NO_ITEMS)
231a6432 614 {
5f5119ee 615 irq.cpu_id = e->cpu_id;
616 irq.id = e->id;
31935b31 617 irq.TotalNumberOfInterrupts++;
5f5119ee 618 irq.total_duration = ltt_time_sub(time_exit, e->event_time);
e5258c09 619
446b4179 620 irq.max_irq_handler.start_time = e->event_time;
621 irq.max_irq_handler.end_time = time_exit;
622 irq.max_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
ecafd9df 623
624 irq.min_irq_handler.start_time = e->event_time;
625 irq.min_irq_handler.end_time = time_exit;
626 irq.min_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
e5258c09 627
dc06b1bc 628 g_array_append_val (FirstRequestIrqExit, irq);
5f5119ee 629 }
231a6432 630 else
631 {
dc06b1bc 632 for(i = 0; i < FirstRequestIrqExit->len; i++)
231a6432 633 {
dc06b1bc 634 element = &g_array_index(FirstRequestIrqExit,Irq,i);
635 if(element->id == e->id)
636 {
5f5119ee 637 notFound = TRUE;
638 duration = ltt_time_sub(time_exit, e->event_time);
639 element->total_duration = ltt_time_add(element->total_duration, duration);
31935b31 640 element->TotalNumberOfInterrupts++;
ecafd9df 641 // Max irq handler
446b4179 642 if(ltt_time_compare(duration,element->max_irq_handler.duration) > 0)
643 {
644 element->max_irq_handler.duration = duration;
645 element->max_irq_handler.start_time = e->event_time;
646 element->max_irq_handler.end_time = time_exit;
647 }
ecafd9df 648 // Min irq handler
649 if(ltt_time_compare(duration,element->min_irq_handler.duration) < 0)
650 {
651 element->min_irq_handler.duration = duration;
652 element->min_irq_handler.start_time = e->event_time;
653 element->min_irq_handler.end_time = time_exit;
654 }
5f5119ee 655 }
656 }
231a6432 657 if(!notFound)
658 {
5f5119ee 659 irq.cpu_id = e->cpu_id;
660 irq.id = e->id;
31935b31 661 irq.TotalNumberOfInterrupts++;
5f5119ee 662 irq.total_duration = ltt_time_sub(time_exit, e->event_time);
ecafd9df 663 // Max irq handler
446b4179 664 irq.max_irq_handler.start_time = e->event_time;
665 irq.max_irq_handler.end_time = time_exit;
666 irq.max_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
ecafd9df 667 // Min irq handler
668 irq.min_irq_handler.start_time = e->event_time;
669 irq.min_irq_handler.end_time = time_exit;
670 irq.min_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
446b4179 671
dc06b1bc 672 g_array_append_val (FirstRequestIrqExit, irq);
5f5119ee 673 }
674 }
675}
231a6432 676
e5258c09 677/**
678 * This function passes the second EventsRequest to LTTV
679 *
680 */
dc06b1bc 681static gboolean SecondRequest(void *hook_data, void *call_data)
682{
683
684 guint i, k, l, nb_trace;
685
686 LttvTraceHook *hook;
687
688 guint ret;
689
690 LttvTraceState *ts;
691
692 GArray *hooks;
693
694 EventsRequest *events_request;
695
c88429fb 696 LttvTraceHook *th;
dc06b1bc 697
698 InterruptEventData *event_data = (InterruptEventData *)hook_data;
699
700 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
701
702 CalculateAverageDurationForEachIrqId(event_data);
703
704 /* Get the traceset */
705 LttvTraceset *traceset = tsc->ts;
706
707 nb_trace = lttv_traceset_number(traceset);
708
709 /* There are many traces in a traceset. Iteration for each trace. */
8402f27d 710 for(i = 0 ; i < nb_trace ; i++) {
711 // fixed for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++) {
dc06b1bc 712 events_request = g_new(EventsRequest, 1);
713
c88429fb 714 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 2);
dc06b1bc 715
dc06b1bc 716 event_data->hooks_trace_after = lttv_hooks_new();
717
718 /* Registers a hook function */
719 lttv_hooks_add(event_data->hooks_trace_after, DisplayViewer, event_data, LTTV_PRIO_DEFAULT);
720
721 /* Get a trace state */
722 ts = (LttvTraceState *)tsc->traces[i];
723 /* Create event_by_Id hooks */
724 event_data->event_by_id_hooks = lttv_hooks_by_id_new();
725
726 /*Register event_by_id_hooks with a callback function*/
727 ret = lttv_trace_find_hook(ts->parent.t,
c88429fb 728 LTT_FACILITY_KERNEL,
729 LTT_EVENT_IRQ_ENTRY,
730 FIELD_ARRAY(LTT_FIELD_IRQ_ID),
dc06b1bc 731 SecondRequestIrqEntryCallback,
732 events_request,
c88429fb 733 &hooks);
dc06b1bc 734
735 ret = lttv_trace_find_hook(ts->parent.t,
c88429fb 736 LTT_FACILITY_KERNEL,
737 LTT_EVENT_IRQ_EXIT,
738 NULL,
dc06b1bc 739 SecondRequestIrqExitCallback,
740 events_request,
c88429fb 741 &hooks);
dc06b1bc 742
743 g_assert(!ret);
e5258c09 744
745 /* iterate through the facility list */
dc06b1bc 746 for(k = 0 ; k < hooks->len; k++)
747 {
c88429fb 748 th = &g_array_index(hooks, LttvTraceHook, k);
749 lttv_hooks_add(lttv_hooks_by_id_find(event_data->event_by_id_hooks, th->id),
750 th->h,
751 th,
752 LTTV_PRIO_DEFAULT);
dc06b1bc 753
dc06b1bc 754 }
755 /* Initalize the EventsRequest structure */
756 events_request->owner = event_data;
757 events_request->viewer_data = event_data;
758 events_request->servicing = FALSE;
759 events_request->start_time = event_data->time_window.start_time;
760 events_request->start_position = NULL;
761 events_request->stop_flag = FALSE;
762 events_request->end_time = event_data->time_window.end_time;
763 events_request->num_events = G_MAXUINT;
764 events_request->end_position = NULL;
765 events_request->trace = i;
766
767 events_request->hooks = hooks;
768
769 events_request->before_chunk_traceset = NULL;
770 events_request->before_chunk_trace = NULL;
771 events_request->before_chunk_tracefile= NULL;
772 events_request->event = NULL;
773 events_request->event_by_id = event_data->event_by_id_hooks;
774 events_request->after_chunk_tracefile = NULL;
775 events_request->after_chunk_trace = NULL;
776 events_request->after_chunk_traceset = NULL;
777 events_request->before_request = NULL;
778 events_request->after_request = event_data->hooks_trace_after;
779
780 lttvwindow_events_request(event_data->tab, events_request);
781 }
e5258c09 782 return FALSE;
dc06b1bc 783}
784
ecafd9df 785/**
786 * This function calculates the average duration for each Irq Id
787 *
788 */
dc06b1bc 789static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data)
790{
791 guint64 real_data;
792 Irq *element;
793 gint i;
794 GArray* FirstRequestIrqExit = event_data->FirstRequestIrqExit;
795 for(i = 0; i < FirstRequestIrqExit->len; i++)
796 {
797 element = &g_array_index(FirstRequestIrqExit,Irq,i);
798 real_data = element->total_duration.tv_sec;
799 real_data *= NANOSECONDS_PER_SECOND;
800 real_data += element->total_duration.tv_nsec;
31935b31 801 if(element->TotalNumberOfInterrupts != 0)
802 element->average_duration = real_data / element->TotalNumberOfInterrupts;
ecafd9df 803 else
804 element->average_duration = 0;
dc06b1bc 805 }
806
807}
808
e5258c09 809/**
810 * This function is called whenever an irq_entry event occurs. Use in the second request
811 *
812 */
dc06b1bc 813static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data)
814{
815
816 LttTime event_time;
817 unsigned cpu_id;
818 irq_entry entry;
819 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
820 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
c88429fb 821 LttvTraceHook *th = (LttvTraceHook *)hook_data;
822 EventsRequest *events_request = (EventsRequest*)th->hook_data;
823 InterruptEventData *event_data = events_request->viewer_data;
dc06b1bc 824 GArray* SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
825 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
826 event_time = ltt_event_time(e);
c88429fb 827 cpu_id = tfs->cpu;
dc06b1bc 828
829
c88429fb 830 entry.id = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
dc06b1bc 831 entry.cpu_id = cpu_id;
832 entry.event_time = event_time;
833 g_array_append_val (SecondRequestIrqEntry, entry);
834
835 return FALSE;
836}
837
e5258c09 838/**
839 * This function is called whenever an irq_exit event occurs in the second request.
840 *
841 */
dc06b1bc 842static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data)
843{
844
845 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
846 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
c88429fb 847 LttvTraceHook *th = (LttvTraceHook *)hook_data;
848 EventsRequest *events_request = (EventsRequest*)th->hook_data;
849 InterruptEventData *event_data = events_request->viewer_data;
850
dc06b1bc 851 LttEvent *event = ltt_tracefile_get_event(tfc->tf);
852
c88429fb 853 CalculateXi(event, event_data, tfs->cpu);
dc06b1bc 854 return FALSE;
855}
856
e5258c09 857
858/**
859 * This function is called whenever an irq_exit event occurs in the second request.
860 *
861 */
c88429fb 862static void CalculateXi(LttEvent *event_irq_exit, InterruptEventData *event_data, guint cpu_id)
dc06b1bc 863{
864 gint i, irq_id;
865 irq_entry *element;
866 LttTime Xi;
867 LttTime exit_time;
dc06b1bc 868
869 GArray *SecondRequestIrqExit = event_data->SecondRequestIrqExit;
870 GArray *SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
dc06b1bc 871 for(i = 0; i < SecondRequestIrqEntry->len; i++)
872 {
873 element = &g_array_index(SecondRequestIrqEntry,irq_entry,i);
874 if(element->cpu_id == cpu_id)
875 {
876
877 /* time calculation */
878 exit_time = ltt_event_time(event_irq_exit);
879 Xi = ltt_time_sub(exit_time, element->event_time);
880 irq_id = element->id;
881
882 SumItems(irq_id, Xi,event_data);
883 g_array_remove_index(SecondRequestIrqEntry, i);
884 break;
885 }
886 }
887}
888
e5258c09 889
890/**
891 * This function computes the Sum ((xi -Xa)^2) and store the result in SumArray
892 *
893 */
dc06b1bc 894static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data)
895{
896 gint i;
6b0817c2 897 guint Xi_in_ns;
dc06b1bc 898
6b0817c2 899 gint duration_inner_part;
900 guint64 period_inner_part;
ecafd9df 901 guint64 frequency_inner_part;
902
dc06b1bc 903 Irq *average;
904 SumId *sumItem;
905 SumId sum;
6b0817c2 906 int FrequencyHZ = 0;
dc06b1bc 907 gboolean notFound = FALSE;
908 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
909 GArray *SumArray = event_data->SumArray;
6b0817c2 910 Xi_in_ns = Xi.tv_sec;
911 Xi_in_ns *= NANOSECONDS_PER_SECOND;
912 Xi_in_ns += Xi.tv_nsec;
dc06b1bc 913
914 for(i = 0; i < FirstRequestIrqExit->len; i++)
915 {
916 average = &g_array_index(FirstRequestIrqExit,Irq,i);
917 if(irq_id == average->id)
918 {
6b0817c2 919 duration_inner_part = Xi_in_ns - average->average_duration;
31935b31 920 FrequencyHZ = FrequencyInHZ(average->TotalNumberOfInterrupts, event_data->time_window);
dc06b1bc 921 sum.irqId = irq_id;
ecafd9df 922 // compute (xi -Xa)^2 of the duration Standard deviation
31935b31 923 sum.TotalNumberOfInterrupts = average->TotalNumberOfInterrupts;
6b0817c2 924 sum.sumOfDurations = pow (duration_inner_part , 2);
ecafd9df 925
926 // compute (xi -Xa)^2 of the period Standard deviation
6b0817c2 927 period_inner_part = CalculatePeriodInnerPart(Xi_in_ns, FrequencyHZ);
ecafd9df 928
929 // compute (xi -Xa)^2 of the frequency Standard deviation
930 frequency_inner_part = CalculateFrequencyInnerPart(Xi_in_ns, FrequencyHZ);
931
6b0817c2 932 sum.sumOfPeriods = period_inner_part;
ecafd9df 933
934 sum.sumOfFrequencies = frequency_inner_part;
935
dc06b1bc 936 if(event_data->SumArray->len == NO_ITEMS)
937 {
938 g_array_append_val (SumArray, sum);
939 }
940 else
6b0817c2 941 {
dc06b1bc 942 for(i = 0; i < SumArray->len; i++)
943 {
944 sumItem = &g_array_index(SumArray, SumId, i);
945 if(sumItem->irqId == irq_id)
946 {
947 notFound = TRUE;
948 sumItem->sumOfDurations += sum.sumOfDurations;
6b0817c2 949 sumItem->sumOfPeriods += sum.sumOfPeriods;
ecafd9df 950 sumItem->sumOfFrequencies += sum.sumOfFrequencies;
951 }
dc06b1bc 952 }
953 if(!notFound)
954 {
955 g_array_append_val (SumArray, sum);
956 }
6b0817c2 957
dc06b1bc 958 }
959
960 }
961 }
962}
963
ecafd9df 964/**
965 * This function computes the inner part of the period standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
966 * The inner part is: (xi -Xa)^2
967 */
6b0817c2 968static guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ)
969{
970
971 double periodInSec; /*period in sec*/
972 int periodInNSec;
973 gint difference;
974 guint64 result;
975 periodInSec = (double)1/FrequencyHZ;
976 periodInSec *= NANOSECONDS_PER_SECOND;
977 periodInNSec = (int)periodInSec;
978
979 difference = Xi - periodInNSec;
980 result = pow (difference , 2);
6b0817c2 981 return result;
ecafd9df 982}
6b0817c2 983
ecafd9df 984/**
985 * This function computes the inner part of the frequency standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
986 * The inner part is: (xi -Xa)^2
987 */
988static guint64 CalculateFrequencyInnerPart(guint Xi_in_ns, guint FrequencyHZ)
989{
990 guint64 result;
991 gint difference;
992
993 difference = Xi_in_ns - FrequencyHZ;
994 result = pow (difference , 2);
995 return result;
6b0817c2 996}
f2ec7aa9 997/**
998 * This function displays the result on the viewer
999 *
1000 */
dc06b1bc 1001static gboolean DisplayViewer(void *hook_data, void *call_data)
1002{
5f5119ee 1003
dc06b1bc 1004 guint average;
f2ec7aa9 1005 gint i;
1006 Irq element;
1007 LttTime average_duration;
1008 GtkTreeIter iter;
1009 guint64 real_data;
446b4179 1010 guint maxIRQduration;
05600f3b 1011 guint minIRQduration;
6b0817c2 1012 double periodInSec;
1013 int periodInNsec;
e5258c09 1014 char maxIrqHandler[80];
05600f3b 1015 char minIrqHandler[80];
f2ec7aa9 1016 InterruptEventData *event_data = (InterruptEventData *)hook_data;
dc06b1bc 1017 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
52948a62 1018 int FrequencyHZ = 0;
6b0817c2 1019 periodInSec = 0;
f2ec7aa9 1020 gtk_list_store_clear(event_data->ListStore);
dc06b1bc 1021 for(i = 0; i < FirstRequestIrqExit->len; i++)
231a6432 1022 {
dc06b1bc 1023 element = g_array_index(FirstRequestIrqExit,Irq,i);
f2ec7aa9 1024 real_data = element.total_duration.tv_sec;
1025 real_data *= NANOSECONDS_PER_SECOND;
1026 real_data += element.total_duration.tv_nsec;
446b4179 1027
1028
1029 maxIRQduration = element.max_irq_handler.duration.tv_sec;
1030 maxIRQduration *= NANOSECONDS_PER_SECOND;
1031 maxIRQduration += element.max_irq_handler.duration.tv_nsec;
e5258c09 1032
fc77fe59 1033 sprintf(maxIrqHandler, "%d [%d.%d - %d.%d]",maxIRQduration, element.max_irq_handler.start_time.tv_sec, \
1034 element.max_irq_handler.start_time.tv_nsec, element.max_irq_handler.end_time.tv_sec, \
1035 element.max_irq_handler.end_time.tv_nsec) ;
05600f3b 1036
1037 minIRQduration = element.min_irq_handler.duration.tv_sec;
1038 minIRQduration *= NANOSECONDS_PER_SECOND;
1039 minIRQduration += element.min_irq_handler.duration.tv_nsec;
1040 sprintf(minIrqHandler, "%d [%d.%d - %d.%d]",minIRQduration, element.min_irq_handler.start_time.tv_sec, \
1041 element.min_irq_handler.start_time.tv_nsec, element.min_irq_handler.end_time.tv_sec, \
1042 element.min_irq_handler.end_time.tv_nsec) ;
1043
1044
31935b31 1045 FrequencyHZ = FrequencyInHZ(element.TotalNumberOfInterrupts,event_data->time_window);
6b0817c2 1046
52948a62 1047 if(FrequencyHZ != 0)
1048 {
6b0817c2 1049 periodInSec = (double)1/FrequencyHZ;
1050 periodInSec *= NANOSECONDS_PER_SECOND;
1051 periodInNsec = (int)periodInSec;
ecafd9df 1052
52948a62 1053 }
6b0817c2 1054
f2ec7aa9 1055 gtk_list_store_append (event_data->ListStore, &iter);
1056 gtk_list_store_set (event_data->ListStore, &iter,
1057 CPUID_COLUMN, element.cpu_id,
1058 IRQ_ID_COLUMN, element.id,
52948a62 1059 FREQUENCY_COLUMN, FrequencyHZ,
f2ec7aa9 1060 DURATION_COLUMN, real_data,
6b0817c2 1061 DURATION_STANDARD_DEV_COLUMN, CalculateDurationStandardDeviation(element.id, event_data),
e5258c09 1062 MAX_IRQ_HANDLER_COLUMN, maxIrqHandler,
05600f3b 1063 MIN_IRQ_HANDLER_COLUMN, minIrqHandler,
6b0817c2 1064 AVERAGE_PERIOD , periodInNsec,
1065 PERIOD_STANDARD_DEV_COLUMN, CalculatePeriodStandardDeviation(element.id, event_data),
ecafd9df 1066 FREQUENCY_STANDARD_DEV_COLUMN, CalculateFrequencyStandardDeviation(element.id, event_data),
8f72bb94 1067 -1);
f2ec7aa9 1068 }
dc06b1bc 1069
dc06b1bc 1070
1071 if(event_data->FirstRequestIrqExit->len)
231a6432 1072 {
dc06b1bc 1073 g_array_remove_range (event_data->FirstRequestIrqExit,0,event_data->FirstRequestIrqExit->len);
231a6432 1074 }
1075
dc06b1bc 1076 if(event_data->FirstRequestIrqEntry->len)
231a6432 1077 {
dc06b1bc 1078 g_array_remove_range (event_data->FirstRequestIrqEntry,0,event_data->FirstRequestIrqEntry->len);
1079 }
1080
1081 if(event_data->SecondRequestIrqEntry->len)
1082 {
1083 g_array_remove_range (event_data->SecondRequestIrqEntry,0,event_data->SecondRequestIrqEntry->len);
1084 }
231a6432 1085
dc06b1bc 1086 if(event_data->SecondRequestIrqExit->len)
1087 {
1088 g_array_remove_range (event_data->SecondRequestIrqExit,0, event_data->SecondRequestIrqExit->len);
1089 }
1090
1091 if(event_data->SumArray->len)
1092 {
1093 g_array_remove_range (event_data->SumArray,0, event_data->SumArray->len);
231a6432 1094 }
dc06b1bc 1095
f2ec7aa9 1096 return FALSE;
5f5119ee 1097}
dc06b1bc 1098
25c6412d 1099
6b0817c2 1100/**
1101 * This function converts the number of interrupts over a time window to
1102 * frequency in HZ
1103 */
ecafd9df 1104static int FrequencyInHZ(gint NumerofInterruptions, TimeWindow time_window)
25c6412d 1105{
1106 guint64 frequencyHz = 0;
6b0817c2 1107 double timeSec; // time in second
1108 double result;
1109 result = ltt_time_to_double(time_window.time_width);
1110 timeSec = (result/NANOSECONDS_PER_SECOND); //time in second
ecafd9df 1111 frequencyHz = NumerofInterruptions / timeSec;
25c6412d 1112 return frequencyHz;
1113}
1114
e5258c09 1115/**
6b0817c2 1116 * This function calculates the duration standard deviation
ecafd9df 1117 * Duration standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
1118 * Where:
1119 * sumId.sumOfDurations -> Sum ((xi -Xa)^2)
1120 * inner_component -> 1/N Sum ((xi -Xa)^2)
1121 * deviation-> sqrt(1/N Sum ((xi -Xa)^2))
e5258c09 1122 */
6b0817c2 1123static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event_data)
dc06b1bc 1124{
1125 int i;
1126 SumId sumId;
1127 double inner_component;
1128 int deviation = 0;
1129 for(i = 0; i < event_data->SumArray->len; i++)
1130 {
1131 sumId = g_array_index(event_data->SumArray, SumId, i);
1132 if(id == sumId.irqId)
1133 {
31935b31 1134 if(sumId.TotalNumberOfInterrupts != 0)
1135 inner_component = sumId.sumOfDurations/ sumId.TotalNumberOfInterrupts;
ecafd9df 1136 else
1137 inner_component = 0.0;
dc06b1bc 1138 deviation = sqrt(inner_component);
25c6412d 1139 return deviation;
dc06b1bc 1140 }
1141 }
1142 return deviation;
1143}
6b0817c2 1144
1145
1146/**
1147 * This function calculates the period standard deviation
ecafd9df 1148 * Period standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
1149 * Where:
1150 * sumId.sumOfPeriods -> Sum ((xi -Xa)^2)
1151 * inner_component -> 1/N Sum ((xi -Xa)^2)
1152 * period_standard_deviation-> sqrt(1/N Sum ((xi -Xa)^2))
1153
6b0817c2 1154 *
1155 */
1156static int CalculatePeriodStandardDeviation(gint id, InterruptEventData *event_data)
1157{
1158 int i;
1159 SumId sumId;
1160 guint64 inner_component;
1161 guint64 period_standard_deviation = 0;
ecafd9df 1162
6b0817c2 1163 for(i = 0; i < event_data->SumArray->len; i++)
1164 {
1165 sumId = g_array_index(event_data->SumArray, SumId, i);
1166 if(id == sumId.irqId)
1167 {
31935b31 1168 if(sumId.TotalNumberOfInterrupts != 0)
1169 inner_component = sumId.sumOfPeriods / sumId.TotalNumberOfInterrupts;
ecafd9df 1170 else
1171 inner_component = 0;
1172
6b0817c2 1173 period_standard_deviation = sqrt(inner_component);
1174 }
1175 }
1176
1177 return period_standard_deviation;
1178}
ecafd9df 1179
1180/**
1181 * This function calculates the frequency standard deviation
1182 * Frequency standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
1183 * Where:
1184 * sumId.sumOfFrequencies -> Sum ((xi -Xa)^2)
1185 * inner_component -> 1/N Sum ((xi -Xa)^2)
1186 * frequency_standard_deviation-> sqrt(1/N Sum ((xi -Xa)^2))
1187 *
1188 */
1189static int CalculateFrequencyStandardDeviation(gint id, InterruptEventData *event_data)
1190{
1191 int i;
1192 SumId sumId;
1193 guint64 inner_component;
1194 guint64 frequency_standard_deviation = 0;
1195 for(i = 0; i < event_data->SumArray->len; i++)
1196 {
1197 sumId = g_array_index(event_data->SumArray, SumId, i);
1198 if(id == sumId.irqId)
1199 {
31935b31 1200 if(sumId.TotalNumberOfInterrupts != 0)
1201 inner_component = sumId.sumOfFrequencies / sumId.TotalNumberOfInterrupts;
ecafd9df 1202 else
1203 inner_component = 0;
1204
1205 frequency_standard_deviation = sqrt(inner_component);
1206 }
1207 }
1208 return frequency_standard_deviation;
1209}
1210
f2ec7aa9 1211/*
1212 * This function is called by the main window
1213 * when the time interval needs to be updated.
1214 **/
1215gboolean interrupt_update_time_window(void * hook_data, void * call_data)
1216{
5f5119ee 1217 InterruptEventData *event_data = (InterruptEventData *) hook_data;
1218 const TimeWindowNotifyData *time_window_nofify_data = ((const TimeWindowNotifyData *)call_data);
1219 event_data->time_window = *time_window_nofify_data->new_time_window;
1220 g_info("interrupts: interrupt_update_time_window()\n");
1221 Tab *tab = event_data->tab;
1222 lttvwindow_events_request_remove_all(tab, event_data);
dc06b1bc 1223 FirstRequest(event_data );
f2ec7aa9 1224 return FALSE;
5f5119ee 1225}
1226
f2ec7aa9 1227
1228gboolean trace_header(void *hook_data, void *call_data)
1229{
1230
1231 InterruptEventData *event_data = (InterruptEventData *)hook_data;
1232 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
f2ec7aa9 1233 LttEvent *e;
1234 LttTime event_time;
1235 return FALSE;
5f5119ee 1236}
1237
f2ec7aa9 1238void interrupt_destroy_walk(gpointer data, gpointer user_data)
1239{
5f5119ee 1240 g_info("interrupt_destroy_walk");
fc77fe59 1241 InterruptEventData *event_data = (InterruptEventData*) data;
5f5119ee 1242 interrupt_destructor((InterruptEventData*)data);
5f5119ee 1243}
1244
fc77fe59 1245
f2ec7aa9 1246void interrupt_destructor(InterruptEventData *event_viewer_data)
1247{
1248 /* May already been done by GTK window closing */
1249 g_info("enter interrupt_destructor \n");
1250 if(GTK_IS_WIDGET(event_viewer_data->Hbox))
1251 {
1252 gtk_widget_destroy(event_viewer_data->Hbox);
1253 }
1254}
1255
fc77fe59 1256/**
1257 This function is called when the viewer is destroyed to free hooks and memory
1258*/
1259static void InterruptFree(InterruptEventData *event_viewer_data)
1260{
1261 Tab *tab = event_viewer_data->tab;
1262 if(tab != NULL)
1263 {
1264
1265 g_array_free(event_viewer_data->FirstRequestIrqExit, TRUE);
1266 g_array_free(event_viewer_data->FirstRequestIrqEntry, TRUE);
1267 g_array_free(event_viewer_data->SecondRequestIrqEntry, TRUE);
1268 g_array_free(event_viewer_data->SecondRequestIrqExit, TRUE);
1269 g_array_free(event_viewer_data->SumArray, TRUE);
1270
1271 lttvwindow_unregister_time_window_notify(tab, interrupt_update_time_window, event_viewer_data);
1272
1273 lttvwindow_events_request_remove_all(event_viewer_data->tab,
1274 event_viewer_data);
1275
1276 interrupt_data_list = g_slist_remove(interrupt_data_list, event_viewer_data);
1277
1278 }
1279
1280}
1281
5f5119ee 1282/**
1283 * plugin's destroy function
1284 *
1285 * This function releases the memory reserved by the module and unregisters
1286 * everything that has been registered in the gtkTraceSet API.
1287 */
dc06b1bc 1288static void destroy()
1289{
1290
5f5119ee 1291 g_info("Destroy interrupts");
1292 g_slist_foreach(interrupt_data_list, interrupt_destroy_walk, NULL );
1293 g_slist_free(interrupt_data_list);
1294 lttvwindow_unregister_constructor(interrupts);
1295
1296}
1297
1298LTTV_MODULE("interrupts", "interrupts info view", \
1299 "Graphical module to display interrupts performance", \
1300 init, destroy, "lttvwindow")
This page took 0.101344 seconds and 4 git commands to generate.