Modified standard deviation
[lttv.git] / ltt / branches / poly / lttv / modules / gui / interrupts / interrupts.c
... / ...
CommitLineData
1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2005 Peter Ho
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19 /******************************************************************
20 CPUID | IRQID | Frequency |
21
22 The standard deviation (sigma) is based on:
23 http://en.wikipedia.org/wiki/Standard_deviation
24
25 sigma = sqrt(1/N Sum ((xi -Xa)^2))
26
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
30 FirstRequestIrqExit.
31
32 In the second EventRequest, we compute the Sum ((xi -Xa)^2)
33
34
35
36
37
38 *******************************************************************/
39
40
41
42#include <math.h>
43#include <glib.h>
44#include <gtk/gtk.h>
45#include <gdk/gdk.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <math.h>
49#include <string.h>
50#include <ltt/ltt.h>
51#include <ltt/event.h>
52#include <ltt/type.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>
61#include <ltt/time.h>
62
63#include "hInterruptsInsert.xpm"
64
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)
67#define NO_ITEMS 0
68
69typedef struct
70{
71 LttTime duration;
72 LttTime start_time;
73 LttTime end_time;
74}MaxDuration;
75
76typedef struct {
77 guint cpu_id;
78 guint id;
79 guint frequency;
80 LttTime total_duration;
81 guint average_duration;
82 MaxDuration max_irq_handler;
83
84}Irq;
85
86typedef struct {
87 guint id;
88 guint cpu_id;
89 LttTime event_time;
90}irq_entry;
91
92
93typedef struct
94{
95 guint irqId;
96 guint frequency;
97 guint64 sumOfDurations;
98
99}SumId;
100
101enum type_t {
102 IRQ_ENTRY,
103 IRQ_EXIT
104};
105
106/** Array containing instanced objects. Used when module is unloaded */
107static GSList *interrupt_data_list = NULL ;
108
109
110#define TRACE_NUMBER 0
111
112typedef struct _InterruptEventData {
113
114 /*Graphical Widgets */
115 GtkWidget * ScrollWindow;
116 GtkListStore *ListStore;
117 GtkWidget *Hbox;
118 GtkWidget *TreeView;
119 GtkTreeSelection *SelectionTree;
120
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;
131 GArray *SumArray;
132
133} InterruptEventData ;
134
135
136/* Function prototypes */
137
138static gboolean interrupt_update_time_window(void * hook_data, void * call_data);
139static GtkWidget *interrupts(Tab *tab);
140static InterruptEventData *system_info(Tab *tab);
141void interrupt_destructor(InterruptEventData *event_viewer_data);
142static void FirstRequest(InterruptEventData *event_data );
143static guint64 get_interrupt_id(LttEvent *e);
144static gboolean trace_header(void *hook_data, void *call_data);
145static gboolean DisplayViewer (void *hook_data, void *call_data);
146static void calcul_duration(LttTime time_exit, guint cpu_id, InterruptEventData *event_data);
147static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit);
148static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data);
149static gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data);
150static gboolean SecondRequest(void *hook_data, void *call_data);
151static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data);
152static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data);
153static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data);
154static void CalculateXi(LttEvent *event, InterruptEventData *event_data);
155static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data);
156static int CalculateStandardDeviation(gint id, InterruptEventData *event_data);
157static void CalculateMaxIRQHandler(LttEvent *event);
158/* Enumeration of the columns */
159enum{
160 CPUID_COLUMN,
161 IRQ_ID_COLUMN,
162 FREQUENCY_COLUMN,
163 DURATION_COLUMN,
164 DURATION_STANDARD_DEV_COLUMN,
165 MAX_IRQ_HANDLER_COLUMN,
166 N_COLUMNS
167};
168
169
170
171/**
172 * init function
173 *
174 *
175 * This is the entry point of the viewer.
176 *
177 */
178static void init() {
179 g_info("interrupts: init()");
180 lttvwindow_register_constructor("interrupts",
181 "/",
182 "Insert Interrupts View",
183 hInterruptsInsert_xpm,
184 "Insert Interrupts View",
185 interrupts);
186
187}
188
189
190/**
191 * Constructor hook
192 *
193 */
194static GtkWidget *interrupts(Tab * tab)
195{
196
197 InterruptEventData* event_data = system_info(tab) ;
198 if(event_data)
199 return event_data->Hbox;
200 else
201 return NULL;
202}
203
204/**
205 * This function initializes the Event Viewer functionnality through the
206 * GTK API.
207 */
208InterruptEventData *system_info(Tab *tab)
209{
210
211 LttTime end;
212 GtkTreeViewColumn *column;
213 GtkCellRenderer *renderer;
214 InterruptEventData* event_viewer_data = g_new(InterruptEventData,1) ;
215
216 event_viewer_data->tab = tab;
217
218 /*Get the current time frame from the main window */
219 event_viewer_data->time_window = lttvwindow_get_time_window(tab);
220
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));
223
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));
226
227 event_viewer_data->SumArray = g_array_new(FALSE, FALSE, sizeof(SumId));
228
229
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*/);
236
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 */
246 );
247
248 event_viewer_data->TreeView = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->ListStore));
249
250 g_object_unref (G_OBJECT (event_viewer_data->ListStore));
251
252 renderer = gtk_cell_renderer_text_new ();
253 column = gtk_tree_view_column_new_with_attributes ("CPUID",
254 renderer,
255 "text", CPUID_COLUMN,
256 NULL);
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);
260
261
262 renderer = gtk_cell_renderer_text_new ();
263 column = gtk_tree_view_column_new_with_attributes ("IrqId",
264 renderer,
265 "text", IRQ_ID_COLUMN,
266 NULL);
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);
270
271 renderer = gtk_cell_renderer_text_new ();
272 column = gtk_tree_view_column_new_with_attributes ("Frequency",
273 renderer,
274 "text", FREQUENCY_COLUMN,
275 NULL);
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);
279
280 renderer = gtk_cell_renderer_text_new ();
281 column = gtk_tree_view_column_new_with_attributes ("Duration (nsec)",
282 renderer,
283 "text", DURATION_COLUMN,
284 NULL);
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);
288
289
290 renderer = gtk_cell_renderer_text_new ();
291 column = gtk_tree_view_column_new_with_attributes ("Duration standard deviation (nsec)",
292 renderer,
293 "text", DURATION_STANDARD_DEV_COLUMN,
294 NULL);
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);
298
299 renderer = gtk_cell_renderer_text_new ();
300 column = gtk_tree_view_column_new_with_attributes ("Max IRQ handler duration (nsec)",
301 renderer,
302 "text", MAX_IRQ_HANDLER_COLUMN,
303 NULL);
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);
307
308
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);
311
312 gtk_container_add (GTK_CONTAINER (event_viewer_data->ScrollWindow), event_viewer_data->TreeView);
313
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);
316
317 gtk_widget_show(event_viewer_data->Hbox);
318 gtk_widget_show(event_viewer_data->TreeView);
319
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,
324 event_viewer_data);
325
326
327 FirstRequest(event_viewer_data );
328 return event_viewer_data;
329}
330
331/**
332 *
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
338 *
339 */
340static void FirstRequest(InterruptEventData *event_data )
341{
342 guint i, k, l, nb_trace;
343
344 LttvTraceHook *hook;
345
346 guint ret;
347
348 LttvTraceState *ts;
349
350 GArray *hooks;
351
352 EventsRequest *events_request;
353
354 LttvTraceHookByFacility *thf;
355
356 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
357
358
359 /* Get the traceset */
360 LttvTraceset *traceset = tsc->ts;
361
362 nb_trace = lttv_traceset_number(traceset);
363
364 /* There are many traces in a traceset. Iteration for each trace. */
365 for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++)
366 {
367 events_request = g_new(EventsRequest, 1);
368
369 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
370
371 hooks = g_array_set_size(hooks, 2);
372
373 event_data->hooks_trace_before = lttv_hooks_new();
374
375 /* Registers a hook function */
376 lttv_hooks_add(event_data->hooks_trace_before, trace_header, event_data, LTTV_PRIO_DEFAULT);
377
378 event_data->hooks_trace_after = lttv_hooks_new();
379
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();
386
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,
392 events_request,
393 &g_array_index(hooks, LttvTraceHook, 0));
394
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,
399 events_request,
400 &g_array_index(hooks, LttvTraceHook, 1));
401
402 g_assert(!ret);
403 /*iterate through the facility list*/
404 for(k = 0 ; k < hooks->len; k++)
405 {
406 hook = &g_array_index(hooks, LttvTraceHook, k);
407 for(l=0; l<hook->fac_list->len; l++)
408 {
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),
411 thf->h,
412 event_data,
413 LTTV_PRIO_DEFAULT);
414
415 }
416 }
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;
428
429 events_request->hooks = hooks;
430
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;
441
442 lttvwindow_events_request(event_data->tab, events_request);
443 }
444
445}
446
447/**
448 * This function is called whenever an irq_entry event occurs.
449 *
450 */
451static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data)
452{
453
454 LttTime event_time;
455 unsigned cpu_id;
456 irq_entry entry;
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);
464
465
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);
470
471 return FALSE;
472}
473
474/**
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.
477 */
478static guint64 get_interrupt_id(LttEvent *e)
479{
480 guint i, num_fields;
481 LttEventType *event_type;
482 LttField *element;
483 LttField *field;
484 guint64 irq_id;
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++)
488 {
489 field = ltt_eventtype_field(event_type, i);
490 irq_id = ltt_event_get_long_unsigned(e,field);
491 }
492 return irq_id;
493
494}
495/**
496 * This function is called whenever an irq_exit event occurs.
497 *
498 */
499gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data)
500{
501 LttTime event_time;
502 unsigned cpu_id;
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);
510
511 calcul_duration( event_time, cpu_id, event_data);
512 CalculateMaxIRQHandler(e);
513 return FALSE;
514}
515
516/**
517 * This function calculates the duration of an interrupt.
518 *
519 */
520static void calcul_duration(LttTime time_exit, guint cpu_id,InterruptEventData *event_data)
521{
522
523 gint i, irq_id;
524 irq_entry *element;
525 LttTime duration;
526 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
527 GArray *FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
528 for(i = 0; i < FirstRequestIrqEntry->len; i++)
529 {
530 element = &g_array_index(FirstRequestIrqEntry,irq_entry,i);
531 if(element->cpu_id == cpu_id)
532 {
533 sum_interrupt_data(element,time_exit, FirstRequestIrqExit);
534 g_array_remove_index(FirstRequestIrqEntry, i);
535 break;
536 }
537 }
538}
539
540static void CalculateMaxIRQHandler(LttEvent *event)
541{
542
543}
544
545/**
546 * This function calculates the total duration of an interrupt.
547 *
548 */
549static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit){
550 Irq irq;
551 Irq *element;
552 guint i;
553 LttTime duration;
554 gboolean notFound = FALSE;
555 memset ((void*)&irq, 0,sizeof(Irq));
556
557 /*first time*/
558 if(FirstRequestIrqExit->len == NO_ITEMS)
559 {
560 irq.cpu_id = e->cpu_id;
561 irq.id = e->id;
562 irq.frequency++;
563 irq.total_duration = ltt_time_sub(time_exit, e->event_time);
564
565 /* test code */
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);
569 /*
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;
573 */
574 /* test code */
575
576 g_array_append_val (FirstRequestIrqExit, irq);
577 }
578 else
579 {
580 for(i = 0; i < FirstRequestIrqExit->len; i++)
581 {
582 element = &g_array_index(FirstRequestIrqExit,Irq,i);
583 if(element->id == e->id)
584 {
585 notFound = TRUE;
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)
590 {
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;
594 }
595 }
596 }
597 if(!notFound)
598 {
599 irq.cpu_id = e->cpu_id;
600 irq.id = e->id;
601 irq.frequency++;
602 irq.total_duration = ltt_time_sub(time_exit, e->event_time);
603
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);
607
608 g_array_append_val (FirstRequestIrqExit, irq);
609 }
610 }
611}
612
613static gboolean SecondRequest(void *hook_data, void *call_data)
614{
615
616 guint i, k, l, nb_trace;
617
618 LttvTraceHook *hook;
619
620 guint ret;
621
622 LttvTraceState *ts;
623
624 GArray *hooks;
625
626 EventsRequest *events_request;
627
628 LttvTraceHookByFacility *thf;
629
630 InterruptEventData *event_data = (InterruptEventData *)hook_data;
631
632 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
633
634 CalculateAverageDurationForEachIrqId(event_data);
635
636 /* Get the traceset */
637 LttvTraceset *traceset = tsc->ts;
638
639 nb_trace = lttv_traceset_number(traceset);
640
641 /* There are many traces in a traceset. Iteration for each trace. */
642 for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++)
643 {
644 events_request = g_new(EventsRequest, 1);
645
646 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
647
648 hooks = g_array_set_size(hooks, 2);
649
650 event_data->hooks_trace_after = lttv_hooks_new();
651
652 /* Registers a hook function */
653 lttv_hooks_add(event_data->hooks_trace_after, DisplayViewer, event_data, LTTV_PRIO_DEFAULT);
654
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();
659
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,
665 events_request,
666 &g_array_index(hooks, LttvTraceHook, 0));
667
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,
672 events_request,
673 &g_array_index(hooks, LttvTraceHook, 1));
674
675 g_assert(!ret);
676 /*iterate through the facility list*/
677 for(k = 0 ; k < hooks->len; k++)
678 {
679 hook = &g_array_index(hooks, LttvTraceHook, k);
680 for(l=0; l<hook->fac_list->len; l++)
681 {
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),
684 thf->h,
685 event_data,
686 LTTV_PRIO_DEFAULT);
687
688 }
689 }
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;
701
702 events_request->hooks = hooks;
703
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;
714
715 lttvwindow_events_request(event_data->tab, events_request);
716 }
717
718
719 return FALSE;
720}
721
722static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data)
723{
724 guint64 real_data;
725 Irq *element;
726 gint i;
727 GArray* FirstRequestIrqExit = event_data->FirstRequestIrqExit;
728 for(i = 0; i < FirstRequestIrqExit->len; i++)
729 {
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);
736 }
737
738}
739
740static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data)
741{
742
743 LttTime event_time;
744 unsigned cpu_id;
745 irq_entry entry;
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);
753
754
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);
759
760 return FALSE;
761}
762
763static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data)
764{
765
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);
770
771 CalculateXi(event, event_data);
772 return FALSE;
773}
774
775static void CalculateXi(LttEvent *event_irq_exit, InterruptEventData *event_data)
776{
777 gint i, irq_id;
778 irq_entry *element;
779 LttTime Xi;
780 LttTime exit_time;
781 unsigned cpu_id;
782
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++)
787 {
788 element = &g_array_index(SecondRequestIrqEntry,irq_entry,i);
789 if(element->cpu_id == cpu_id)
790 {
791
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;
796
797 SumItems(irq_id, Xi,event_data);
798 g_array_remove_index(SecondRequestIrqEntry, i);
799 break;
800 }
801 }
802}
803
804static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data)
805{
806 gint i;
807 guint time_in_ns;
808
809 gint temp;
810 Irq *average;
811 SumId *sumItem;
812 SumId sum;
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;
819
820 for(i = 0; i < FirstRequestIrqExit->len; i++)
821 {
822 average = &g_array_index(FirstRequestIrqExit,Irq,i);
823 if(irq_id == average->id)
824 {
825 temp = time_in_ns - average->average_duration;
826 sum.sumOfDurations = pow (temp , 2);
827 //printf("one : %d\n", sum.sumOfDurations);
828 sum.irqId = irq_id;
829 sum.frequency = average->frequency;
830 if(event_data->SumArray->len == NO_ITEMS)
831 {
832 g_array_append_val (SumArray, sum);
833 }
834 else
835 {
836
837 for(i = 0; i < SumArray->len; i++)
838 {
839 sumItem = &g_array_index(SumArray, SumId, i);
840 if(sumItem->irqId == irq_id)
841 {
842 notFound = TRUE;
843 sumItem->sumOfDurations += sum.sumOfDurations;
844
845 }
846 }
847 if(!notFound)
848 {
849 g_array_append_val (SumArray, sum);
850 }
851
852
853 }
854
855 }
856 }
857}
858
859/**
860 * This function displays the result on the viewer
861 *
862 */
863static gboolean DisplayViewer(void *hook_data, void *call_data)
864{
865
866 guint average;
867 gint i;
868 Irq element;
869 LttTime average_duration;
870 GtkTreeIter iter;
871 guint64 real_data;
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++)
877 {
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;
882
883
884 maxIRQduration = element.max_irq_handler.duration.tv_sec;
885 maxIRQduration *= NANOSECONDS_PER_SECOND;
886 maxIRQduration += element.max_irq_handler.duration.tv_nsec;
887
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,
896 -1);
897
898
899 }
900
901
902
903 if(event_data->FirstRequestIrqExit->len)
904 {
905 g_array_remove_range (event_data->FirstRequestIrqExit,0,event_data->FirstRequestIrqExit->len);
906 }
907
908 if(event_data->FirstRequestIrqEntry->len)
909 {
910 g_array_remove_range (event_data->FirstRequestIrqEntry,0,event_data->FirstRequestIrqEntry->len);
911 }
912
913 if(event_data->SecondRequestIrqEntry->len)
914 {
915 g_array_remove_range (event_data->SecondRequestIrqEntry,0,event_data->SecondRequestIrqEntry->len);
916 }
917
918 if(event_data->SecondRequestIrqExit->len)
919 {
920 g_array_remove_range (event_data->SecondRequestIrqExit,0, event_data->SecondRequestIrqExit->len);
921 }
922
923 if(event_data->SumArray->len)
924 {
925 g_array_remove_range (event_data->SumArray,0, event_data->SumArray->len);
926 }
927
928 return FALSE;
929}
930
931static int CalculateStandardDeviation(gint id, InterruptEventData *event_data)
932{
933 int i;
934 SumId sumId;
935 double inner_component;
936 int deviation = 0;
937 for(i = 0; i < event_data->SumArray->len; i++)
938 {
939 sumId = g_array_index(event_data->SumArray, SumId, i);
940 if(id == sumId.irqId)
941 {
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);
946 return deviation;
947
948 }
949 }
950 return deviation;
951}
952/*
953 * This function is called by the main window
954 * when the time interval needs to be updated.
955 **/
956gboolean interrupt_update_time_window(void * hook_data, void * call_data)
957{
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 );
965 return FALSE;
966}
967
968
969gboolean trace_header(void *hook_data, void *call_data)
970{
971
972 InterruptEventData *event_data = (InterruptEventData *)hook_data;
973 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
974 LttEvent *e;
975 LttTime event_time;
976 return FALSE;
977}
978
979void interrupt_destroy_walk(gpointer data, gpointer user_data)
980{
981 g_info("interrupt_destroy_walk");
982 interrupt_destructor((InterruptEventData*)data);
983
984}
985
986void interrupt_destructor(InterruptEventData *event_viewer_data)
987{
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))
991 {
992 gtk_widget_destroy(event_viewer_data->Hbox);
993 }
994}
995
996/**
997 * plugin's destroy function
998 *
999 * This function releases the memory reserved by the module and unregisters
1000 * everything that has been registered in the gtkTraceSet API.
1001 */
1002static void destroy()
1003{
1004
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);
1009
1010}
1011
1012LTTV_MODULE("interrupts", "interrupts info view", \
1013 "Graphical module to display interrupts performance", \
1014 init, destroy, "lttvwindow")
This page took 0.025702 seconds and 4 git commands to generate.