update compat
[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
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 <ltt/time.h>
86
87#include "hInterruptsInsert.xpm"
88
89#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
90#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
91#define NO_ITEMS 0
92
93typedef struct
94{
95 LttTime duration;
96 LttTime start_time;
97 LttTime end_time;
98}IrqDuration;
99
100typedef struct {
101 guint cpu_id;
102 guint id;
103 guint TotalNumberOfInterrupts;
104 LttTime total_duration;
105 guint average_duration;
106 IrqDuration max_irq_handler;
107 IrqDuration min_irq_handler;
108}Irq;
109
110typedef struct {
111 guint id;
112 guint cpu_id;
113 LttTime event_time;
114}irq_entry;
115
116
117typedef struct
118{
119 guint irqId;
120 guint TotalNumberOfInterrupts;//frequency;//
121 guint64 sumOfDurations; // to store the Sum ((xi -Xa)^2) of the duration Standard deviation
122 guint64 sumOfPeriods; // to store the Sum ((xi -Xa)^2) of the period Standard deviation
123 guint64 sumOfFrequencies;// to store the Sum ((xi -Xa)^2) of the frequency Standard deviation
124
125}SumId;
126
127enum type_t {
128 IRQ_ENTRY,
129 IRQ_EXIT
130};
131
132/** Array containing instanced objects. Used when module is unloaded */
133static GSList *interrupt_data_list = NULL ;
134
135
136#define TRACE_NUMBER 0
137
138typedef struct _InterruptEventData {
139
140 /*Graphical Widgets */
141 GtkWidget * ScrollWindow;
142 GtkListStore *ListStore;
143 GtkWidget *Hbox;
144 GtkWidget *TreeView;
145 GtkTreeSelection *SelectionTree;
146
147 Tab * tab; /* tab that contains this plug-in*/
148 LttvHooks * event_hooks;
149 LttvHooks * hooks_trace_after;
150 LttvHooks * hooks_trace_before;
151 TimeWindow time_window;
152 LttvHooksById * event_by_id_hooks;
153 GArray *FirstRequestIrqExit;
154 GArray *FirstRequestIrqEntry;
155 GArray *SecondRequestIrqEntry;
156 GArray *SecondRequestIrqExit;
157 GArray *SumArray;
158
159} InterruptEventData ;
160
161
162/* Function prototypes */
163
164static gboolean interrupt_update_time_window(void * hook_data, void * call_data);
165static GtkWidget *interrupts(Tab *tab);
166static InterruptEventData *system_info(Tab *tab);
167void interrupt_destructor(InterruptEventData *event_viewer_data);
168static void FirstRequest(InterruptEventData *event_data );
169static guint64 get_interrupt_id(LttEvent *e);
170static gboolean trace_header(void *hook_data, void *call_data);
171static gboolean DisplayViewer (void *hook_data, void *call_data);
172static void CalculateData(LttTime time_exit, guint cpu_id, InterruptEventData *event_data);
173static void CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit);
174static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data);
175static gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data);
176static gboolean SecondRequest(void *hook_data, void *call_data);
177static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data);
178static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data);
179static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data);
180static void CalculateXi(LttEvent *event, InterruptEventData *event_data);
181static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data);
182static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event_data);
183static int CalculatePeriodStandardDeviation(gint id, InterruptEventData *event_data);
184static int FrequencyInHZ(gint NumberOfInterruptions, TimeWindow time_window);
185static guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ);
186static guint64 CalculateFrequencyInnerPart(guint Xi_in_ns, guint FrequencyHZ);
187static void InterruptFree(InterruptEventData *event_viewer_data);
188static int CalculateFrequencyStandardDeviation(gint id, InterruptEventData *event_data);
189
190/* Enumeration of the columns */
191enum{
192 CPUID_COLUMN,
193 IRQ_ID_COLUMN,
194 FREQUENCY_COLUMN,
195 DURATION_COLUMN,
196 DURATION_STANDARD_DEV_COLUMN,
197 MAX_IRQ_HANDLER_COLUMN,
198 MIN_IRQ_HANDLER_COLUMN,
199 AVERAGE_PERIOD,
200 PERIOD_STANDARD_DEV_COLUMN,
201 FREQUENCY_STANDARD_DEV_COLUMN,
202 N_COLUMNS
203};
204
205
206
207/**
208 * init function
209 *
210 *
211 * This is the entry point of the viewer.
212 *
213 */
214static void init() {
215 g_info("interrupts: init()");
216 lttvwindow_register_constructor("interrupts",
217 "/",
218 "Insert Interrupts View",
219 hInterruptsInsert_xpm,
220 "Insert Interrupts View",
221 interrupts);
222
223}
224
225
226/**
227 * Constructor hook
228 *
229 */
230static GtkWidget *interrupts(Tab * tab)
231{
232
233 InterruptEventData* event_data = system_info(tab) ;
234 if(event_data)
235 return event_data->Hbox;
236 else
237 return NULL;
238}
239
240/**
241 * This function initializes the Event Viewer functionnality through the
242 * GTK API.
243 */
244InterruptEventData *system_info(Tab *tab)
245{
246
247 LttTime end;
248 GtkTreeViewColumn *column;
249 GtkCellRenderer *renderer;
250 InterruptEventData* event_viewer_data = g_new(InterruptEventData,1) ;
251
252 event_viewer_data->tab = tab;
253
254 /*Get the current time frame from the main window */
255 event_viewer_data->time_window = lttvwindow_get_time_window(tab);
256
257 event_viewer_data->FirstRequestIrqExit = g_array_new(FALSE, FALSE, sizeof(Irq));
258 event_viewer_data->FirstRequestIrqEntry = g_array_new(FALSE, FALSE, sizeof(irq_entry));
259
260 event_viewer_data->SecondRequestIrqEntry = g_array_new(FALSE, FALSE, sizeof(irq_entry));
261 event_viewer_data->SecondRequestIrqExit = g_array_new(FALSE, FALSE, sizeof(Irq));
262
263 event_viewer_data->SumArray = g_array_new(FALSE, FALSE, sizeof(SumId));
264
265
266 /*Create tha main window for the viewer */
267 event_viewer_data->ScrollWindow = gtk_scrolled_window_new (NULL, NULL);
268 gtk_widget_show (event_viewer_data->ScrollWindow);
269 gtk_scrolled_window_set_policy(
270 GTK_SCROLLED_WINDOW(event_viewer_data->ScrollWindow),
271 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC/*GTK_POLICY_NEVER*/);
272
273 /* Create a model for storing the data list */
274 event_viewer_data->ListStore = gtk_list_store_new (
275 N_COLUMNS, /* Total number of columns */
276 G_TYPE_INT, /* CPUID */
277 G_TYPE_INT, /* IRQ_ID */
278 G_TYPE_INT, /* Frequency */
279 G_TYPE_UINT64, /* Duration */
280 G_TYPE_INT, /* standard deviation */
281 G_TYPE_STRING, /* Max IRQ handler */
282 G_TYPE_STRING, /* Min IRQ handler */
283 G_TYPE_INT, /* Average period */
284 G_TYPE_INT, /* period standard deviation */
285 G_TYPE_INT /* frequency standard deviation */
286
287 );
288
289 event_viewer_data->TreeView = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->ListStore));
290
291 g_object_unref (G_OBJECT (event_viewer_data->ListStore));
292
293 renderer = gtk_cell_renderer_text_new ();
294 column = gtk_tree_view_column_new_with_attributes ("CPU ID",
295 renderer,
296 "text", CPUID_COLUMN,
297 NULL);
298 gtk_tree_view_column_set_alignment (column, 0.0);
299 gtk_tree_view_column_set_fixed_width (column, 45);
300 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
301
302
303 renderer = gtk_cell_renderer_text_new ();
304 column = gtk_tree_view_column_new_with_attributes ("IRQ ID",
305 renderer,
306 "text", IRQ_ID_COLUMN,
307 NULL);
308 gtk_tree_view_column_set_alignment (column, 0.0);
309 gtk_tree_view_column_set_fixed_width (column, 220);
310 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
311
312 renderer = gtk_cell_renderer_text_new ();
313 column = gtk_tree_view_column_new_with_attributes ("Frequency (Hz)",
314 renderer,
315 "text", FREQUENCY_COLUMN,
316 NULL);
317 gtk_tree_view_column_set_alignment (column, 1.0);
318 gtk_tree_view_column_set_fixed_width (column, 220);
319 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
320
321 renderer = gtk_cell_renderer_text_new ();
322 column = gtk_tree_view_column_new_with_attributes ("Total Duration (nsec)",
323 renderer,
324 "text", DURATION_COLUMN,
325 NULL);
326 gtk_tree_view_column_set_alignment (column, 0.0);
327 gtk_tree_view_column_set_fixed_width (column, 145);
328 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
329
330
331 renderer = gtk_cell_renderer_text_new ();
332 column = gtk_tree_view_column_new_with_attributes ("Duration standard deviation (nsec)",
333 renderer,
334 "text", DURATION_STANDARD_DEV_COLUMN,
335 NULL);
336 gtk_tree_view_column_set_alignment (column, 0.0);
337 gtk_tree_view_column_set_fixed_width (column, 200);
338 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
339
340 renderer = gtk_cell_renderer_text_new ();
341 column = gtk_tree_view_column_new_with_attributes ("Max IRQ handler duration (nsec) [time interval]",
342 renderer,
343 "text", MAX_IRQ_HANDLER_COLUMN,
344 NULL);
345 gtk_tree_view_column_set_alignment (column, 0.0);
346 gtk_tree_view_column_set_fixed_width (column, 250);
347 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
348
349 renderer = gtk_cell_renderer_text_new ();
350 column = gtk_tree_view_column_new_with_attributes ("Min IRQ handler duration (nsec) [time interval]",
351 renderer,
352 "text", MIN_IRQ_HANDLER_COLUMN,
353 NULL);
354 gtk_tree_view_column_set_alignment (column, 0.0);
355 gtk_tree_view_column_set_fixed_width (column, 250);
356 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
357
358 renderer = gtk_cell_renderer_text_new ();
359 column = gtk_tree_view_column_new_with_attributes (" Average period (nsec)",
360 renderer,
361 "text", AVERAGE_PERIOD,
362 NULL);
363 gtk_tree_view_column_set_alignment (column, 0.0);
364 gtk_tree_view_column_set_fixed_width (column, 200);
365 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
366
367 renderer = gtk_cell_renderer_text_new ();
368 column = gtk_tree_view_column_new_with_attributes ("Period standard deviation (nsec)",
369 renderer,
370 "text", PERIOD_STANDARD_DEV_COLUMN,
371 NULL);
372 gtk_tree_view_column_set_alignment (column, 0.0);
373 gtk_tree_view_column_set_fixed_width (column, 200);
374 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
375
376 renderer = gtk_cell_renderer_text_new ();
377 column = gtk_tree_view_column_new_with_attributes ("Frequency standard deviation (Hz)",
378 renderer,
379 "text", FREQUENCY_STANDARD_DEV_COLUMN,
380 NULL);
381 gtk_tree_view_column_set_alignment (column, 0.0);
382 gtk_tree_view_column_set_fixed_width (column, 200);
383 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
384
385
386 event_viewer_data->SelectionTree = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data->TreeView));
387 gtk_tree_selection_set_mode (event_viewer_data->SelectionTree, GTK_SELECTION_SINGLE);
388
389 gtk_container_add (GTK_CONTAINER (event_viewer_data->ScrollWindow), event_viewer_data->TreeView);
390
391 event_viewer_data->Hbox = gtk_hbox_new(0, 0);
392 gtk_box_pack_start(GTK_BOX(event_viewer_data->Hbox), event_viewer_data->ScrollWindow, TRUE, TRUE, 0);
393
394 gtk_widget_show(event_viewer_data->Hbox);
395 gtk_widget_show(event_viewer_data->TreeView);
396
397 interrupt_data_list = g_slist_append(interrupt_data_list, event_viewer_data);
398 /* Registration for time notification */
399 lttvwindow_register_time_window_notify(tab,
400 interrupt_update_time_window,
401 event_viewer_data);
402
403 g_object_set_data_full(G_OBJECT(event_viewer_data->Hbox),
404 "event_data",
405 event_viewer_data,
406 (GDestroyNotify) InterruptFree);
407
408 FirstRequest(event_viewer_data );
409 return event_viewer_data;
410}
411
412
413/**
414 *
415 * For each trace in the traceset, this function:
416 * - registers a callback function to each hook
417 * - calls lttv_trace_find_hook() registers a hook function to event_by_id_hooks
418 * - calls lttvwindow_events_request() to request data in a specific
419 * time interval to the main window
420 *
421 */
422static void FirstRequest(InterruptEventData *event_data )
423{
424 guint i, k, l, nb_trace;
425
426 LttvTraceHook *hook;
427
428 guint ret;
429
430 LttvTraceState *ts;
431
432 GArray *hooks;
433
434 EventsRequest *events_request;
435
436 LttvTraceHookByFacility *thf;
437
438 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
439
440
441 /* Get the traceset */
442 LttvTraceset *traceset = tsc->ts;
443
444 nb_trace = lttv_traceset_number(traceset);
445
446 /* There are many traces in a traceset. Iteration for each trace. */
447 for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++)
448 {
449 events_request = g_new(EventsRequest, 1);
450
451 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
452
453 hooks = g_array_set_size(hooks, 2);
454
455 event_data->hooks_trace_before = lttv_hooks_new();
456
457 /* Registers a hook function */
458 lttv_hooks_add(event_data->hooks_trace_before, trace_header, event_data, LTTV_PRIO_DEFAULT);
459
460 event_data->hooks_trace_after = lttv_hooks_new();
461
462 /* Registers a hook function */
463 lttv_hooks_add(event_data->hooks_trace_after, SecondRequest, event_data, LTTV_PRIO_DEFAULT);
464 /* Get a trace state */
465 ts = (LttvTraceState *)tsc->traces[i];
466 /* Create event_by_Id hooks */
467 event_data->event_by_id_hooks = lttv_hooks_by_id_new();
468
469 /*Register event_by_id_hooks with a callback function*/
470 ret = lttv_trace_find_hook(ts->parent.t,
471 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
472 LTT_FIELD_IRQ_ID, 0, 0,
473 FirstRequestIrqEntryCallback,
474 events_request,
475 &g_array_index(hooks, LttvTraceHook, 0));
476
477 ret = lttv_trace_find_hook(ts->parent.t,
478 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
479 LTT_FIELD_IRQ_ID, 0, 0,
480 FirstRequestIrqExitCallback,
481 events_request,
482 &g_array_index(hooks, LttvTraceHook, 1));
483
484 g_assert(!ret);
485 /*iterate through the facility list*/
486 for(k = 0 ; k < hooks->len; k++)
487 {
488 hook = &g_array_index(hooks, LttvTraceHook, k);
489 for(l=0; l<hook->fac_list->len; l++)
490 {
491 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
492 lttv_hooks_add(lttv_hooks_by_id_find(event_data->event_by_id_hooks, thf->id),
493 thf->h,
494 event_data,
495 LTTV_PRIO_DEFAULT);
496
497 }
498 }
499 /* Initalize the EventsRequest structure */
500 events_request->owner = event_data;
501 events_request->viewer_data = event_data;
502 events_request->servicing = FALSE;
503 events_request->start_time = event_data->time_window.start_time;
504 events_request->start_position = NULL;
505 events_request->stop_flag = FALSE;
506 events_request->end_time = event_data->time_window.end_time;
507 events_request->num_events = G_MAXUINT;
508 events_request->end_position = NULL;
509 events_request->trace = i;
510
511 events_request->hooks = hooks;
512
513 events_request->before_chunk_traceset = NULL;
514 events_request->before_chunk_trace = event_data->hooks_trace_before;
515 events_request->before_chunk_tracefile= NULL;
516 events_request->event = NULL;
517 events_request->event_by_id = event_data->event_by_id_hooks;
518 events_request->after_chunk_tracefile = NULL;
519 events_request->after_chunk_trace = NULL;
520 events_request->after_chunk_traceset = NULL;
521 events_request->before_request = NULL;
522 events_request->after_request = event_data->hooks_trace_after;
523
524 lttvwindow_events_request(event_data->tab, events_request);
525 }
526
527}
528
529/**
530 * This function is called whenever an irq_entry event occurs.
531 *
532 */
533static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data)
534{
535
536 LttTime event_time;
537 unsigned cpu_id;
538 irq_entry entry;
539 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
540 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
541 InterruptEventData *event_data = (InterruptEventData *)hook_data;
542 GArray* FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
543 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
544 event_time = ltt_event_time(e);
545 cpu_id = ltt_event_cpu_id(e);
546
547
548 entry.id =get_interrupt_id(e);
549 entry.cpu_id = cpu_id;
550 entry.event_time = event_time;
551 g_array_append_val (FirstRequestIrqEntry, entry);
552
553 return FALSE;
554}
555
556/**
557 * This function gets the id of the interrupt. The id is stored in a dynamic structure.
558 * Refer to the print.c file for how to extract data from a dynamic structure.
559 */
560static guint64 get_interrupt_id(LttEvent *e)
561{
562 guint i, num_fields;
563 LttEventType *event_type;
564 LttField *element;
565 LttField *field;
566 guint64 irq_id;
567 event_type = ltt_event_eventtype(e);
568 num_fields = ltt_eventtype_num_fields(event_type);
569 for(i = 0 ; i < num_fields-1 ; i++)
570 {
571 field = ltt_eventtype_field(event_type, i);
572 irq_id = ltt_event_get_long_unsigned(e,field);
573 }
574 return irq_id;
575
576}
577/**
578 * This function is called whenever an irq_exit event occurs.
579 *
580 */
581gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data)
582{
583 LttTime event_time;
584 unsigned cpu_id;
585 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
586 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
587 InterruptEventData *event_data = (InterruptEventData *)hook_data;
588 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
589 LttEventType *type = ltt_event_eventtype(e);
590 event_time = ltt_event_time(e);
591 cpu_id = ltt_event_cpu_id(e);
592
593 CalculateData( event_time, cpu_id, event_data);
594
595 return FALSE;
596}
597
598/**
599 * This function calculates the duration of an interrupt.
600 *
601 */
602static void CalculateData(LttTime time_exit, guint cpu_id,InterruptEventData *event_data)
603{
604
605 gint i, irq_id;
606 irq_entry *element;
607 LttTime duration;
608 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
609 GArray *FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
610 for(i = 0; i < FirstRequestIrqEntry->len; i++)
611 {
612 element = &g_array_index(FirstRequestIrqEntry,irq_entry,i);
613 if(element->cpu_id == cpu_id)
614 {
615 CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(element,time_exit, FirstRequestIrqExit);
616 g_array_remove_index(FirstRequestIrqEntry, i);
617 break;
618 }
619 }
620}
621
622
623/**
624 * This function calculates the total duration of an interrupt and the longest & shortest Irq handlers.
625 *
626 */
627static void CalculateTotalDurationAndMaxIrqDurationAndMinIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit)
628{
629 Irq irq;
630 Irq *element;
631 guint i;
632 LttTime duration;
633 gboolean notFound = FALSE;
634 memset ((void*)&irq, 0,sizeof(Irq));
635
636 /*first time*/
637 if(FirstRequestIrqExit->len == NO_ITEMS)
638 {
639 irq.cpu_id = e->cpu_id;
640 irq.id = e->id;
641 irq.TotalNumberOfInterrupts++;
642 irq.total_duration = ltt_time_sub(time_exit, e->event_time);
643
644 irq.max_irq_handler.start_time = e->event_time;
645 irq.max_irq_handler.end_time = time_exit;
646 irq.max_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
647
648 irq.min_irq_handler.start_time = e->event_time;
649 irq.min_irq_handler.end_time = time_exit;
650 irq.min_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
651
652 g_array_append_val (FirstRequestIrqExit, irq);
653 }
654 else
655 {
656 for(i = 0; i < FirstRequestIrqExit->len; i++)
657 {
658 element = &g_array_index(FirstRequestIrqExit,Irq,i);
659 if(element->id == e->id)
660 {
661 notFound = TRUE;
662 duration = ltt_time_sub(time_exit, e->event_time);
663 element->total_duration = ltt_time_add(element->total_duration, duration);
664 element->TotalNumberOfInterrupts++;
665 // Max irq handler
666 if(ltt_time_compare(duration,element->max_irq_handler.duration) > 0)
667 {
668 element->max_irq_handler.duration = duration;
669 element->max_irq_handler.start_time = e->event_time;
670 element->max_irq_handler.end_time = time_exit;
671 }
672 // Min irq handler
673 if(ltt_time_compare(duration,element->min_irq_handler.duration) < 0)
674 {
675 element->min_irq_handler.duration = duration;
676 element->min_irq_handler.start_time = e->event_time;
677 element->min_irq_handler.end_time = time_exit;
678 }
679 }
680 }
681 if(!notFound)
682 {
683 irq.cpu_id = e->cpu_id;
684 irq.id = e->id;
685 irq.TotalNumberOfInterrupts++;
686 irq.total_duration = ltt_time_sub(time_exit, e->event_time);
687 // Max irq handler
688 irq.max_irq_handler.start_time = e->event_time;
689 irq.max_irq_handler.end_time = time_exit;
690 irq.max_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
691 // Min irq handler
692 irq.min_irq_handler.start_time = e->event_time;
693 irq.min_irq_handler.end_time = time_exit;
694 irq.min_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
695
696 g_array_append_val (FirstRequestIrqExit, irq);
697 }
698 }
699}
700
701/**
702 * This function passes the second EventsRequest to LTTV
703 *
704 */
705static gboolean SecondRequest(void *hook_data, void *call_data)
706{
707
708 guint i, k, l, nb_trace;
709
710 LttvTraceHook *hook;
711
712 guint ret;
713
714 LttvTraceState *ts;
715
716 GArray *hooks;
717
718 EventsRequest *events_request;
719
720 LttvTraceHookByFacility *thf;
721
722 InterruptEventData *event_data = (InterruptEventData *)hook_data;
723
724 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
725
726 CalculateAverageDurationForEachIrqId(event_data);
727
728 /* Get the traceset */
729 LttvTraceset *traceset = tsc->ts;
730
731 nb_trace = lttv_traceset_number(traceset);
732
733 /* There are many traces in a traceset. Iteration for each trace. */
734 for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++)
735 {
736 events_request = g_new(EventsRequest, 1);
737
738 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
739
740 hooks = g_array_set_size(hooks, 2);
741
742 event_data->hooks_trace_after = lttv_hooks_new();
743
744 /* Registers a hook function */
745 lttv_hooks_add(event_data->hooks_trace_after, DisplayViewer, event_data, LTTV_PRIO_DEFAULT);
746
747 /* Get a trace state */
748 ts = (LttvTraceState *)tsc->traces[i];
749 /* Create event_by_Id hooks */
750 event_data->event_by_id_hooks = lttv_hooks_by_id_new();
751
752 /*Register event_by_id_hooks with a callback function*/
753 ret = lttv_trace_find_hook(ts->parent.t,
754 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
755 LTT_FIELD_IRQ_ID, 0, 0,
756 SecondRequestIrqEntryCallback,
757 events_request,
758 &g_array_index(hooks, LttvTraceHook, 0));
759
760 ret = lttv_trace_find_hook(ts->parent.t,
761 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
762 LTT_FIELD_IRQ_ID, 0, 0,
763 SecondRequestIrqExitCallback,
764 events_request,
765 &g_array_index(hooks, LttvTraceHook, 1));
766
767 g_assert(!ret);
768
769 /* iterate through the facility list */
770 for(k = 0 ; k < hooks->len; k++)
771 {
772 hook = &g_array_index(hooks, LttvTraceHook, k);
773 for(l=0; l<hook->fac_list->len; l++)
774 {
775 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
776 lttv_hooks_add(lttv_hooks_by_id_find(event_data->event_by_id_hooks, thf->id),
777 thf->h,
778 event_data,
779 LTTV_PRIO_DEFAULT);
780
781 }
782 }
783 /* Initalize the EventsRequest structure */
784 events_request->owner = event_data;
785 events_request->viewer_data = event_data;
786 events_request->servicing = FALSE;
787 events_request->start_time = event_data->time_window.start_time;
788 events_request->start_position = NULL;
789 events_request->stop_flag = FALSE;
790 events_request->end_time = event_data->time_window.end_time;
791 events_request->num_events = G_MAXUINT;
792 events_request->end_position = NULL;
793 events_request->trace = i;
794
795 events_request->hooks = hooks;
796
797 events_request->before_chunk_traceset = NULL;
798 events_request->before_chunk_trace = NULL;
799 events_request->before_chunk_tracefile= NULL;
800 events_request->event = NULL;
801 events_request->event_by_id = event_data->event_by_id_hooks;
802 events_request->after_chunk_tracefile = NULL;
803 events_request->after_chunk_trace = NULL;
804 events_request->after_chunk_traceset = NULL;
805 events_request->before_request = NULL;
806 events_request->after_request = event_data->hooks_trace_after;
807
808 lttvwindow_events_request(event_data->tab, events_request);
809 }
810 return FALSE;
811}
812
813/**
814 * This function calculates the average duration for each Irq Id
815 *
816 */
817static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data)
818{
819 guint64 real_data;
820 Irq *element;
821 gint i;
822 GArray* FirstRequestIrqExit = event_data->FirstRequestIrqExit;
823 for(i = 0; i < FirstRequestIrqExit->len; i++)
824 {
825 element = &g_array_index(FirstRequestIrqExit,Irq,i);
826 real_data = element->total_duration.tv_sec;
827 real_data *= NANOSECONDS_PER_SECOND;
828 real_data += element->total_duration.tv_nsec;
829 if(element->TotalNumberOfInterrupts != 0)
830 element->average_duration = real_data / element->TotalNumberOfInterrupts;
831 else
832 element->average_duration = 0;
833 }
834
835}
836
837/**
838 * This function is called whenever an irq_entry event occurs. Use in the second request
839 *
840 */
841static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data)
842{
843
844 LttTime event_time;
845 unsigned cpu_id;
846 irq_entry entry;
847 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
848 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
849 InterruptEventData *event_data = (InterruptEventData *)hook_data;
850 GArray* SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
851 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
852 event_time = ltt_event_time(e);
853 cpu_id = ltt_event_cpu_id(e);
854
855
856 entry.id =get_interrupt_id(e);
857 entry.cpu_id = cpu_id;
858 entry.event_time = event_time;
859 g_array_append_val (SecondRequestIrqEntry, entry);
860
861 return FALSE;
862}
863
864/**
865 * This function is called whenever an irq_exit event occurs in the second request.
866 *
867 */
868static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data)
869{
870
871 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
872 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
873 InterruptEventData *event_data = (InterruptEventData *)hook_data;
874 LttEvent *event = ltt_tracefile_get_event(tfc->tf);
875
876 CalculateXi(event, event_data);
877 return FALSE;
878}
879
880
881/**
882 * This function is called whenever an irq_exit event occurs in the second request.
883 *
884 */
885static void CalculateXi(LttEvent *event_irq_exit, InterruptEventData *event_data)
886{
887 gint i, irq_id;
888 irq_entry *element;
889 LttTime Xi;
890 LttTime exit_time;
891 unsigned cpu_id;
892
893 GArray *SecondRequestIrqExit = event_data->SecondRequestIrqExit;
894 GArray *SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
895 cpu_id = ltt_event_cpu_id(event_irq_exit);
896 for(i = 0; i < SecondRequestIrqEntry->len; i++)
897 {
898 element = &g_array_index(SecondRequestIrqEntry,irq_entry,i);
899 if(element->cpu_id == cpu_id)
900 {
901
902 /* time calculation */
903 exit_time = ltt_event_time(event_irq_exit);
904 Xi = ltt_time_sub(exit_time, element->event_time);
905 irq_id = element->id;
906
907 SumItems(irq_id, Xi,event_data);
908 g_array_remove_index(SecondRequestIrqEntry, i);
909 break;
910 }
911 }
912}
913
914
915/**
916 * This function computes the Sum ((xi -Xa)^2) and store the result in SumArray
917 *
918 */
919static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data)
920{
921 gint i;
922 guint Xi_in_ns;
923
924 gint duration_inner_part;
925 guint64 period_inner_part;
926 guint64 frequency_inner_part;
927
928 Irq *average;
929 SumId *sumItem;
930 SumId sum;
931 int FrequencyHZ = 0;
932 gboolean notFound = FALSE;
933 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
934 GArray *SumArray = event_data->SumArray;
935 Xi_in_ns = Xi.tv_sec;
936 Xi_in_ns *= NANOSECONDS_PER_SECOND;
937 Xi_in_ns += Xi.tv_nsec;
938
939 for(i = 0; i < FirstRequestIrqExit->len; i++)
940 {
941 average = &g_array_index(FirstRequestIrqExit,Irq,i);
942 if(irq_id == average->id)
943 {
944 duration_inner_part = Xi_in_ns - average->average_duration;
945 FrequencyHZ = FrequencyInHZ(average->TotalNumberOfInterrupts, event_data->time_window);
946 sum.irqId = irq_id;
947 // compute (xi -Xa)^2 of the duration Standard deviation
948 sum.TotalNumberOfInterrupts = average->TotalNumberOfInterrupts;
949 sum.sumOfDurations = pow (duration_inner_part , 2);
950
951 // compute (xi -Xa)^2 of the period Standard deviation
952 period_inner_part = CalculatePeriodInnerPart(Xi_in_ns, FrequencyHZ);
953
954 // compute (xi -Xa)^2 of the frequency Standard deviation
955 frequency_inner_part = CalculateFrequencyInnerPart(Xi_in_ns, FrequencyHZ);
956
957 sum.sumOfPeriods = period_inner_part;
958
959 sum.sumOfFrequencies = frequency_inner_part;
960
961 if(event_data->SumArray->len == NO_ITEMS)
962 {
963 g_array_append_val (SumArray, sum);
964 }
965 else
966 {
967 for(i = 0; i < SumArray->len; i++)
968 {
969 sumItem = &g_array_index(SumArray, SumId, i);
970 if(sumItem->irqId == irq_id)
971 {
972 notFound = TRUE;
973 sumItem->sumOfDurations += sum.sumOfDurations;
974 sumItem->sumOfPeriods += sum.sumOfPeriods;
975 sumItem->sumOfFrequencies += sum.sumOfFrequencies;
976 }
977 }
978 if(!notFound)
979 {
980 g_array_append_val (SumArray, sum);
981 }
982
983 }
984
985 }
986 }
987}
988
989/**
990 * This function computes the inner part of the period standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
991 * The inner part is: (xi -Xa)^2
992 */
993static guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ)
994{
995
996 double periodInSec; /*period in sec*/
997 int periodInNSec;
998 gint difference;
999 guint64 result;
1000 periodInSec = (double)1/FrequencyHZ;
1001 periodInSec *= NANOSECONDS_PER_SECOND;
1002 periodInNSec = (int)periodInSec;
1003
1004 difference = Xi - periodInNSec;
1005 result = pow (difference , 2);
1006 return result;
1007}
1008
1009/**
1010 * This function computes the inner part of the frequency standard deviation = sqrt(1/N Sum ((xi -Xa)^2))
1011 * The inner part is: (xi -Xa)^2
1012 */
1013static guint64 CalculateFrequencyInnerPart(guint Xi_in_ns, guint FrequencyHZ)
1014{
1015 guint64 result;
1016 gint difference;
1017
1018 difference = Xi_in_ns - FrequencyHZ;
1019 result = pow (difference , 2);
1020 return result;
1021}
1022/**
1023 * This function displays the result on the viewer
1024 *
1025 */
1026static gboolean DisplayViewer(void *hook_data, void *call_data)
1027{
1028
1029 guint average;
1030 gint i;
1031 Irq element;
1032 LttTime average_duration;
1033 GtkTreeIter iter;
1034 guint64 real_data;
1035 guint maxIRQduration;
1036 guint minIRQduration;
1037 double periodInSec;
1038 int periodInNsec;
1039 char maxIrqHandler[80];
1040 char minIrqHandler[80];
1041 InterruptEventData *event_data = (InterruptEventData *)hook_data;
1042 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
1043 int FrequencyHZ = 0;
1044 periodInSec = 0;
1045 gtk_list_store_clear(event_data->ListStore);
1046 for(i = 0; i < FirstRequestIrqExit->len; i++)
1047 {
1048 element = g_array_index(FirstRequestIrqExit,Irq,i);
1049 real_data = element.total_duration.tv_sec;
1050 real_data *= NANOSECONDS_PER_SECOND;
1051 real_data += element.total_duration.tv_nsec;
1052
1053
1054 maxIRQduration = element.max_irq_handler.duration.tv_sec;
1055 maxIRQduration *= NANOSECONDS_PER_SECOND;
1056 maxIRQduration += element.max_irq_handler.duration.tv_nsec;
1057
1058 sprintf(maxIrqHandler, "%d [%d.%d - %d.%d]",maxIRQduration, element.max_irq_handler.start_time.tv_sec, \
1059 element.max_irq_handler.start_time.tv_nsec, element.max_irq_handler.end_time.tv_sec, \
1060 element.max_irq_handler.end_time.tv_nsec) ;
1061
1062 minIRQduration = element.min_irq_handler.duration.tv_sec;
1063 minIRQduration *= NANOSECONDS_PER_SECOND;
1064 minIRQduration += element.min_irq_handler.duration.tv_nsec;
1065 sprintf(minIrqHandler, "%d [%d.%d - %d.%d]",minIRQduration, element.min_irq_handler.start_time.tv_sec, \
1066 element.min_irq_handler.start_time.tv_nsec, element.min_irq_handler.end_time.tv_sec, \
1067 element.min_irq_handler.end_time.tv_nsec) ;
1068
1069
1070 FrequencyHZ = FrequencyInHZ(element.TotalNumberOfInterrupts,event_data->time_window);
1071
1072 if(FrequencyHZ != 0)
1073 {
1074 periodInSec = (double)1/FrequencyHZ;
1075 periodInSec *= NANOSECONDS_PER_SECOND;
1076 periodInNsec = (int)periodInSec;
1077
1078 }
1079
1080 gtk_list_store_append (event_data->ListStore, &iter);
1081 gtk_list_store_set (event_data->ListStore, &iter,
1082 CPUID_COLUMN, element.cpu_id,
1083 IRQ_ID_COLUMN, element.id,
1084 FREQUENCY_COLUMN, FrequencyHZ,
1085 DURATION_COLUMN, real_data,
1086 DURATION_STANDARD_DEV_COLUMN, CalculateDurationStandardDeviation(element.id, event_data),
1087 MAX_IRQ_HANDLER_COLUMN, maxIrqHandler,
1088 MIN_IRQ_HANDLER_COLUMN, minIrqHandler,
1089 AVERAGE_PERIOD , periodInNsec,
1090 PERIOD_STANDARD_DEV_COLUMN, CalculatePeriodStandardDeviation(element.id, event_data),
1091 FREQUENCY_STANDARD_DEV_COLUMN, CalculateFrequencyStandardDeviation(element.id, event_data),
1092 -1);
1093 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));
1094
1095
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.025768 seconds and 4 git commands to generate.