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