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