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