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