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