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)
80 LttTime total_duration
;
81 guint average_duration
;
82 MaxDuration max_irq_handler
;
97 guint64 sumOfDurations
;
106 /** Array containing instanced objects. Used when module is unloaded */
107 static GSList
*interrupt_data_list
= NULL
;
110 #define TRACE_NUMBER 0
112 typedef struct _InterruptEventData
{
114 /*Graphical Widgets */
115 GtkWidget
* ScrollWindow
;
116 GtkListStore
*ListStore
;
119 GtkTreeSelection
*SelectionTree
;
121 Tab
* tab
; /* tab that contains this plug-in*/
122 LttvHooks
* event_hooks
;
123 LttvHooks
* hooks_trace_after
;
124 LttvHooks
* hooks_trace_before
;
125 TimeWindow time_window
;
126 LttvHooksById
* event_by_id_hooks
;
127 GArray
*FirstRequestIrqExit
;
128 GArray
*FirstRequestIrqEntry
;
129 GArray
*SecondRequestIrqEntry
;
130 GArray
*SecondRequestIrqExit
;
133 } InterruptEventData
;
136 /* Function prototypes */
138 static gboolean
interrupt_update_time_window(void * hook_data
, void * call_data
);
139 static GtkWidget
*interrupts(Tab
*tab
);
140 static InterruptEventData
*system_info(Tab
*tab
);
141 void interrupt_destructor(InterruptEventData
*event_viewer_data
);
142 static void FirstRequest(InterruptEventData
*event_data
);
143 static guint64
get_interrupt_id(LttEvent
*e
);
144 static gboolean
trace_header(void *hook_data
, void *call_data
);
145 static gboolean
DisplayViewer (void *hook_data
, void *call_data
);
146 static void calcul_duration(LttTime time_exit
, guint cpu_id
, InterruptEventData
*event_data
);
147 static void sum_interrupt_data(irq_entry
*e
, LttTime time_exit
, GArray
*FirstRequestIrqExit
);
148 static gboolean
FirstRequestIrqEntryCallback(void *hook_data
, void *call_data
);
149 static gboolean
FirstRequestIrqExitCallback(void *hook_data
, void *call_data
);
150 static gboolean
SecondRequest(void *hook_data
, void *call_data
);
151 static void CalculateAverageDurationForEachIrqId(InterruptEventData
*event_data
);
152 static gboolean
SecondRequestIrqEntryCallback(void *hook_data
, void *call_data
);
153 static gboolean
SecondRequestIrqExitCallback(void *hook_data
, void *call_data
);
154 static void CalculateXi(LttEvent
*event
, InterruptEventData
*event_data
);
155 static void SumItems(gint irq_id
, LttTime Xi
, InterruptEventData
*event_data
);
156 static int CalculateStandardDeviation(gint id
, InterruptEventData
*event_data
);
157 static void CalculateMaxIRQHandler(LttEvent
*event
);
158 /* Enumeration of the columns */
164 DURATION_STANDARD_DEV_COLUMN
,
165 MAX_IRQ_HANDLER_COLUMN
,
175 * This is the entry point of the viewer.
179 g_info("interrupts: init()");
180 lttvwindow_register_constructor("interrupts",
182 "Insert Interrupts View",
183 hInterruptsInsert_xpm
,
184 "Insert Interrupts View",
194 static GtkWidget
*interrupts(Tab
* tab
)
197 InterruptEventData
* event_data
= system_info(tab
) ;
199 return event_data
->Hbox
;
205 * This function initializes the Event Viewer functionnality through the
208 InterruptEventData
*system_info(Tab
*tab
)
212 GtkTreeViewColumn
*column
;
213 GtkCellRenderer
*renderer
;
214 InterruptEventData
* event_viewer_data
= g_new(InterruptEventData
,1) ;
216 event_viewer_data
->tab
= tab
;
218 /*Get the current time frame from the main window */
219 event_viewer_data
->time_window
= lttvwindow_get_time_window(tab
);
221 event_viewer_data
->FirstRequestIrqExit
= g_array_new(FALSE
, FALSE
, sizeof(Irq
));
222 event_viewer_data
->FirstRequestIrqEntry
= g_array_new(FALSE
, FALSE
, sizeof(irq_entry
));
224 event_viewer_data
->SecondRequestIrqEntry
= g_array_new(FALSE
, FALSE
, sizeof(irq_entry
));
225 event_viewer_data
->SecondRequestIrqExit
= g_array_new(FALSE
, FALSE
, sizeof(Irq
));
227 event_viewer_data
->SumArray
= g_array_new(FALSE
, FALSE
, sizeof(SumId
));
230 /*Create tha main window for the viewer */
231 event_viewer_data
->ScrollWindow
= gtk_scrolled_window_new (NULL
, NULL
);
232 gtk_widget_show (event_viewer_data
->ScrollWindow
);
233 gtk_scrolled_window_set_policy(
234 GTK_SCROLLED_WINDOW(event_viewer_data
->ScrollWindow
),
235 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
/*GTK_POLICY_NEVER*/);
237 /* Create a model for storing the data list */
238 event_viewer_data
->ListStore
= gtk_list_store_new (
239 N_COLUMNS
, /* Total number of columns */
240 G_TYPE_INT
, /* CPUID */
241 G_TYPE_INT
, /* IRQ_ID */
242 G_TYPE_INT
, /* Frequency */
243 G_TYPE_UINT64
, /* Duration */
244 G_TYPE_INT
, /* standard deviation */
245 G_TYPE_INT
/* Max IRQ handler */
248 event_viewer_data
->TreeView
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data
->ListStore
));
250 g_object_unref (G_OBJECT (event_viewer_data
->ListStore
));
252 renderer
= gtk_cell_renderer_text_new ();
253 column
= gtk_tree_view_column_new_with_attributes ("CPUID",
255 "text", CPUID_COLUMN
,
257 gtk_tree_view_column_set_alignment (column
, 0.0);
258 gtk_tree_view_column_set_fixed_width (column
, 45);
259 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->TreeView
), column
);
262 renderer
= gtk_cell_renderer_text_new ();
263 column
= gtk_tree_view_column_new_with_attributes ("IrqId",
265 "text", IRQ_ID_COLUMN
,
267 gtk_tree_view_column_set_alignment (column
, 0.0);
268 gtk_tree_view_column_set_fixed_width (column
, 220);
269 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->TreeView
), column
);
271 renderer
= gtk_cell_renderer_text_new ();
272 column
= gtk_tree_view_column_new_with_attributes ("Frequency",
274 "text", FREQUENCY_COLUMN
,
276 gtk_tree_view_column_set_alignment (column
, 1.0);
277 gtk_tree_view_column_set_fixed_width (column
, 220);
278 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 (nsec)",
283 "text", DURATION_COLUMN
,
285 gtk_tree_view_column_set_alignment (column
, 0.0);
286 gtk_tree_view_column_set_fixed_width (column
, 145);
287 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->TreeView
), column
);
290 renderer
= gtk_cell_renderer_text_new ();
291 column
= gtk_tree_view_column_new_with_attributes ("Duration standard deviation (nsec)",
293 "text", DURATION_STANDARD_DEV_COLUMN
,
295 gtk_tree_view_column_set_alignment (column
, 0.0);
296 gtk_tree_view_column_set_fixed_width (column
, 200);
297 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->TreeView
), column
);
299 renderer
= gtk_cell_renderer_text_new ();
300 column
= gtk_tree_view_column_new_with_attributes ("Max IRQ handler duration (nsec)",
302 "text", MAX_IRQ_HANDLER_COLUMN
,
304 gtk_tree_view_column_set_alignment (column
, 0.0);
305 gtk_tree_view_column_set_fixed_width (column
, 250);
306 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->TreeView
), column
);
309 event_viewer_data
->SelectionTree
= gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data
->TreeView
));
310 gtk_tree_selection_set_mode (event_viewer_data
->SelectionTree
, GTK_SELECTION_SINGLE
);
312 gtk_container_add (GTK_CONTAINER (event_viewer_data
->ScrollWindow
), event_viewer_data
->TreeView
);
314 event_viewer_data
->Hbox
= gtk_hbox_new(0, 0);
315 gtk_box_pack_start(GTK_BOX(event_viewer_data
->Hbox
), event_viewer_data
->ScrollWindow
, TRUE
, TRUE
, 0);
317 gtk_widget_show(event_viewer_data
->Hbox
);
318 gtk_widget_show(event_viewer_data
->TreeView
);
320 interrupt_data_list
= g_slist_append(interrupt_data_list
, event_viewer_data
);
321 /* Registration for time notification */
322 lttvwindow_register_time_window_notify(tab
,
323 interrupt_update_time_window
,
327 FirstRequest(event_viewer_data
);
328 return event_viewer_data
;
333 * For each trace in the traceset, this function:
334 * - registers a callback function to each hook
335 * - calls lttv_trace_find_hook() registers a hook function to event_by_id_hooks
336 * - calls lttvwindow_events_request() to request data in a specific
337 * time interval to the main window
340 static void FirstRequest(InterruptEventData
*event_data
)
342 guint i
, k
, l
, nb_trace
;
352 EventsRequest
*events_request
;
354 LttvTraceHookByFacility
*thf
;
356 LttvTracesetContext
*tsc
= lttvwindow_get_traceset_context(event_data
->tab
);
359 /* Get the traceset */
360 LttvTraceset
*traceset
= tsc
->ts
;
362 nb_trace
= lttv_traceset_number(traceset
);
364 /* There are many traces in a traceset. Iteration for each trace. */
365 for(i
= 0; i
<MIN(TRACE_NUMBER
+1, nb_trace
);i
++)
367 events_request
= g_new(EventsRequest
, 1);
369 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
371 hooks
= g_array_set_size(hooks
, 2);
373 event_data
->hooks_trace_before
= lttv_hooks_new();
375 /* Registers a hook function */
376 lttv_hooks_add(event_data
->hooks_trace_before
, trace_header
, event_data
, LTTV_PRIO_DEFAULT
);
378 event_data
->hooks_trace_after
= lttv_hooks_new();
380 /* Registers a hook function */
381 lttv_hooks_add(event_data
->hooks_trace_after
, SecondRequest
, event_data
, LTTV_PRIO_DEFAULT
);
382 /* Get a trace state */
383 ts
= (LttvTraceState
*)tsc
->traces
[i
];
384 /* Create event_by_Id hooks */
385 event_data
->event_by_id_hooks
= lttv_hooks_by_id_new();
387 /*Register event_by_id_hooks with a callback function*/
388 ret
= lttv_trace_find_hook(ts
->parent
.t
,
389 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
390 LTT_FIELD_IRQ_ID
, 0, 0,
391 FirstRequestIrqEntryCallback
,
393 &g_array_index(hooks
, LttvTraceHook
, 0));
395 ret
= lttv_trace_find_hook(ts
->parent
.t
,
396 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
397 LTT_FIELD_IRQ_ID
, 0, 0,
398 FirstRequestIrqExitCallback
,
400 &g_array_index(hooks
, LttvTraceHook
, 1));
403 /*iterate through the facility list*/
404 for(k
= 0 ; k
< hooks
->len
; k
++)
406 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
407 for(l
=0; l
<hook
->fac_list
->len
; l
++)
409 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
410 lttv_hooks_add(lttv_hooks_by_id_find(event_data
->event_by_id_hooks
, thf
->id
),
417 /* Initalize the EventsRequest structure */
418 events_request
->owner
= event_data
;
419 events_request
->viewer_data
= event_data
;
420 events_request
->servicing
= FALSE
;
421 events_request
->start_time
= event_data
->time_window
.start_time
;
422 events_request
->start_position
= NULL
;
423 events_request
->stop_flag
= FALSE
;
424 events_request
->end_time
= event_data
->time_window
.end_time
;
425 events_request
->num_events
= G_MAXUINT
;
426 events_request
->end_position
= NULL
;
427 events_request
->trace
= i
;
429 events_request
->hooks
= hooks
;
431 events_request
->before_chunk_traceset
= NULL
;
432 events_request
->before_chunk_trace
= event_data
->hooks_trace_before
;
433 events_request
->before_chunk_tracefile
= NULL
;
434 events_request
->event
= NULL
;
435 events_request
->event_by_id
= event_data
->event_by_id_hooks
;
436 events_request
->after_chunk_tracefile
= NULL
;
437 events_request
->after_chunk_trace
= NULL
;
438 events_request
->after_chunk_traceset
= NULL
;
439 events_request
->before_request
= NULL
;
440 events_request
->after_request
= event_data
->hooks_trace_after
;
442 lttvwindow_events_request(event_data
->tab
, events_request
);
448 * This function is called whenever an irq_entry event occurs.
451 static gboolean
FirstRequestIrqEntryCallback(void *hook_data
, void *call_data
)
457 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
458 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
459 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
460 GArray
* FirstRequestIrqEntry
= event_data
->FirstRequestIrqEntry
;
461 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
462 event_time
= ltt_event_time(e
);
463 cpu_id
= ltt_event_cpu_id(e
);
466 entry
.id
=get_interrupt_id(e
);
467 entry
.cpu_id
= cpu_id
;
468 entry
.event_time
= event_time
;
469 g_array_append_val (FirstRequestIrqEntry
, entry
);
475 * This function gets the id of the interrupt. The id is stored in a dynamic structure.
476 * Refer to the print.c file for howto extract data from a dynamic structure.
478 static guint64
get_interrupt_id(LttEvent
*e
)
481 LttEventType
*event_type
;
485 event_type
= ltt_event_eventtype(e
);
486 num_fields
= ltt_eventtype_num_fields(event_type
);
487 for(i
= 0 ; i
< num_fields
-1 ; i
++)
489 field
= ltt_eventtype_field(event_type
, i
);
490 irq_id
= ltt_event_get_long_unsigned(e
,field
);
496 * This function is called whenever an irq_exit event occurs.
499 gboolean
FirstRequestIrqExitCallback(void *hook_data
, void *call_data
)
503 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
504 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
505 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
506 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
507 LttEventType
*type
= ltt_event_eventtype(e
);
508 event_time
= ltt_event_time(e
);
509 cpu_id
= ltt_event_cpu_id(e
);
511 calcul_duration( event_time
, cpu_id
, event_data
);
512 CalculateMaxIRQHandler(e
);
517 * This function calculates the duration of an interrupt.
520 static void calcul_duration(LttTime time_exit
, guint cpu_id
,InterruptEventData
*event_data
)
526 GArray
*FirstRequestIrqExit
= event_data
->FirstRequestIrqExit
;
527 GArray
*FirstRequestIrqEntry
= event_data
->FirstRequestIrqEntry
;
528 for(i
= 0; i
< FirstRequestIrqEntry
->len
; i
++)
530 element
= &g_array_index(FirstRequestIrqEntry
,irq_entry
,i
);
531 if(element
->cpu_id
== cpu_id
)
533 sum_interrupt_data(element
,time_exit
, FirstRequestIrqExit
);
534 g_array_remove_index(FirstRequestIrqEntry
, i
);
540 static void CalculateMaxIRQHandler(LttEvent
*event
)
546 * This function calculates the total duration of an interrupt.
549 static void sum_interrupt_data(irq_entry
*e
, LttTime time_exit
, GArray
*FirstRequestIrqExit
){
554 gboolean notFound
= FALSE
;
555 memset ((void*)&irq
, 0,sizeof(Irq
));
558 if(FirstRequestIrqExit
->len
== NO_ITEMS
)
560 irq
.cpu_id
= e
->cpu_id
;
563 irq
.total_duration
= ltt_time_sub(time_exit
, e
->event_time
);
566 irq
.max_irq_handler
.start_time
= e
->event_time
;
567 irq
.max_irq_handler
.end_time
= time_exit
;
568 irq
.max_irq_handler
.duration
= ltt_time_sub(time_exit
, e
->event_time
);
570 irq.max_irq_handler.duration = duration.tv_sec;
571 irq.max_irq_handler.duration *= NANOSECONDS_PER_SECOND;
572 irq.max_irq_handler.duration += element.total_duration.tv_nsec;
576 g_array_append_val (FirstRequestIrqExit
, irq
);
580 for(i
= 0; i
< FirstRequestIrqExit
->len
; i
++)
582 element
= &g_array_index(FirstRequestIrqExit
,Irq
,i
);
583 if(element
->id
== e
->id
)
586 duration
= ltt_time_sub(time_exit
, e
->event_time
);
587 element
->total_duration
= ltt_time_add(element
->total_duration
, duration
);
588 element
->frequency
++;
589 if(ltt_time_compare(duration
,element
->max_irq_handler
.duration
) > 0)
591 element
->max_irq_handler
.duration
= duration
;
592 element
->max_irq_handler
.start_time
= e
->event_time
;
593 element
->max_irq_handler
.end_time
= time_exit
;
599 irq
.cpu_id
= e
->cpu_id
;
602 irq
.total_duration
= ltt_time_sub(time_exit
, e
->event_time
);
604 irq
.max_irq_handler
.start_time
= e
->event_time
;
605 irq
.max_irq_handler
.end_time
= time_exit
;
606 irq
.max_irq_handler
.duration
= ltt_time_sub(time_exit
, e
->event_time
);
608 g_array_append_val (FirstRequestIrqExit
, irq
);
613 static gboolean
SecondRequest(void *hook_data
, void *call_data
)
616 guint i
, k
, l
, nb_trace
;
626 EventsRequest
*events_request
;
628 LttvTraceHookByFacility
*thf
;
630 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
632 LttvTracesetContext
*tsc
= lttvwindow_get_traceset_context(event_data
->tab
);
634 CalculateAverageDurationForEachIrqId(event_data
);
636 /* Get the traceset */
637 LttvTraceset
*traceset
= tsc
->ts
;
639 nb_trace
= lttv_traceset_number(traceset
);
641 /* There are many traces in a traceset. Iteration for each trace. */
642 for(i
= 0; i
<MIN(TRACE_NUMBER
+1, nb_trace
);i
++)
644 events_request
= g_new(EventsRequest
, 1);
646 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
648 hooks
= g_array_set_size(hooks
, 2);
650 event_data
->hooks_trace_after
= lttv_hooks_new();
652 /* Registers a hook function */
653 lttv_hooks_add(event_data
->hooks_trace_after
, DisplayViewer
, event_data
, LTTV_PRIO_DEFAULT
);
655 /* Get a trace state */
656 ts
= (LttvTraceState
*)tsc
->traces
[i
];
657 /* Create event_by_Id hooks */
658 event_data
->event_by_id_hooks
= lttv_hooks_by_id_new();
660 /*Register event_by_id_hooks with a callback function*/
661 ret
= lttv_trace_find_hook(ts
->parent
.t
,
662 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
663 LTT_FIELD_IRQ_ID
, 0, 0,
664 SecondRequestIrqEntryCallback
,
666 &g_array_index(hooks
, LttvTraceHook
, 0));
668 ret
= lttv_trace_find_hook(ts
->parent
.t
,
669 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
670 LTT_FIELD_IRQ_ID
, 0, 0,
671 SecondRequestIrqExitCallback
,
673 &g_array_index(hooks
, LttvTraceHook
, 1));
676 /*iterate through the facility list*/
677 for(k
= 0 ; k
< hooks
->len
; k
++)
679 hook
= &g_array_index(hooks
, LttvTraceHook
, k
);
680 for(l
=0; l
<hook
->fac_list
->len
; l
++)
682 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
683 lttv_hooks_add(lttv_hooks_by_id_find(event_data
->event_by_id_hooks
, thf
->id
),
690 /* Initalize the EventsRequest structure */
691 events_request
->owner
= event_data
;
692 events_request
->viewer_data
= event_data
;
693 events_request
->servicing
= FALSE
;
694 events_request
->start_time
= event_data
->time_window
.start_time
;
695 events_request
->start_position
= NULL
;
696 events_request
->stop_flag
= FALSE
;
697 events_request
->end_time
= event_data
->time_window
.end_time
;
698 events_request
->num_events
= G_MAXUINT
;
699 events_request
->end_position
= NULL
;
700 events_request
->trace
= i
;
702 events_request
->hooks
= hooks
;
704 events_request
->before_chunk_traceset
= NULL
;
705 events_request
->before_chunk_trace
= NULL
;
706 events_request
->before_chunk_tracefile
= NULL
;
707 events_request
->event
= NULL
;
708 events_request
->event_by_id
= event_data
->event_by_id_hooks
;
709 events_request
->after_chunk_tracefile
= NULL
;
710 events_request
->after_chunk_trace
= NULL
;
711 events_request
->after_chunk_traceset
= NULL
;
712 events_request
->before_request
= NULL
;
713 events_request
->after_request
= event_data
->hooks_trace_after
;
715 lttvwindow_events_request(event_data
->tab
, events_request
);
722 static void CalculateAverageDurationForEachIrqId(InterruptEventData
*event_data
)
727 GArray
* FirstRequestIrqExit
= event_data
->FirstRequestIrqExit
;
728 for(i
= 0; i
< FirstRequestIrqExit
->len
; i
++)
730 element
= &g_array_index(FirstRequestIrqExit
,Irq
,i
);
731 real_data
= element
->total_duration
.tv_sec
;
732 real_data
*= NANOSECONDS_PER_SECOND
;
733 real_data
+= element
->total_duration
.tv_nsec
;
734 element
->average_duration
= real_data
/ element
->frequency
;
735 printf("average duration: %d\n", element
->average_duration
);
740 static gboolean
SecondRequestIrqEntryCallback(void *hook_data
, void *call_data
)
746 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
747 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
748 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
749 GArray
* SecondRequestIrqEntry
= event_data
->SecondRequestIrqEntry
;
750 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
751 event_time
= ltt_event_time(e
);
752 cpu_id
= ltt_event_cpu_id(e
);
755 entry
.id
=get_interrupt_id(e
);
756 entry
.cpu_id
= cpu_id
;
757 entry
.event_time
= event_time
;
758 g_array_append_val (SecondRequestIrqEntry
, entry
);
763 static gboolean
SecondRequestIrqExitCallback(void *hook_data
, void *call_data
)
766 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
767 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
768 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
769 LttEvent
*event
= ltt_tracefile_get_event(tfc
->tf
);
771 CalculateXi(event
, event_data
);
775 static void CalculateXi(LttEvent
*event_irq_exit
, InterruptEventData
*event_data
)
783 GArray
*SecondRequestIrqExit
= event_data
->SecondRequestIrqExit
;
784 GArray
*SecondRequestIrqEntry
= event_data
->SecondRequestIrqEntry
;
785 cpu_id
= ltt_event_cpu_id(event_irq_exit
);
786 for(i
= 0; i
< SecondRequestIrqEntry
->len
; i
++)
788 element
= &g_array_index(SecondRequestIrqEntry
,irq_entry
,i
);
789 if(element
->cpu_id
== cpu_id
)
792 /* time calculation */
793 exit_time
= ltt_event_time(event_irq_exit
);
794 Xi
= ltt_time_sub(exit_time
, element
->event_time
);
795 irq_id
= element
->id
;
797 SumItems(irq_id
, Xi
,event_data
);
798 g_array_remove_index(SecondRequestIrqEntry
, i
);
804 static void SumItems(gint irq_id
, LttTime Xi
, InterruptEventData
*event_data
)
813 gboolean notFound
= FALSE
;
814 GArray
*FirstRequestIrqExit
= event_data
->FirstRequestIrqExit
;
815 GArray
*SumArray
= event_data
->SumArray
;
816 time_in_ns
= Xi
.tv_sec
;
817 time_in_ns
*= NANOSECONDS_PER_SECOND
;
818 time_in_ns
+= Xi
.tv_nsec
;
820 for(i
= 0; i
< FirstRequestIrqExit
->len
; i
++)
822 average
= &g_array_index(FirstRequestIrqExit
,Irq
,i
);
823 if(irq_id
== average
->id
)
825 temp
= time_in_ns
- average
->average_duration
;
826 sum
.sumOfDurations
= pow (temp
, 2);
827 //printf("one : %d\n", sum.sumOfDurations);
829 sum
.frequency
= average
->frequency
;
830 if(event_data
->SumArray
->len
== NO_ITEMS
)
832 g_array_append_val (SumArray
, sum
);
837 for(i
= 0; i
< SumArray
->len
; i
++)
839 sumItem
= &g_array_index(SumArray
, SumId
, i
);
840 if(sumItem
->irqId
== irq_id
)
843 sumItem
->sumOfDurations
+= sum
.sumOfDurations
;
849 g_array_append_val (SumArray
, sum
);
860 * This function displays the result on the viewer
863 static gboolean
DisplayViewer(void *hook_data
, void *call_data
)
869 LttTime average_duration
;
872 guint maxIRQduration
;
873 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
874 GArray
*FirstRequestIrqExit
= event_data
->FirstRequestIrqExit
;
875 gtk_list_store_clear(event_data
->ListStore
);
876 for(i
= 0; i
< FirstRequestIrqExit
->len
; i
++)
878 element
= g_array_index(FirstRequestIrqExit
,Irq
,i
);
879 real_data
= element
.total_duration
.tv_sec
;
880 real_data
*= NANOSECONDS_PER_SECOND
;
881 real_data
+= element
.total_duration
.tv_nsec
;
884 maxIRQduration
= element
.max_irq_handler
.duration
.tv_sec
;
885 maxIRQduration
*= NANOSECONDS_PER_SECOND
;
886 maxIRQduration
+= element
.max_irq_handler
.duration
.tv_nsec
;
888 gtk_list_store_append (event_data
->ListStore
, &iter
);
889 gtk_list_store_set (event_data
->ListStore
, &iter
,
890 CPUID_COLUMN
, element
.cpu_id
,
891 IRQ_ID_COLUMN
, element
.id
,
892 FREQUENCY_COLUMN
, element
.frequency
,
893 DURATION_COLUMN
, real_data
,
894 DURATION_STANDARD_DEV_COLUMN
, CalculateStandardDeviation(element
.id
, event_data
),
895 MAX_IRQ_HANDLER_COLUMN
, maxIRQduration
,
903 if(event_data
->FirstRequestIrqExit
->len
)
905 g_array_remove_range (event_data
->FirstRequestIrqExit
,0,event_data
->FirstRequestIrqExit
->len
);
908 if(event_data
->FirstRequestIrqEntry
->len
)
910 g_array_remove_range (event_data
->FirstRequestIrqEntry
,0,event_data
->FirstRequestIrqEntry
->len
);
913 if(event_data
->SecondRequestIrqEntry
->len
)
915 g_array_remove_range (event_data
->SecondRequestIrqEntry
,0,event_data
->SecondRequestIrqEntry
->len
);
918 if(event_data
->SecondRequestIrqExit
->len
)
920 g_array_remove_range (event_data
->SecondRequestIrqExit
,0, event_data
->SecondRequestIrqExit
->len
);
923 if(event_data
->SumArray
->len
)
925 g_array_remove_range (event_data
->SumArray
,0, event_data
->SumArray
->len
);
931 static int CalculateStandardDeviation(gint id
, InterruptEventData
*event_data
)
935 double inner_component
;
937 for(i
= 0; i
< event_data
->SumArray
->len
; i
++)
939 sumId
= g_array_index(event_data
->SumArray
, SumId
, i
);
940 if(id
== sumId
.irqId
)
942 printf("id: %d\n", sumId
.irqId
);
943 inner_component
= sumId
.sumOfDurations
/ sumId
.frequency
;
944 deviation
= sqrt(inner_component
);
945 printf("deviation: %d\n", deviation
);
953 * This function is called by the main window
954 * when the time interval needs to be updated.
956 gboolean
interrupt_update_time_window(void * hook_data
, void * call_data
)
958 InterruptEventData
*event_data
= (InterruptEventData
*) hook_data
;
959 const TimeWindowNotifyData
*time_window_nofify_data
= ((const TimeWindowNotifyData
*)call_data
);
960 event_data
->time_window
= *time_window_nofify_data
->new_time_window
;
961 g_info("interrupts: interrupt_update_time_window()\n");
962 Tab
*tab
= event_data
->tab
;
963 lttvwindow_events_request_remove_all(tab
, event_data
);
964 FirstRequest(event_data
);
969 gboolean
trace_header(void *hook_data
, void *call_data
)
972 InterruptEventData
*event_data
= (InterruptEventData
*)hook_data
;
973 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
979 void interrupt_destroy_walk(gpointer data
, gpointer user_data
)
981 g_info("interrupt_destroy_walk");
982 interrupt_destructor((InterruptEventData
*)data
);
986 void interrupt_destructor(InterruptEventData
*event_viewer_data
)
988 /* May already been done by GTK window closing */
989 g_info("enter interrupt_destructor \n");
990 if(GTK_IS_WIDGET(event_viewer_data
->Hbox
))
992 gtk_widget_destroy(event_viewer_data
->Hbox
);
997 * plugin's destroy function
999 * This function releases the memory reserved by the module and unregisters
1000 * everything that has been registered in the gtkTraceSet API.
1002 static void destroy()
1005 g_info("Destroy interrupts");
1006 g_slist_foreach(interrupt_data_list
, interrupt_destroy_walk
, NULL
);
1007 g_slist_free(interrupt_data_list
);
1008 lttvwindow_unregister_constructor(interrupts
);
1012 LTTV_MODULE("interrupts", "interrupts info view", \
1013 "Graphical module to display interrupts performance", \
1014 init
, destroy
, "lttvwindow")