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