Modified standard deviation
[lttv.git] / ltt / branches / poly / lttv / modules / gui / interrupts / interrupts.c
CommitLineData
5f5119ee 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 */
dc06b1bc 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 *******************************************************************/
5f5119ee 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>
dc06b1bc 48#include <math.h>
5f5119ee 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
446b4179 69typedef struct
70{
71 LttTime duration;
72 LttTime start_time;
73 LttTime end_time;
74}MaxDuration;
75
5f5119ee 76typedef struct {
77 guint cpu_id;
78 guint id;
79 guint frequency;
80 LttTime total_duration;
dc06b1bc 81 guint average_duration;
446b4179 82 MaxDuration max_irq_handler;
dc06b1bc 83
5f5119ee 84}Irq;
85
86typedef struct {
87 guint id;
88 guint cpu_id;
89 LttTime event_time;
90}irq_entry;
91
dc06b1bc 92
93typedef struct
94{
95 guint irqId;
96 guint frequency;
97 guint64 sumOfDurations;
98
99}SumId;
100
5f5119ee 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
f2ec7aa9 110#define TRACE_NUMBER 0
111
5f5119ee 112typedef struct _InterruptEventData {
113
b3e7b125 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*/
5f5119ee 122 LttvHooks * event_hooks;
123 LttvHooks * hooks_trace_after;
124 LttvHooks * hooks_trace_before;
b3e7b125 125 TimeWindow time_window;
f2ec7aa9 126 LttvHooksById * event_by_id_hooks;
dc06b1bc 127 GArray *FirstRequestIrqExit;
128 GArray *FirstRequestIrqEntry;
129 GArray *SecondRequestIrqEntry;
130 GArray *SecondRequestIrqExit;
131 GArray *SumArray;
132
5f5119ee 133} InterruptEventData ;
134
f2ec7aa9 135
b3e7b125 136/* Function prototypes */
5f5119ee 137
138static gboolean interrupt_update_time_window(void * hook_data, void * call_data);
f2ec7aa9 139static GtkWidget *interrupts(Tab *tab);
140static InterruptEventData *system_info(Tab *tab);
5f5119ee 141void interrupt_destructor(InterruptEventData *event_viewer_data);
dc06b1bc 142static void FirstRequest(InterruptEventData *event_data );
f2ec7aa9 143static guint64 get_interrupt_id(LttEvent *e);
5f5119ee 144static gboolean trace_header(void *hook_data, void *call_data);
dc06b1bc 145static gboolean DisplayViewer (void *hook_data, void *call_data);
5f5119ee 146static void calcul_duration(LttTime time_exit, guint cpu_id, InterruptEventData *event_data);
dc06b1bc 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);
446b4179 157static void CalculateMaxIRQHandler(LttEvent *event);
5f5119ee 158/* Enumeration of the columns */
159enum{
160 CPUID_COLUMN,
161 IRQ_ID_COLUMN,
162 FREQUENCY_COLUMN,
163 DURATION_COLUMN,
dc06b1bc 164 DURATION_STANDARD_DEV_COLUMN,
446b4179 165 MAX_IRQ_HANDLER_COLUMN,
5f5119ee 166 N_COLUMNS
167};
f2ec7aa9 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
5f5119ee 189
5f5119ee 190/**
f2ec7aa9 191 * Constructor hook
5f5119ee 192 *
5f5119ee 193 */
f2ec7aa9 194static GtkWidget *interrupts(Tab * tab)
195{
b3e7b125 196
5f5119ee 197 InterruptEventData* event_data = system_info(tab) ;
198 if(event_data)
b3e7b125 199 return event_data->Hbox;
5f5119ee 200 else
201 return NULL;
202}
203
f2ec7aa9 204/**
205 * This function initializes the Event Viewer functionnality through the
206 * GTK API.
207 */
5f5119ee 208InterruptEventData *system_info(Tab *tab)
209{
dc06b1bc 210
5f5119ee 211 LttTime end;
212 GtkTreeViewColumn *column;
213 GtkCellRenderer *renderer;
214 InterruptEventData* event_viewer_data = g_new(InterruptEventData,1) ;
dc06b1bc 215
5f5119ee 216 event_viewer_data->tab = tab;
f2ec7aa9 217
218 /*Get the current time frame from the main window */
5f5119ee 219 event_viewer_data->time_window = lttvwindow_get_time_window(tab);
dc06b1bc 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
f2ec7aa9 230 /*Create tha main window for the viewer */
b3e7b125 231 event_viewer_data->ScrollWindow = gtk_scrolled_window_new (NULL, NULL);
232 gtk_widget_show (event_viewer_data->ScrollWindow);
5f5119ee 233 gtk_scrolled_window_set_policy(
b3e7b125 234 GTK_SCROLLED_WINDOW(event_viewer_data->ScrollWindow),
5f5119ee 235 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC/*GTK_POLICY_NEVER*/);
236
237 /* Create a model for storing the data list */
b3e7b125 238 event_viewer_data->ListStore = gtk_list_store_new (
5f5119ee 239 N_COLUMNS, /* Total number of columns */
240 G_TYPE_INT, /* CPUID */
241 G_TYPE_INT, /* IRQ_ID */
242 G_TYPE_INT, /* Frequency */
dc06b1bc 243 G_TYPE_UINT64, /* Duration */
446b4179 244 G_TYPE_INT, /* standard deviation */
245 G_TYPE_INT /* Max IRQ handler */
5f5119ee 246 );
247
b3e7b125 248 event_viewer_data->TreeView = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->ListStore));
5f5119ee 249
b3e7b125 250 g_object_unref (G_OBJECT (event_viewer_data->ListStore));
5f5119ee 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);
b3e7b125 259 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 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);
b3e7b125 269 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 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);
b3e7b125 278 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 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);
b3e7b125 287 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 288
dc06b1bc 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);
446b4179 296 gtk_tree_view_column_set_fixed_width (column, 200);
dc06b1bc 297 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
298
446b4179 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);
dc06b1bc 307
308
b3e7b125 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);
5f5119ee 311
b3e7b125 312 gtk_container_add (GTK_CONTAINER (event_viewer_data->ScrollWindow), event_viewer_data->TreeView);
5f5119ee 313
b3e7b125 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);
5f5119ee 316
b3e7b125 317 gtk_widget_show(event_viewer_data->Hbox);
318 gtk_widget_show(event_viewer_data->TreeView);
5f5119ee 319
b3e7b125 320 interrupt_data_list = g_slist_append(interrupt_data_list, event_viewer_data);
f2ec7aa9 321 /* Registration for time notification */
b3e7b125 322 lttvwindow_register_time_window_notify(tab,
323 interrupt_update_time_window,
324 event_viewer_data);
f2ec7aa9 325
326
dc06b1bc 327 FirstRequest(event_viewer_data );
5f5119ee 328 return event_viewer_data;
329}
b3e7b125 330
f2ec7aa9 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 */
dc06b1bc 340static void FirstRequest(InterruptEventData *event_data )
f2ec7aa9 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);
5f5119ee 357
f2ec7aa9 358
359 /* Get the traceset */
360 LttvTraceset *traceset = tsc->ts;
5f5119ee 361
f2ec7aa9 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);
b3e7b125 372
f2ec7aa9 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();
dc06b1bc 379
380 /* Registers a hook function */
381 lttv_hooks_add(event_data->hooks_trace_after, SecondRequest, event_data, LTTV_PRIO_DEFAULT);
f2ec7aa9 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();
b3e7b125 386
f2ec7aa9 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,
dc06b1bc 391 FirstRequestIrqEntryCallback,
f2ec7aa9 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,
dc06b1bc 398 FirstRequestIrqExitCallback,
f2ec7aa9 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;
231a6432 437 events_request->after_chunk_trace = NULL;
f2ec7aa9 438 events_request->after_chunk_traceset = NULL;
231a6432 439 events_request->before_request = NULL;
f2ec7aa9 440 events_request->after_request = event_data->hooks_trace_after;
441
442 lttvwindow_events_request(event_data->tab, events_request);
443 }
444
b3e7b125 445}
5f5119ee 446
f2ec7aa9 447/**
448 * This function is called whenever an irq_entry event occurs.
449 *
450 */
dc06b1bc 451static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data)
f2ec7aa9 452{
453
b3e7b125 454 LttTime event_time;
b3e7b125 455 unsigned cpu_id;
456 irq_entry entry;
b3e7b125 457 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
458 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
f2ec7aa9 459 InterruptEventData *event_data = (InterruptEventData *)hook_data;
dc06b1bc 460 GArray* FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
f2ec7aa9 461 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
b3e7b125 462 event_time = ltt_event_time(e);
b3e7b125 463 cpu_id = ltt_event_cpu_id(e);
f2ec7aa9 464
231a6432 465
466 entry.id =get_interrupt_id(e);
467 entry.cpu_id = cpu_id;
468 entry.event_time = event_time;
dc06b1bc 469 g_array_append_val (FirstRequestIrqEntry, entry);
231a6432 470
f2ec7aa9 471 return FALSE;
5f5119ee 472}
473
f2ec7aa9 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)
5f5119ee 479{
f2ec7aa9 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);
5f5119ee 491 }
492 return irq_id;
5f5119ee 493
f2ec7aa9 494}
495/**
496 * This function is called whenever an irq_exit event occurs.
497 *
498 */
dc06b1bc 499gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data)
f2ec7aa9 500{
501 LttTime event_time;
502 unsigned cpu_id;
5f5119ee 503 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
f2ec7aa9 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);
231a6432 510
511 calcul_duration( event_time, cpu_id, event_data);
446b4179 512 CalculateMaxIRQHandler(e);
231a6432 513 return FALSE;
5f5119ee 514}
515
f2ec7aa9 516/**
517 * This function calculates the duration of an interrupt.
518 *
519 */
dc06b1bc 520static void calcul_duration(LttTime time_exit, guint cpu_id,InterruptEventData *event_data)
521{
5f5119ee 522
f2ec7aa9 523 gint i, irq_id;
524 irq_entry *element;
525 LttTime duration;
dc06b1bc 526 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
527 GArray *FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
528 for(i = 0; i < FirstRequestIrqEntry->len; i++)
231a6432 529 {
dc06b1bc 530 element = &g_array_index(FirstRequestIrqEntry,irq_entry,i);
231a6432 531 if(element->cpu_id == cpu_id)
532 {
dc06b1bc 533 sum_interrupt_data(element,time_exit, FirstRequestIrqExit);
534 g_array_remove_index(FirstRequestIrqEntry, i);
f2ec7aa9 535 break;
536 }
537 }
5f5119ee 538}
dc06b1bc 539
446b4179 540static void CalculateMaxIRQHandler(LttEvent *event)
dc06b1bc 541{
542
543}
544
f2ec7aa9 545/**
546 * This function calculates the total duration of an interrupt.
547 *
548 */
dc06b1bc 549static void sum_interrupt_data(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit){
5f5119ee 550 Irq irq;
551 Irq *element;
552 guint i;
553 LttTime duration;
554 gboolean notFound = FALSE;
555 memset ((void*)&irq, 0,sizeof(Irq));
556
231a6432 557 /*first time*/
dc06b1bc 558 if(FirstRequestIrqExit->len == NO_ITEMS)
231a6432 559 {
5f5119ee 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);
446b4179 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
dc06b1bc 576 g_array_append_val (FirstRequestIrqExit, irq);
5f5119ee 577 }
231a6432 578 else
579 {
dc06b1bc 580 for(i = 0; i < FirstRequestIrqExit->len; i++)
231a6432 581 {
dc06b1bc 582 element = &g_array_index(FirstRequestIrqExit,Irq,i);
583 if(element->id == e->id)
584 {
5f5119ee 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++;
446b4179 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 }
5f5119ee 595 }
596 }
231a6432 597 if(!notFound)
598 {
5f5119ee 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);
446b4179 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
dc06b1bc 608 g_array_append_val (FirstRequestIrqExit, irq);
5f5119ee 609 }
610 }
611}
231a6432 612
dc06b1bc 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
f2ec7aa9 859/**
860 * This function displays the result on the viewer
861 *
862 */
dc06b1bc 863static gboolean DisplayViewer(void *hook_data, void *call_data)
864{
5f5119ee 865
dc06b1bc 866 guint average;
f2ec7aa9 867 gint i;
868 Irq element;
869 LttTime average_duration;
870 GtkTreeIter iter;
871 guint64 real_data;
446b4179 872 guint maxIRQduration;
f2ec7aa9 873 InterruptEventData *event_data = (InterruptEventData *)hook_data;
dc06b1bc 874 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
f2ec7aa9 875 gtk_list_store_clear(event_data->ListStore);
dc06b1bc 876 for(i = 0; i < FirstRequestIrqExit->len; i++)
231a6432 877 {
dc06b1bc 878 element = g_array_index(FirstRequestIrqExit,Irq,i);
f2ec7aa9 879 real_data = element.total_duration.tv_sec;
880 real_data *= NANOSECONDS_PER_SECOND;
881 real_data += element.total_duration.tv_nsec;
446b4179 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
f2ec7aa9 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,
dc06b1bc 894 DURATION_STANDARD_DEV_COLUMN, CalculateStandardDeviation(element.id, event_data),
446b4179 895 MAX_IRQ_HANDLER_COLUMN, maxIRQduration,
f2ec7aa9 896 -1);
dc06b1bc 897
446b4179 898
f2ec7aa9 899 }
dc06b1bc 900
231a6432 901
dc06b1bc 902
903 if(event_data->FirstRequestIrqExit->len)
231a6432 904 {
dc06b1bc 905 g_array_remove_range (event_data->FirstRequestIrqExit,0,event_data->FirstRequestIrqExit->len);
231a6432 906 }
907
dc06b1bc 908 if(event_data->FirstRequestIrqEntry->len)
231a6432 909 {
dc06b1bc 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 }
231a6432 917
dc06b1bc 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);
231a6432 926 }
dc06b1bc 927
f2ec7aa9 928 return FALSE;
5f5119ee 929}
dc06b1bc 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}
f2ec7aa9 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{
5f5119ee 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);
dc06b1bc 964 FirstRequest(event_data );
f2ec7aa9 965 return FALSE;
5f5119ee 966}
967
f2ec7aa9 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;
f2ec7aa9 974 LttEvent *e;
975 LttTime event_time;
976 return FALSE;
5f5119ee 977}
978
f2ec7aa9 979void interrupt_destroy_walk(gpointer data, gpointer user_data)
980{
5f5119ee 981 g_info("interrupt_destroy_walk");
982 interrupt_destructor((InterruptEventData*)data);
983
984}
985
f2ec7aa9 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
5f5119ee 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 */
dc06b1bc 1002static void destroy()
1003{
1004
5f5119ee 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.069363 seconds and 4 git commands to generate.