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