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