1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2005 Peter Ho
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;
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.
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,
19 /******************************************************************
20 CPUID | IRQID | Frequency |
22 The standard deviation (sigma) is based on:
23 http://en.wikipedia.org/wiki/Standard_deviation
25 sigma = sqrt(1/N Sum ((xi -Xa)^2))
27 To compute the standard deviation, we pass two EventRequests to LTTV. In
28 the first EventRequest, we compute the average duration (Xa) of and the
29 frequency (N) each IrqID. We store the information in an array called
32 In the second EventRequest, we compute the Sum ((xi -Xa)^2)
38 *******************************************************************/
51 #include <ltt/event.h>
53 #include <ltt/trace.h>
54 #include <ltt/facility.h>
55 #include <lttv/module.h>
56 #include <lttv/hook.h>
57 #include <lttv/tracecontext.h>
58 #include <lttv/state.h>
59 #include <lttv/filter.h>
60 #include <lttvwindow/lttvwindow.h>
63 #include "hInterruptsInsert.xpm"
65 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
66 #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
73 LttTime total_duration
;
74 guint average_duration
;
89 guint64 sumOfDurations
;
98 /** Array containing instanced objects. Used when module is unloaded */
99 static GSList
*interrupt_data_list
= NULL
;
102 #define TRACE_NUMBER 0
104 typedef struct _InterruptEventData
{
106 /*Graphical Widgets */
107 GtkWidget
* ScrollWindow
;
108 GtkListStore
*ListStore
;
111 GtkTreeSelection
*SelectionTree
;
113 Tab
* tab
; /* tab that contains this plug-in*/
114 LttvHooks
* event_hooks
;
115 LttvHooks
* hooks_trace_after
;
116 LttvHooks
* hooks_trace_before
;
117 TimeWindow time_window
;
118 LttvHooksById
* event_by_id_hooks
;
119 GArray
*FirstRequestIrqExit
;
120 GArray
*FirstRequestIrqEntry
;
121 GArray
*SecondRequestIrqEntry
;
122 GArray
*SecondRequestIrqExit
;
125 } InterruptEventData
;
128 /* Function prototypes */
130 static gboolean
interrupt_update_time_window(void * hook_data
, void * call_data
);
131 static GtkWidget
*interrupts(Tab
*tab
);
132 static InterruptEventData
*system_info(Tab
*tab
);
133 void interrupt_destructor(InterruptEventData
*event_viewer_data
);
134 static void FirstRequest(InterruptEventData
*event_data
);
135 static guint64
get_interrupt_id(LttEvent
*e
);
136 static gboolean
trace_header(void *hook_data
, void *call_data
);
137 static gboolean
DisplayViewer (void *hook_data
, void *call_data
);
138 static void calcul_duration(LttTime time_exit
, guint cpu_id
, InterruptEventData
*event_data
);
139 static void sum_interrupt_data(irq_entry
*e
, LttTime time_exit
, GArray
*FirstRequestIrqExit
);
140 static gboolean
FirstRequestIrqEntryCallback(void *hook_data
, void *call_data
);
141 static gboolean
FirstRequestIrqExitCallback(void *hook_data
, void *call_data
);
142 static gboolean
SecondRequest(void *hook_data
, void *call_data
);
143 static void CalculateAverageDurationForEachIrqId(InterruptEventData
*event_data
);
144 static gboolean
SecondRequestIrqEntryCallback(void *hook_data
, void *call_data
);
145 static gboolean
SecondRequestIrqExitCallback(void *hook_data
, void *call_data
);
146 static void CalculateXi(LttEvent
*event
, InterruptEventData
*event_data
);
147 static void SumItems(gint irq_id
, LttTime Xi
, InterruptEventData
*event_data
);
148 static int CalculateStandardDeviation(gint id
, InterruptEventData
*event_data
);
149 static void CalculateMaxIRQHandler();
150 /* Enumeration of the columns */
156 DURATION_STANDARD_DEV_COLUMN
,
166 * This is the entry point of the viewer.
170 g_info("interrupts: init()");
171 lttvwindow_register_constructor("interrupts",
173 "Insert Interrupts View",
174 hInterruptsInsert_xpm
,
175 "Insert Interrupts View",
185 static GtkWidget
*interrupts(Tab
* tab
)
188 InterruptEventData
* event_data
= system_info(tab
) ;
190 return event_data
->Hbox
;
196 * This function initializes the Event Viewer functionnality through the
199 InterruptEventData
*system_info(Tab
*tab
)
203 GtkTreeViewColumn
*column
;
204 GtkCellRenderer
*renderer
;
205 InterruptEventData
* event_viewer_data
= g_new(InterruptEventData
,1) ;
207 event_viewer_data
->tab
= tab
;
209 /*Get the current time frame from the main window */
210 event_viewer_data
->time_window
= lttvwindow_get_time_window(tab
);
212 event_viewer_data
->FirstRequestIrqExit
= g_array_new(FALSE
, FALSE
, sizeof(Irq
));
213 event_viewer_data
->FirstRequestIrqEntry
= g_array_new(FALSE
, FALSE
, sizeof(irq_entry
));
215 event_viewer_data
->SecondRequestIrqEntry
= g_array_new(FALSE
, FALSE
, sizeof(irq_entry
));
216 event_viewer_data
->SecondRequestIrqExit
= g_array_new(FALSE
, FALSE
, sizeof(Irq
));
218 event_viewer_data
->SumArray
= g_array_new(FALSE
, FALSE
, sizeof(SumId
));
221 /*Create tha main window for the viewer */
222 event_viewer_data
->ScrollWindow
= gtk_scrolled_window_new (NULL
, NULL
);
223 gtk_widget_show (event_viewer_data
->ScrollWindow
);
224 gtk_scrolled_window_set_policy(
225 GTK_SCROLLED_WINDOW(event_viewer_data
->ScrollWindow
),
226 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
/*GTK_POLICY_NEVER*/);
228 /* Create a model for storing the data list */
229 event_viewer_data
->ListStore
= gtk_list_store_new (
230 N_COLUMNS
, /* Total number of columns */
231 G_TYPE_INT
, /* CPUID */
232 G_TYPE_INT
, /* IRQ_ID */
233 G_TYPE_INT
, /* Frequency */
234 G_TYPE_UINT64
, /* Duration */
235 G_TYPE_INT
/* standard deviation */
238 event_viewer_data
->TreeView
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data
->ListStore
));
240 g_object_unref (G_OBJECT (event_viewer_data
->ListStore
));
242 renderer
= gtk_cell_renderer_text_new ();
243 column
= gtk_tree_view_column_new_with_attributes ("CPUID",
245 "text", CPUID_COLUMN
,
247 gtk_tree_view_column_set_alignment (column
, 0.0);
248 gtk_tree_view_column_set_fixed_width (column
, 45);
249 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->TreeView
), column
);
252 renderer
= gtk_cell_renderer_text_new ();
253 column
= gtk_tree_view_column_new_with_attributes ("IrqId",
255 "text", IRQ_ID_COLUMN
,
257 gtk_tree_view_column_set_alignment (column
, 0.0);
258 gtk_tree_view_column_set_fixed_width (column
, 220);
259 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->TreeView
), column
);
261 renderer
= gtk_cell_renderer_text_new ();
262 column
= gtk_tree_view_column_new_with_attributes ("Frequency",
264 "text", FREQUENCY_COLUMN
,
266 gtk_tree_view_column_set_alignment (column
, 1.0);
267 gtk_tree_view_column_set_fixed_width (column
, 220);
268 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->TreeView
), column
);
270 renderer
= gtk_cell_renderer_text_new ();
271 column
= gtk_tree_view_column_new_with_attributes ("Duration (nsec)",
273 "text", DURATION_COLUMN
,
275 gtk_tree_view_column_set_alignment (column
, 0.0);
276 gtk_tree_view_column_set_fixed_width (column
, 145);
277 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->TreeView
), column
);
280 renderer
= gtk_cell_renderer_text_new ();
281 column
= gtk_tree_view_column_new_with_attributes ("Duration standard deviation (nsec)",
283 "text", DURATION_STANDARD_DEV_COLUMN
,
285 gtk_tree_view_column_set_alignment (column
, 0.0);
286 gtk_tree_view_column_set_fixed_width (column
, 250);
287 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->TreeView
), column
);
291 event_viewer_data
->SelectionTree
= gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data
->TreeView
));
292 gtk_tree_selection_set_mode (event_viewer_data
->SelectionTree
, GTK_SELECTION_SINGLE
);
294 gtk_container_add (GTK_CONTAINER (event_viewer_data
->ScrollWindow
), event_viewer_data
->TreeView
);
296 event_viewer_data
->Hbox
= gtk_hbox_new(0, 0);
297 gtk_box_pack_start(GTK_BOX(event_viewer_data
->Hbox
), event_viewer_data
->ScrollWindow
, TRUE
, TRUE
, 0);
299 gtk_widget_show(event_viewer_data
->Hbox
);
300 gtk_widget_show(event_viewer_data
->TreeView
);
302 interrupt_data_list
= g_slist_append(interrupt_data_list
, event_viewer_data
);
303 /* Registration for time notification */
304 lttvwindow_register_time_window_notify(tab
,
305 interrupt_update_time_window
,
309 FirstRequest(event_viewer_data
);
310 return event_viewer_data
;
315 * For each trace in the traceset, this function:
316 * - registers a callback function to each hook
317 * - calls lttv_trace_find_hook() registers a hook function to event_by_id_hooks
318 * - calls lttvwindow_events_request() to request data in a specific
319 * time interval to the main window
322 static void FirstRequest(InterruptEventData
*event_data
)
324 guint i
, k
, l
, nb_trace
;
334 EventsRequest
*events_request
;
336 LttvTraceHookByFacility
*thf
;
338 LttvTracesetContext
*tsc
= lttvwindow_get_traceset_context(event_data
->tab
);
341 /* Get the traceset */
342 LttvTraceset
*traceset
= tsc
->ts
;
344 nb_trace
= lttv_traceset_number(traceset
);
346 /* There are many traces in a traceset. Iteration for each trace. */
347 for(i
= 0; i
<MIN(TRACE_NUMBER
+1, nb_trace
);i
++)
349 events_request
= g_new(EventsRequest
, 1);
351 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
353 hooks
= g_array_set_size(hooks
, 2);
355 event_data
->hooks_trace_before
= lttv_hooks_new();
357 /* Registers a hook function */
358 lttv_hooks_add(event_data
->hooks_trace_before
, trace_header
, event_data
, LTTV_PRIO_DEFAULT
);
360 event_data
->hooks_trace_after
= lttv_hooks_new();
362 /* Registers a hook function */
363 lttv_hooks_add(event_data
->hooks_trace_after
, SecondRequest
, event_data
, LTTV_PRIO_DEFAULT
);
364 /* Get a trace state */
365 ts
= (LttvTraceState
*)tsc
->traces
[i
];
366 /* Create event_by_Id hooks */
367 event_data
->event_by_id_hooks
= lttv_hooks_by_id_new();
369 /*Register event_by_id_hooks with a callback function*/
370 ret
= lttv_trace_find_hook(ts
->parent
.t
,
371 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
372 LTT_FIELD_IRQ_ID
, 0, 0,
373 FirstRequestIrqEntryCallback
,
375 &g_array_index(hooks
, LttvTraceHook
, 0));
377 ret
= lttv_trace_find_hook(ts
->parent
.t
,
378 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
379 LTT_FIELD_IRQ_ID
, 0, 0,
380 FirstRequestIrqExitCallback
,
382 &g_array_index(hooks
, LttvTraceHook
, 1));
385 /*iterate through the facility list*/
386 for(k
= 0 ; k
< hooks
->len
; k
++)
388 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
389 for(l
=0; l
<hook
->fac_list
->len
; l
++)
391 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
392 lttv_hooks_add(lttv_hooks_by_id_find(event_data
->event_by_id_hooks
, thf
->id
),
399 /* Initalize the EventsRequest structure */
400 events_request
->owner
= event_data
;
401 events_request
->viewer_data
= event_data
;
402 events_request
->servicing
= FALSE
;
403 events_request
->start_time
= event_data
->time_window
.start_time
;
404 events_request
->start_position
= NULL
;
405 events_request
->stop_flag
= FALSE
;
406 events_request
->end_time
= event_data
->time_window
.end_time
;
407 events_request
->num_events
= G_MAXUINT
;
408 events_request
->end_position
= NULL
;
409 events_request
->trace
= i
;
411 events_request
->hooks
= hooks
;
413 events_request
->before_chunk_traceset
= NULL
;
414 events_request
->before_chunk_trace
= event_data
->hooks_trace_before
;
415 events_request
->before_chunk_tracefile
= NULL
;
416 events_request
->event
= NULL
;
417 events_request
->event_by_id
= event_data
->event_by_id_hooks
;
418 events_request
->after_chunk_tracefile
= NULL
;
419 events_request
->after_chunk_trace
= NULL
;
420 events_request
->after_chunk_traceset
= NULL
;
421 events_request
->before_request
= NULL
;
422 events_request
->after_request
= event_data
->hooks_trace_after
;
424 lttvwindow_events_request(event_data
->tab
, events_request
);
430 * This function is called whenever an irq_entry event occurs.
433 static gboolean
FirstRequestIrqEntryCallback(void *hook_data
, void *call_data
)
439 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
440 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
441 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
442 GArray
* FirstRequestIrqEntry
= event_data
->FirstRequestIrqEntry
;
443 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
444 event_time
= ltt_event_time(e
);
445 cpu_id
= ltt_event_cpu_id(e
);
448 entry
.id
=get_interrupt_id(e
);
449 entry
.cpu_id
= cpu_id
;
450 entry
.event_time
= event_time
;
451 g_array_append_val (FirstRequestIrqEntry
, entry
);
457 * This function gets the id of the interrupt. The id is stored in a dynamic structure.
458 * Refer to the print.c file for howto extract data from a dynamic structure.
460 static guint64
get_interrupt_id(LttEvent
*e
)
463 LttEventType
*event_type
;
467 event_type
= ltt_event_eventtype(e
);
468 num_fields
= ltt_eventtype_num_fields(event_type
);
469 for(i
= 0 ; i
< num_fields
-1 ; i
++)
471 field
= ltt_eventtype_field(event_type
, i
);
472 irq_id
= ltt_event_get_long_unsigned(e
,field
);
478 * This function is called whenever an irq_exit event occurs.
481 gboolean
FirstRequestIrqExitCallback(void *hook_data
, void *call_data
)
485 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
486 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
487 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
488 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
489 LttEventType
*type
= ltt_event_eventtype(e
);
490 event_time
= ltt_event_time(e
);
491 cpu_id
= ltt_event_cpu_id(e
);
493 calcul_duration( event_time
, cpu_id
, event_data
);
494 CalculateMaxIRQHandler();
499 * This function calculates the duration of an interrupt.
502 static void calcul_duration(LttTime time_exit
, guint cpu_id
,InterruptEventData
*event_data
)
508 GArray
*FirstRequestIrqExit
= event_data
->FirstRequestIrqExit
;
509 GArray
*FirstRequestIrqEntry
= event_data
->FirstRequestIrqEntry
;
510 for(i
= 0; i
< FirstRequestIrqEntry
->len
; i
++)
512 element
= &g_array_index(FirstRequestIrqEntry
,irq_entry
,i
);
513 if(element
->cpu_id
== cpu_id
)
515 sum_interrupt_data(element
,time_exit
, FirstRequestIrqExit
);
516 g_array_remove_index(FirstRequestIrqEntry
, i
);
522 static void CalculateMaxIRQHandler()
528 * This function calculates the total duration of an interrupt.
531 static void sum_interrupt_data(irq_entry
*e
, LttTime time_exit
, GArray
*FirstRequestIrqExit
){
536 gboolean notFound
= FALSE
;
537 memset ((void*)&irq
, 0,sizeof(Irq
));
540 if(FirstRequestIrqExit
->len
== NO_ITEMS
)
542 irq
.cpu_id
= e
->cpu_id
;
545 irq
.total_duration
= ltt_time_sub(time_exit
, e
->event_time
);
546 g_array_append_val (FirstRequestIrqExit
, irq
);
550 for(i
= 0; i
< FirstRequestIrqExit
->len
; i
++)
552 element
= &g_array_index(FirstRequestIrqExit
,Irq
,i
);
553 if(element
->id
== e
->id
)
556 duration
= ltt_time_sub(time_exit
, e
->event_time
);
557 element
->total_duration
= ltt_time_add(element
->total_duration
, duration
);
558 element
->frequency
++;
563 irq
.cpu_id
= e
->cpu_id
;
566 irq
.total_duration
= ltt_time_sub(time_exit
, e
->event_time
);
567 g_array_append_val (FirstRequestIrqExit
, irq
);
572 static gboolean
SecondRequest(void *hook_data
, void *call_data
)
575 guint i
, k
, l
, nb_trace
;
585 EventsRequest
*events_request
;
587 LttvTraceHookByFacility
*thf
;
589 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
591 LttvTracesetContext
*tsc
= lttvwindow_get_traceset_context(event_data
->tab
);
593 CalculateAverageDurationForEachIrqId(event_data
);
595 /* Get the traceset */
596 LttvTraceset
*traceset
= tsc
->ts
;
598 nb_trace
= lttv_traceset_number(traceset
);
600 /* There are many traces in a traceset. Iteration for each trace. */
601 for(i
= 0; i
<MIN(TRACE_NUMBER
+1, nb_trace
);i
++)
603 events_request
= g_new(EventsRequest
, 1);
605 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
607 hooks
= g_array_set_size(hooks
, 2);
609 event_data
->hooks_trace_after
= lttv_hooks_new();
611 /* Registers a hook function */
612 lttv_hooks_add(event_data
->hooks_trace_after
, DisplayViewer
, event_data
, LTTV_PRIO_DEFAULT
);
614 /* Get a trace state */
615 ts
= (LttvTraceState
*)tsc
->traces
[i
];
616 /* Create event_by_Id hooks */
617 event_data
->event_by_id_hooks
= lttv_hooks_by_id_new();
619 /*Register event_by_id_hooks with a callback function*/
620 ret
= lttv_trace_find_hook(ts
->parent
.t
,
621 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
622 LTT_FIELD_IRQ_ID
, 0, 0,
623 SecondRequestIrqEntryCallback
,
625 &g_array_index(hooks
, LttvTraceHook
, 0));
627 ret
= lttv_trace_find_hook(ts
->parent
.t
,
628 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
629 LTT_FIELD_IRQ_ID
, 0, 0,
630 SecondRequestIrqExitCallback
,
632 &g_array_index(hooks
, LttvTraceHook
, 1));
635 /*iterate through the facility list*/
636 for(k
= 0 ; k
< hooks
->len
; k
++)
638 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
639 for(l
=0; l
<hook
->fac_list
->len
; l
++)
641 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
642 lttv_hooks_add(lttv_hooks_by_id_find(event_data
->event_by_id_hooks
, thf
->id
),
649 /* Initalize the EventsRequest structure */
650 events_request
->owner
= event_data
;
651 events_request
->viewer_data
= event_data
;
652 events_request
->servicing
= FALSE
;
653 events_request
->start_time
= event_data
->time_window
.start_time
;
654 events_request
->start_position
= NULL
;
655 events_request
->stop_flag
= FALSE
;
656 events_request
->end_time
= event_data
->time_window
.end_time
;
657 events_request
->num_events
= G_MAXUINT
;
658 events_request
->end_position
= NULL
;
659 events_request
->trace
= i
;
661 events_request
->hooks
= hooks
;
663 events_request
->before_chunk_traceset
= NULL
;
664 events_request
->before_chunk_trace
= NULL
;
665 events_request
->before_chunk_tracefile
= NULL
;
666 events_request
->event
= NULL
;
667 events_request
->event_by_id
= event_data
->event_by_id_hooks
;
668 events_request
->after_chunk_tracefile
= NULL
;
669 events_request
->after_chunk_trace
= NULL
;
670 events_request
->after_chunk_traceset
= NULL
;
671 events_request
->before_request
= NULL
;
672 events_request
->after_request
= event_data
->hooks_trace_after
;
674 lttvwindow_events_request(event_data
->tab
, events_request
);
681 static void CalculateAverageDurationForEachIrqId(InterruptEventData
*event_data
)
686 GArray
* FirstRequestIrqExit
= event_data
->FirstRequestIrqExit
;
687 for(i
= 0; i
< FirstRequestIrqExit
->len
; i
++)
689 element
= &g_array_index(FirstRequestIrqExit
,Irq
,i
);
690 real_data
= element
->total_duration
.tv_sec
;
691 real_data
*= NANOSECONDS_PER_SECOND
;
692 real_data
+= element
->total_duration
.tv_nsec
;
693 element
->average_duration
= real_data
/ element
->frequency
;
694 printf("average duration: %d\n", element
->average_duration
);
699 static gboolean
SecondRequestIrqEntryCallback(void *hook_data
, void *call_data
)
705 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
706 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
707 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
708 GArray
* SecondRequestIrqEntry
= event_data
->SecondRequestIrqEntry
;
709 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
710 event_time
= ltt_event_time(e
);
711 cpu_id
= ltt_event_cpu_id(e
);
714 entry
.id
=get_interrupt_id(e
);
715 entry
.cpu_id
= cpu_id
;
716 entry
.event_time
= event_time
;
717 g_array_append_val (SecondRequestIrqEntry
, entry
);
722 static gboolean
SecondRequestIrqExitCallback(void *hook_data
, void *call_data
)
725 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
726 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
727 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
728 LttEvent
*event
= ltt_tracefile_get_event(tfc
->tf
);
730 CalculateXi(event
, event_data
);
734 static void CalculateXi(LttEvent
*event_irq_exit
, InterruptEventData
*event_data
)
742 GArray
*SecondRequestIrqExit
= event_data
->SecondRequestIrqExit
;
743 GArray
*SecondRequestIrqEntry
= event_data
->SecondRequestIrqEntry
;
744 cpu_id
= ltt_event_cpu_id(event_irq_exit
);
745 for(i
= 0; i
< SecondRequestIrqEntry
->len
; i
++)
747 element
= &g_array_index(SecondRequestIrqEntry
,irq_entry
,i
);
748 if(element
->cpu_id
== cpu_id
)
751 /* time calculation */
752 exit_time
= ltt_event_time(event_irq_exit
);
753 Xi
= ltt_time_sub(exit_time
, element
->event_time
);
754 irq_id
= element
->id
;
756 SumItems(irq_id
, Xi
,event_data
);
757 g_array_remove_index(SecondRequestIrqEntry
, i
);
763 static void SumItems(gint irq_id
, LttTime Xi
, InterruptEventData
*event_data
)
772 gboolean notFound
= FALSE
;
773 GArray
*FirstRequestIrqExit
= event_data
->FirstRequestIrqExit
;
774 GArray
*SumArray
= event_data
->SumArray
;
775 time_in_ns
= Xi
.tv_sec
;
776 time_in_ns
*= NANOSECONDS_PER_SECOND
;
777 time_in_ns
+= Xi
.tv_nsec
;
779 for(i
= 0; i
< FirstRequestIrqExit
->len
; i
++)
781 average
= &g_array_index(FirstRequestIrqExit
,Irq
,i
);
782 if(irq_id
== average
->id
)
784 temp
= time_in_ns
- average
->average_duration
;
785 sum
.sumOfDurations
= pow (temp
, 2);
786 //printf("one : %d\n", sum.sumOfDurations);
788 sum
.frequency
= average
->frequency
;
789 if(event_data
->SumArray
->len
== NO_ITEMS
)
791 g_array_append_val (SumArray
, sum
);
796 for(i
= 0; i
< SumArray
->len
; i
++)
798 sumItem
= &g_array_index(SumArray
, SumId
, i
);
799 if(sumItem
->irqId
== irq_id
)
802 sumItem
->sumOfDurations
+= sum
.sumOfDurations
;
808 g_array_append_val (SumArray
, sum
);
819 * This function displays the result on the viewer
822 static gboolean
DisplayViewer(void *hook_data
, void *call_data
)
828 LttTime average_duration
;
831 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
832 GArray
*FirstRequestIrqExit
= event_data
->FirstRequestIrqExit
;
833 gtk_list_store_clear(event_data
->ListStore
);
834 for(i
= 0; i
< FirstRequestIrqExit
->len
; i
++)
836 element
= g_array_index(FirstRequestIrqExit
,Irq
,i
);
837 real_data
= element
.total_duration
.tv_sec
;
838 real_data
*= NANOSECONDS_PER_SECOND
;
839 real_data
+= element
.total_duration
.tv_nsec
;
840 gtk_list_store_append (event_data
->ListStore
, &iter
);
841 gtk_list_store_set (event_data
->ListStore
, &iter
,
842 CPUID_COLUMN
, element
.cpu_id
,
843 IRQ_ID_COLUMN
, element
.id
,
844 FREQUENCY_COLUMN
, element
.frequency
,
845 DURATION_COLUMN
, real_data
,
846 DURATION_STANDARD_DEV_COLUMN
, CalculateStandardDeviation(element
.id
, event_data
),
853 if(event_data
->FirstRequestIrqExit
->len
)
855 g_array_remove_range (event_data
->FirstRequestIrqExit
,0,event_data
->FirstRequestIrqExit
->len
);
858 if(event_data
->FirstRequestIrqEntry
->len
)
860 g_array_remove_range (event_data
->FirstRequestIrqEntry
,0,event_data
->FirstRequestIrqEntry
->len
);
863 if(event_data
->SecondRequestIrqEntry
->len
)
865 g_array_remove_range (event_data
->SecondRequestIrqEntry
,0,event_data
->SecondRequestIrqEntry
->len
);
868 if(event_data
->SecondRequestIrqExit
->len
)
870 g_array_remove_range (event_data
->SecondRequestIrqExit
,0, event_data
->SecondRequestIrqExit
->len
);
873 if(event_data
->SumArray
->len
)
875 g_array_remove_range (event_data
->SumArray
,0, event_data
->SumArray
->len
);
881 static int CalculateStandardDeviation(gint id
, InterruptEventData
*event_data
)
885 double inner_component
;
887 for(i
= 0; i
< event_data
->SumArray
->len
; i
++)
889 sumId
= g_array_index(event_data
->SumArray
, SumId
, i
);
890 if(id
== sumId
.irqId
)
892 printf("id: %d\n", sumId
.irqId
);
893 inner_component
= sumId
.sumOfDurations
/ sumId
.frequency
;
894 deviation
= sqrt(inner_component
);
895 printf("deviation: %d\n", deviation
);
903 * This function is called by the main window
904 * when the time interval needs to be updated.
906 gboolean
interrupt_update_time_window(void * hook_data
, void * call_data
)
908 InterruptEventData
*event_data
= (InterruptEventData
*) hook_data
;
909 const TimeWindowNotifyData
*time_window_nofify_data
= ((const TimeWindowNotifyData
*)call_data
);
910 event_data
->time_window
= *time_window_nofify_data
->new_time_window
;
911 g_info("interrupts: interrupt_update_time_window()\n");
912 Tab
*tab
= event_data
->tab
;
913 lttvwindow_events_request_remove_all(tab
, event_data
);
914 FirstRequest(event_data
);
919 gboolean
trace_header(void *hook_data
, void *call_data
)
922 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
923 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
929 void interrupt_destroy_walk(gpointer data
, gpointer user_data
)
931 g_info("interrupt_destroy_walk");
932 interrupt_destructor((InterruptEventData
*)data
);
936 void interrupt_destructor(InterruptEventData
*event_viewer_data
)
938 /* May already been done by GTK window closing */
939 g_info("enter interrupt_destructor \n");
940 if(GTK_IS_WIDGET(event_viewer_data
->Hbox
))
942 gtk_widget_destroy(event_viewer_data
->Hbox
);
947 * plugin's destroy function
949 * This function releases the memory reserved by the module and unregisters
950 * everything that has been registered in the gtkTraceSet API.
952 static void destroy()
955 g_info("Destroy interrupts");
956 g_slist_foreach(interrupt_data_list
, interrupt_destroy_walk
, NULL
);
957 g_slist_free(interrupt_data_list
);
958 lttvwindow_unregister_constructor(interrupts
);
962 LTTV_MODULE("interrupts", "interrupts info view", \
963 "Graphical module to display interrupts performance", \
964 init
, destroy
, "lttvwindow")