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