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