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