update compat
[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 /******************************************************************
e5258c09 20
21 The standard deviation calculation is based on:
dc06b1bc 22 http://en.wikipedia.org/wiki/Standard_deviation
23
e5258c09 24 Standard_deviation = sqrt(1/N Sum ((xi -Xa)^2))
dc06b1bc 25
e5258c09 26 To compute the standard deviation, we need to make EventRequests to LTTV. In
27 the first EventRequest, we compute the average duration (Xa) and the
28 frequency (N) of each IrqID. We store the information calculated in the first
29 EventRequest in an array called FirstRequestIrqExit.
30 In the second EventRequest, we compute the Sum ((xi -Xa)^2) and store this information
6b0817c2 31 in a array called SumArray. The function CalculateDurationStandardDeviation() uses FirstRequestIrqExit
e5258c09 32 and SumArray arrays to calculate the standard deviation.
33
6b0817c2 34
35
36CPUID: processor ID
37
38IrqId: IRQ ID
39
40Frequency (Hz): the number of interruptions per second (Hz)
41
42Total Duration (nsec): the sum of each interrupt duration in nsec
43
44Duration standard deviation (nsec): taken from http://en.wikipedia.org/wiki/Standard_deviation
45Duration Standard_deviation = sqrt(1/N Sum ((xi -Xa)^2)) where
46N: number of interrupts
47xi: duration of an interrupt (nsec)
48Xa: average duration (nsec)
49
50Max IRQ handler duration (nsec) [time interval]: the longest IRQ handler duration in nsec.
51
52Average period (nsec): 1/frequency
53
54
55Period Standard_deviation = sqrt(1/N Sum ((xi -Xa)^2)) where
56N: number of interrupts
fc77fe59 57xi: duration of an interrupt
6b0817c2 58Xa: 1/frequency
59
dc06b1bc 60 *******************************************************************/
5f5119ee 61
62
63
64#include <math.h>
65#include <glib.h>
66#include <gtk/gtk.h>
67#include <gdk/gdk.h>
68#include <stdio.h>
69#include <stdlib.h>
dc06b1bc 70#include <math.h>
5f5119ee 71#include <string.h>
72#include <ltt/ltt.h>
73#include <ltt/event.h>
74#include <ltt/type.h>
75#include <ltt/trace.h>
76#include <ltt/facility.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 <ltt/time.h>
84
85#include "hInterruptsInsert.xpm"
86
87#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
88#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
89#define NO_ITEMS 0
90
446b4179 91typedef struct
92{
93 LttTime duration;
94 LttTime start_time;
95 LttTime end_time;
96}MaxDuration;
97
5f5119ee 98typedef struct {
99 guint cpu_id;
100 guint id;
101 guint frequency;
102 LttTime total_duration;
dc06b1bc 103 guint average_duration;
446b4179 104 MaxDuration max_irq_handler;
dc06b1bc 105
5f5119ee 106}Irq;
107
108typedef struct {
109 guint id;
110 guint cpu_id;
111 LttTime event_time;
112}irq_entry;
113
dc06b1bc 114
115typedef struct
116{
117 guint irqId;
118 guint frequency;
119 guint64 sumOfDurations;
6b0817c2 120 guint64 sumOfPeriods;
dc06b1bc 121
122}SumId;
123
5f5119ee 124enum type_t {
125 IRQ_ENTRY,
126 IRQ_EXIT
127};
128
129/** Array containing instanced objects. Used when module is unloaded */
130static GSList *interrupt_data_list = NULL ;
131
132
f2ec7aa9 133#define TRACE_NUMBER 0
134
5f5119ee 135typedef struct _InterruptEventData {
136
b3e7b125 137 /*Graphical Widgets */
138 GtkWidget * ScrollWindow;
139 GtkListStore *ListStore;
140 GtkWidget *Hbox;
141 GtkWidget *TreeView;
142 GtkTreeSelection *SelectionTree;
143
144 Tab * tab; /* tab that contains this plug-in*/
5f5119ee 145 LttvHooks * event_hooks;
146 LttvHooks * hooks_trace_after;
147 LttvHooks * hooks_trace_before;
b3e7b125 148 TimeWindow time_window;
f2ec7aa9 149 LttvHooksById * event_by_id_hooks;
dc06b1bc 150 GArray *FirstRequestIrqExit;
151 GArray *FirstRequestIrqEntry;
152 GArray *SecondRequestIrqEntry;
153 GArray *SecondRequestIrqExit;
154 GArray *SumArray;
155
5f5119ee 156} InterruptEventData ;
157
f2ec7aa9 158
b3e7b125 159/* Function prototypes */
5f5119ee 160
161static gboolean interrupt_update_time_window(void * hook_data, void * call_data);
f2ec7aa9 162static GtkWidget *interrupts(Tab *tab);
163static InterruptEventData *system_info(Tab *tab);
5f5119ee 164void interrupt_destructor(InterruptEventData *event_viewer_data);
dc06b1bc 165static void FirstRequest(InterruptEventData *event_data );
f2ec7aa9 166static guint64 get_interrupt_id(LttEvent *e);
5f5119ee 167static gboolean trace_header(void *hook_data, void *call_data);
dc06b1bc 168static gboolean DisplayViewer (void *hook_data, void *call_data);
e5258c09 169static void CalculateData(LttTime time_exit, guint cpu_id, InterruptEventData *event_data);
170static void TotalDurationMaxIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit);
dc06b1bc 171static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data);
172static gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data);
173static gboolean SecondRequest(void *hook_data, void *call_data);
174static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data);
175static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data);
176static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data);
177static void CalculateXi(LttEvent *event, InterruptEventData *event_data);
178static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data);
6b0817c2 179static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event_data);
180static int CalculatePeriodStandardDeviation(gint id, InterruptEventData *event_data);
25c6412d 181static int FrequencyInHZ(gint frequency, TimeWindow time_window);
6b0817c2 182static guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ);
fc77fe59 183static void InterruptFree(InterruptEventData *event_viewer_data);
5f5119ee 184/* Enumeration of the columns */
185enum{
186 CPUID_COLUMN,
187 IRQ_ID_COLUMN,
188 FREQUENCY_COLUMN,
189 DURATION_COLUMN,
dc06b1bc 190 DURATION_STANDARD_DEV_COLUMN,
446b4179 191 MAX_IRQ_HANDLER_COLUMN,
52948a62 192 AVERAGE_PERIOD,
193 PERIOD_STANDARD_DEV_COLUMN,
5f5119ee 194 N_COLUMNS
195};
f2ec7aa9 196
197
198
199/**
200 * init function
201 *
202 *
203 * This is the entry point of the viewer.
204 *
205 */
206static void init() {
207 g_info("interrupts: init()");
208 lttvwindow_register_constructor("interrupts",
209 "/",
210 "Insert Interrupts View",
211 hInterruptsInsert_xpm,
212 "Insert Interrupts View",
213 interrupts);
214
215}
216
5f5119ee 217
5f5119ee 218/**
f2ec7aa9 219 * Constructor hook
5f5119ee 220 *
5f5119ee 221 */
f2ec7aa9 222static GtkWidget *interrupts(Tab * tab)
223{
b3e7b125 224
5f5119ee 225 InterruptEventData* event_data = system_info(tab) ;
226 if(event_data)
b3e7b125 227 return event_data->Hbox;
5f5119ee 228 else
229 return NULL;
230}
231
f2ec7aa9 232/**
233 * This function initializes the Event Viewer functionnality through the
234 * GTK API.
235 */
5f5119ee 236InterruptEventData *system_info(Tab *tab)
237{
dc06b1bc 238
5f5119ee 239 LttTime end;
240 GtkTreeViewColumn *column;
241 GtkCellRenderer *renderer;
242 InterruptEventData* event_viewer_data = g_new(InterruptEventData,1) ;
dc06b1bc 243
5f5119ee 244 event_viewer_data->tab = tab;
f2ec7aa9 245
246 /*Get the current time frame from the main window */
5f5119ee 247 event_viewer_data->time_window = lttvwindow_get_time_window(tab);
dc06b1bc 248
249 event_viewer_data->FirstRequestIrqExit = g_array_new(FALSE, FALSE, sizeof(Irq));
250 event_viewer_data->FirstRequestIrqEntry = g_array_new(FALSE, FALSE, sizeof(irq_entry));
251
252 event_viewer_data->SecondRequestIrqEntry = g_array_new(FALSE, FALSE, sizeof(irq_entry));
253 event_viewer_data->SecondRequestIrqExit = g_array_new(FALSE, FALSE, sizeof(Irq));
254
255 event_viewer_data->SumArray = g_array_new(FALSE, FALSE, sizeof(SumId));
256
257
f2ec7aa9 258 /*Create tha main window for the viewer */
b3e7b125 259 event_viewer_data->ScrollWindow = gtk_scrolled_window_new (NULL, NULL);
260 gtk_widget_show (event_viewer_data->ScrollWindow);
5f5119ee 261 gtk_scrolled_window_set_policy(
b3e7b125 262 GTK_SCROLLED_WINDOW(event_viewer_data->ScrollWindow),
5f5119ee 263 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC/*GTK_POLICY_NEVER*/);
264
265 /* Create a model for storing the data list */
b3e7b125 266 event_viewer_data->ListStore = gtk_list_store_new (
5f5119ee 267 N_COLUMNS, /* Total number of columns */
268 G_TYPE_INT, /* CPUID */
269 G_TYPE_INT, /* IRQ_ID */
270 G_TYPE_INT, /* Frequency */
dc06b1bc 271 G_TYPE_UINT64, /* Duration */
446b4179 272 G_TYPE_INT, /* standard deviation */
52948a62 273 G_TYPE_STRING, /* Max IRQ handler */
6b0817c2 274 G_TYPE_INT, /* Average period */
275 G_TYPE_INT /* period standard deviation */
5f5119ee 276 );
277
b3e7b125 278 event_viewer_data->TreeView = gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->ListStore));
5f5119ee 279
b3e7b125 280 g_object_unref (G_OBJECT (event_viewer_data->ListStore));
5f5119ee 281
282 renderer = gtk_cell_renderer_text_new ();
283 column = gtk_tree_view_column_new_with_attributes ("CPUID",
284 renderer,
285 "text", CPUID_COLUMN,
286 NULL);
287 gtk_tree_view_column_set_alignment (column, 0.0);
288 gtk_tree_view_column_set_fixed_width (column, 45);
b3e7b125 289 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 290
291
292 renderer = gtk_cell_renderer_text_new ();
293 column = gtk_tree_view_column_new_with_attributes ("IrqId",
294 renderer,
295 "text", IRQ_ID_COLUMN,
296 NULL);
297 gtk_tree_view_column_set_alignment (column, 0.0);
298 gtk_tree_view_column_set_fixed_width (column, 220);
b3e7b125 299 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 300
301 renderer = gtk_cell_renderer_text_new ();
52948a62 302 column = gtk_tree_view_column_new_with_attributes ("Frequency (Hz)",
5f5119ee 303 renderer,
304 "text", FREQUENCY_COLUMN,
305 NULL);
306 gtk_tree_view_column_set_alignment (column, 1.0);
307 gtk_tree_view_column_set_fixed_width (column, 220);
b3e7b125 308 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 309
310 renderer = gtk_cell_renderer_text_new ();
25c6412d 311 column = gtk_tree_view_column_new_with_attributes ("Total Duration (nsec)",
5f5119ee 312 renderer,
313 "text", DURATION_COLUMN,
314 NULL);
315 gtk_tree_view_column_set_alignment (column, 0.0);
316 gtk_tree_view_column_set_fixed_width (column, 145);
b3e7b125 317 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
5f5119ee 318
dc06b1bc 319
320 renderer = gtk_cell_renderer_text_new ();
321 column = gtk_tree_view_column_new_with_attributes ("Duration standard deviation (nsec)",
322 renderer,
323 "text", DURATION_STANDARD_DEV_COLUMN,
324 NULL);
325 gtk_tree_view_column_set_alignment (column, 0.0);
446b4179 326 gtk_tree_view_column_set_fixed_width (column, 200);
dc06b1bc 327 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
328
446b4179 329 renderer = gtk_cell_renderer_text_new ();
25c6412d 330 column = gtk_tree_view_column_new_with_attributes ("Max IRQ handler duration (nsec) [time interval]",
446b4179 331 renderer,
332 "text", MAX_IRQ_HANDLER_COLUMN,
333 NULL);
334 gtk_tree_view_column_set_alignment (column, 0.0);
335 gtk_tree_view_column_set_fixed_width (column, 250);
336 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
dc06b1bc 337
52948a62 338 renderer = gtk_cell_renderer_text_new ();
339 column = gtk_tree_view_column_new_with_attributes (" Average period (nsec)",
340 renderer,
341 "text", AVERAGE_PERIOD,
342 NULL);
343 gtk_tree_view_column_set_alignment (column, 0.0);
344 gtk_tree_view_column_set_fixed_width (column, 200);
345 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
346
347 renderer = gtk_cell_renderer_text_new ();
348 column = gtk_tree_view_column_new_with_attributes ("Period standard deviation (nsec)",
349 renderer,
350 "text", PERIOD_STANDARD_DEV_COLUMN,
351 NULL);
352 gtk_tree_view_column_set_alignment (column, 0.0);
353 gtk_tree_view_column_set_fixed_width (column, 200);
354 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->TreeView), column);
355
356
dc06b1bc 357
b3e7b125 358 event_viewer_data->SelectionTree = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data->TreeView));
359 gtk_tree_selection_set_mode (event_viewer_data->SelectionTree, GTK_SELECTION_SINGLE);
5f5119ee 360
b3e7b125 361 gtk_container_add (GTK_CONTAINER (event_viewer_data->ScrollWindow), event_viewer_data->TreeView);
5f5119ee 362
b3e7b125 363 event_viewer_data->Hbox = gtk_hbox_new(0, 0);
364 gtk_box_pack_start(GTK_BOX(event_viewer_data->Hbox), event_viewer_data->ScrollWindow, TRUE, TRUE, 0);
5f5119ee 365
b3e7b125 366 gtk_widget_show(event_viewer_data->Hbox);
367 gtk_widget_show(event_viewer_data->TreeView);
5f5119ee 368
b3e7b125 369 interrupt_data_list = g_slist_append(interrupt_data_list, event_viewer_data);
f2ec7aa9 370 /* Registration for time notification */
b3e7b125 371 lttvwindow_register_time_window_notify(tab,
372 interrupt_update_time_window,
373 event_viewer_data);
f2ec7aa9 374
fc77fe59 375 g_object_set_data_full(G_OBJECT(event_viewer_data->Hbox),
376 "event_data",
377 event_viewer_data,
378 (GDestroyNotify) InterruptFree);
f2ec7aa9 379
dc06b1bc 380 FirstRequest(event_viewer_data );
5f5119ee 381 return event_viewer_data;
382}
b3e7b125 383
fc77fe59 384
f2ec7aa9 385/**
386 *
387 * For each trace in the traceset, this function:
388 * - registers a callback function to each hook
389 * - calls lttv_trace_find_hook() registers a hook function to event_by_id_hooks
390 * - calls lttvwindow_events_request() to request data in a specific
391 * time interval to the main window
392 *
393 */
dc06b1bc 394static void FirstRequest(InterruptEventData *event_data )
f2ec7aa9 395{
396 guint i, k, l, nb_trace;
397
398 LttvTraceHook *hook;
399
400 guint ret;
401
402 LttvTraceState *ts;
403
404 GArray *hooks;
405
406 EventsRequest *events_request;
407
408 LttvTraceHookByFacility *thf;
409
410 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
5f5119ee 411
f2ec7aa9 412
413 /* Get the traceset */
414 LttvTraceset *traceset = tsc->ts;
5f5119ee 415
f2ec7aa9 416 nb_trace = lttv_traceset_number(traceset);
417
418 /* There are many traces in a traceset. Iteration for each trace. */
419 for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++)
420 {
421 events_request = g_new(EventsRequest, 1);
422
423 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
424
425 hooks = g_array_set_size(hooks, 2);
b3e7b125 426
f2ec7aa9 427 event_data->hooks_trace_before = lttv_hooks_new();
428
429 /* Registers a hook function */
430 lttv_hooks_add(event_data->hooks_trace_before, trace_header, event_data, LTTV_PRIO_DEFAULT);
431
432 event_data->hooks_trace_after = lttv_hooks_new();
dc06b1bc 433
434 /* Registers a hook function */
435 lttv_hooks_add(event_data->hooks_trace_after, SecondRequest, event_data, LTTV_PRIO_DEFAULT);
f2ec7aa9 436 /* Get a trace state */
437 ts = (LttvTraceState *)tsc->traces[i];
438 /* Create event_by_Id hooks */
439 event_data->event_by_id_hooks = lttv_hooks_by_id_new();
b3e7b125 440
f2ec7aa9 441 /*Register event_by_id_hooks with a callback function*/
442 ret = lttv_trace_find_hook(ts->parent.t,
443 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
444 LTT_FIELD_IRQ_ID, 0, 0,
dc06b1bc 445 FirstRequestIrqEntryCallback,
f2ec7aa9 446 events_request,
447 &g_array_index(hooks, LttvTraceHook, 0));
448
449 ret = lttv_trace_find_hook(ts->parent.t,
450 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
451 LTT_FIELD_IRQ_ID, 0, 0,
dc06b1bc 452 FirstRequestIrqExitCallback,
f2ec7aa9 453 events_request,
454 &g_array_index(hooks, LttvTraceHook, 1));
455
456 g_assert(!ret);
457 /*iterate through the facility list*/
458 for(k = 0 ; k < hooks->len; k++)
459 {
460 hook = &g_array_index(hooks, LttvTraceHook, k);
461 for(l=0; l<hook->fac_list->len; l++)
462 {
463 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
464 lttv_hooks_add(lttv_hooks_by_id_find(event_data->event_by_id_hooks, thf->id),
465 thf->h,
466 event_data,
467 LTTV_PRIO_DEFAULT);
468
469 }
470 }
471 /* Initalize the EventsRequest structure */
472 events_request->owner = event_data;
473 events_request->viewer_data = event_data;
474 events_request->servicing = FALSE;
475 events_request->start_time = event_data->time_window.start_time;
476 events_request->start_position = NULL;
477 events_request->stop_flag = FALSE;
478 events_request->end_time = event_data->time_window.end_time;
479 events_request->num_events = G_MAXUINT;
480 events_request->end_position = NULL;
481 events_request->trace = i;
482
483 events_request->hooks = hooks;
484
485 events_request->before_chunk_traceset = NULL;
486 events_request->before_chunk_trace = event_data->hooks_trace_before;
487 events_request->before_chunk_tracefile= NULL;
488 events_request->event = NULL;
489 events_request->event_by_id = event_data->event_by_id_hooks;
490 events_request->after_chunk_tracefile = NULL;
231a6432 491 events_request->after_chunk_trace = NULL;
f2ec7aa9 492 events_request->after_chunk_traceset = NULL;
231a6432 493 events_request->before_request = NULL;
f2ec7aa9 494 events_request->after_request = event_data->hooks_trace_after;
495
496 lttvwindow_events_request(event_data->tab, events_request);
497 }
498
b3e7b125 499}
5f5119ee 500
f2ec7aa9 501/**
502 * This function is called whenever an irq_entry event occurs.
503 *
504 */
dc06b1bc 505static gboolean FirstRequestIrqEntryCallback(void *hook_data, void *call_data)
f2ec7aa9 506{
507
b3e7b125 508 LttTime event_time;
b3e7b125 509 unsigned cpu_id;
510 irq_entry entry;
b3e7b125 511 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
512 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
f2ec7aa9 513 InterruptEventData *event_data = (InterruptEventData *)hook_data;
dc06b1bc 514 GArray* FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
f2ec7aa9 515 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
b3e7b125 516 event_time = ltt_event_time(e);
b3e7b125 517 cpu_id = ltt_event_cpu_id(e);
f2ec7aa9 518
231a6432 519
520 entry.id =get_interrupt_id(e);
521 entry.cpu_id = cpu_id;
522 entry.event_time = event_time;
dc06b1bc 523 g_array_append_val (FirstRequestIrqEntry, entry);
231a6432 524
f2ec7aa9 525 return FALSE;
5f5119ee 526}
527
f2ec7aa9 528/**
529 * This function gets the id of the interrupt. The id is stored in a dynamic structure.
530 * Refer to the print.c file for howto extract data from a dynamic structure.
531 */
532static guint64 get_interrupt_id(LttEvent *e)
5f5119ee 533{
f2ec7aa9 534 guint i, num_fields;
535 LttEventType *event_type;
536 LttField *element;
537 LttField *field;
538 guint64 irq_id;
539 event_type = ltt_event_eventtype(e);
540 num_fields = ltt_eventtype_num_fields(event_type);
541 for(i = 0 ; i < num_fields-1 ; i++)
542 {
543 field = ltt_eventtype_field(event_type, i);
544 irq_id = ltt_event_get_long_unsigned(e,field);
5f5119ee 545 }
546 return irq_id;
5f5119ee 547
f2ec7aa9 548}
549/**
550 * This function is called whenever an irq_exit event occurs.
551 *
552 */
dc06b1bc 553gboolean FirstRequestIrqExitCallback(void *hook_data, void *call_data)
f2ec7aa9 554{
555 LttTime event_time;
556 unsigned cpu_id;
5f5119ee 557 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
f2ec7aa9 558 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
559 InterruptEventData *event_data = (InterruptEventData *)hook_data;
560 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
561 LttEventType *type = ltt_event_eventtype(e);
562 event_time = ltt_event_time(e);
563 cpu_id = ltt_event_cpu_id(e);
231a6432 564
e5258c09 565 CalculateData( event_time, cpu_id, event_data);
566
231a6432 567 return FALSE;
5f5119ee 568}
569
f2ec7aa9 570/**
571 * This function calculates the duration of an interrupt.
572 *
573 */
e5258c09 574static void CalculateData(LttTime time_exit, guint cpu_id,InterruptEventData *event_data)
dc06b1bc 575{
5f5119ee 576
f2ec7aa9 577 gint i, irq_id;
578 irq_entry *element;
579 LttTime duration;
dc06b1bc 580 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
581 GArray *FirstRequestIrqEntry = event_data->FirstRequestIrqEntry;
582 for(i = 0; i < FirstRequestIrqEntry->len; i++)
231a6432 583 {
dc06b1bc 584 element = &g_array_index(FirstRequestIrqEntry,irq_entry,i);
231a6432 585 if(element->cpu_id == cpu_id)
586 {
e5258c09 587 TotalDurationMaxIrqDuration(element,time_exit, FirstRequestIrqExit);
dc06b1bc 588 g_array_remove_index(FirstRequestIrqEntry, i);
f2ec7aa9 589 break;
590 }
591 }
e5258c09 592}
dc06b1bc 593
f2ec7aa9 594/**
e5258c09 595 * This function calculates the total duration of an interrupt and the longest Irq handler.
f2ec7aa9 596 *
597 */
e5258c09 598static void TotalDurationMaxIrqDuration(irq_entry *e, LttTime time_exit, GArray *FirstRequestIrqExit){
5f5119ee 599 Irq irq;
600 Irq *element;
601 guint i;
602 LttTime duration;
603 gboolean notFound = FALSE;
604 memset ((void*)&irq, 0,sizeof(Irq));
605
231a6432 606 /*first time*/
dc06b1bc 607 if(FirstRequestIrqExit->len == NO_ITEMS)
231a6432 608 {
5f5119ee 609 irq.cpu_id = e->cpu_id;
610 irq.id = e->id;
611 irq.frequency++;
612 irq.total_duration = ltt_time_sub(time_exit, e->event_time);
e5258c09 613
446b4179 614 irq.max_irq_handler.start_time = e->event_time;
615 irq.max_irq_handler.end_time = time_exit;
616 irq.max_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
e5258c09 617
dc06b1bc 618 g_array_append_val (FirstRequestIrqExit, irq);
5f5119ee 619 }
231a6432 620 else
621 {
dc06b1bc 622 for(i = 0; i < FirstRequestIrqExit->len; i++)
231a6432 623 {
dc06b1bc 624 element = &g_array_index(FirstRequestIrqExit,Irq,i);
625 if(element->id == e->id)
626 {
5f5119ee 627 notFound = TRUE;
628 duration = ltt_time_sub(time_exit, e->event_time);
629 element->total_duration = ltt_time_add(element->total_duration, duration);
630 element->frequency++;
446b4179 631 if(ltt_time_compare(duration,element->max_irq_handler.duration) > 0)
632 {
633 element->max_irq_handler.duration = duration;
634 element->max_irq_handler.start_time = e->event_time;
635 element->max_irq_handler.end_time = time_exit;
636 }
5f5119ee 637 }
638 }
231a6432 639 if(!notFound)
640 {
5f5119ee 641 irq.cpu_id = e->cpu_id;
642 irq.id = e->id;
643 irq.frequency++;
644 irq.total_duration = ltt_time_sub(time_exit, e->event_time);
446b4179 645
646 irq.max_irq_handler.start_time = e->event_time;
647 irq.max_irq_handler.end_time = time_exit;
648 irq.max_irq_handler.duration = ltt_time_sub(time_exit, e->event_time);
649
dc06b1bc 650 g_array_append_val (FirstRequestIrqExit, irq);
5f5119ee 651 }
652 }
653}
231a6432 654
e5258c09 655/**
656 * This function passes the second EventsRequest to LTTV
657 *
658 */
dc06b1bc 659static gboolean SecondRequest(void *hook_data, void *call_data)
660{
661
662 guint i, k, l, nb_trace;
663
664 LttvTraceHook *hook;
665
666 guint ret;
667
668 LttvTraceState *ts;
669
670 GArray *hooks;
671
672 EventsRequest *events_request;
673
674 LttvTraceHookByFacility *thf;
675
676 InterruptEventData *event_data = (InterruptEventData *)hook_data;
677
678 LttvTracesetContext *tsc = lttvwindow_get_traceset_context(event_data->tab);
679
680 CalculateAverageDurationForEachIrqId(event_data);
681
682 /* Get the traceset */
683 LttvTraceset *traceset = tsc->ts;
684
685 nb_trace = lttv_traceset_number(traceset);
686
687 /* There are many traces in a traceset. Iteration for each trace. */
688 for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++)
689 {
690 events_request = g_new(EventsRequest, 1);
691
692 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
693
694 hooks = g_array_set_size(hooks, 2);
695
696 event_data->hooks_trace_after = lttv_hooks_new();
697
698 /* Registers a hook function */
699 lttv_hooks_add(event_data->hooks_trace_after, DisplayViewer, event_data, LTTV_PRIO_DEFAULT);
700
701 /* Get a trace state */
702 ts = (LttvTraceState *)tsc->traces[i];
703 /* Create event_by_Id hooks */
704 event_data->event_by_id_hooks = lttv_hooks_by_id_new();
705
706 /*Register event_by_id_hooks with a callback function*/
707 ret = lttv_trace_find_hook(ts->parent.t,
708 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
709 LTT_FIELD_IRQ_ID, 0, 0,
710 SecondRequestIrqEntryCallback,
711 events_request,
712 &g_array_index(hooks, LttvTraceHook, 0));
713
714 ret = lttv_trace_find_hook(ts->parent.t,
715 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
716 LTT_FIELD_IRQ_ID, 0, 0,
717 SecondRequestIrqExitCallback,
718 events_request,
719 &g_array_index(hooks, LttvTraceHook, 1));
720
721 g_assert(!ret);
e5258c09 722
723 /* iterate through the facility list */
dc06b1bc 724 for(k = 0 ; k < hooks->len; k++)
725 {
726 hook = &g_array_index(hooks, LttvTraceHook, k);
727 for(l=0; l<hook->fac_list->len; l++)
728 {
729 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
730 lttv_hooks_add(lttv_hooks_by_id_find(event_data->event_by_id_hooks, thf->id),
731 thf->h,
732 event_data,
733 LTTV_PRIO_DEFAULT);
734
735 }
736 }
737 /* Initalize the EventsRequest structure */
738 events_request->owner = event_data;
739 events_request->viewer_data = event_data;
740 events_request->servicing = FALSE;
741 events_request->start_time = event_data->time_window.start_time;
742 events_request->start_position = NULL;
743 events_request->stop_flag = FALSE;
744 events_request->end_time = event_data->time_window.end_time;
745 events_request->num_events = G_MAXUINT;
746 events_request->end_position = NULL;
747 events_request->trace = i;
748
749 events_request->hooks = hooks;
750
751 events_request->before_chunk_traceset = NULL;
752 events_request->before_chunk_trace = NULL;
753 events_request->before_chunk_tracefile= NULL;
754 events_request->event = NULL;
755 events_request->event_by_id = event_data->event_by_id_hooks;
756 events_request->after_chunk_tracefile = NULL;
757 events_request->after_chunk_trace = NULL;
758 events_request->after_chunk_traceset = NULL;
759 events_request->before_request = NULL;
760 events_request->after_request = event_data->hooks_trace_after;
761
762 lttvwindow_events_request(event_data->tab, events_request);
763 }
e5258c09 764 return FALSE;
dc06b1bc 765}
766
767static void CalculateAverageDurationForEachIrqId(InterruptEventData *event_data)
768{
769 guint64 real_data;
770 Irq *element;
771 gint i;
772 GArray* FirstRequestIrqExit = event_data->FirstRequestIrqExit;
773 for(i = 0; i < FirstRequestIrqExit->len; i++)
774 {
775 element = &g_array_index(FirstRequestIrqExit,Irq,i);
776 real_data = element->total_duration.tv_sec;
777 real_data *= NANOSECONDS_PER_SECOND;
778 real_data += element->total_duration.tv_nsec;
779 element->average_duration = real_data / element->frequency;
dc06b1bc 780 }
781
782}
783
e5258c09 784/**
785 * This function is called whenever an irq_entry event occurs. Use in the second request
786 *
787 */
dc06b1bc 788static gboolean SecondRequestIrqEntryCallback(void *hook_data, void *call_data)
789{
790
791 LttTime event_time;
792 unsigned cpu_id;
793 irq_entry entry;
794 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
795 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
796 InterruptEventData *event_data = (InterruptEventData *)hook_data;
797 GArray* SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
798 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
799 event_time = ltt_event_time(e);
800 cpu_id = ltt_event_cpu_id(e);
801
802
803 entry.id =get_interrupt_id(e);
804 entry.cpu_id = cpu_id;
805 entry.event_time = event_time;
806 g_array_append_val (SecondRequestIrqEntry, entry);
807
808 return FALSE;
809}
810
e5258c09 811/**
812 * This function is called whenever an irq_exit event occurs in the second request.
813 *
814 */
dc06b1bc 815static gboolean SecondRequestIrqExitCallback(void *hook_data, void *call_data)
816{
817
818 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
819 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
820 InterruptEventData *event_data = (InterruptEventData *)hook_data;
821 LttEvent *event = ltt_tracefile_get_event(tfc->tf);
822
823 CalculateXi(event, event_data);
824 return FALSE;
825}
826
e5258c09 827
828/**
829 * This function is called whenever an irq_exit event occurs in the second request.
830 *
831 */
dc06b1bc 832static void CalculateXi(LttEvent *event_irq_exit, InterruptEventData *event_data)
833{
834 gint i, irq_id;
835 irq_entry *element;
836 LttTime Xi;
837 LttTime exit_time;
838 unsigned cpu_id;
839
840 GArray *SecondRequestIrqExit = event_data->SecondRequestIrqExit;
841 GArray *SecondRequestIrqEntry = event_data->SecondRequestIrqEntry;
842 cpu_id = ltt_event_cpu_id(event_irq_exit);
843 for(i = 0; i < SecondRequestIrqEntry->len; i++)
844 {
845 element = &g_array_index(SecondRequestIrqEntry,irq_entry,i);
846 if(element->cpu_id == cpu_id)
847 {
848
849 /* time calculation */
850 exit_time = ltt_event_time(event_irq_exit);
851 Xi = ltt_time_sub(exit_time, element->event_time);
852 irq_id = element->id;
853
854 SumItems(irq_id, Xi,event_data);
855 g_array_remove_index(SecondRequestIrqEntry, i);
856 break;
857 }
858 }
859}
860
e5258c09 861
862/**
863 * This function computes the Sum ((xi -Xa)^2) and store the result in SumArray
864 *
865 */
dc06b1bc 866static void SumItems(gint irq_id, LttTime Xi, InterruptEventData *event_data)
867{
868 gint i;
6b0817c2 869 guint Xi_in_ns;
dc06b1bc 870
6b0817c2 871 gint duration_inner_part;
872 guint64 period_inner_part;
dc06b1bc 873 Irq *average;
874 SumId *sumItem;
875 SumId sum;
6b0817c2 876 int FrequencyHZ = 0;
dc06b1bc 877 gboolean notFound = FALSE;
878 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
879 GArray *SumArray = event_data->SumArray;
6b0817c2 880 Xi_in_ns = Xi.tv_sec;
881 Xi_in_ns *= NANOSECONDS_PER_SECOND;
882 Xi_in_ns += Xi.tv_nsec;
dc06b1bc 883
884 for(i = 0; i < FirstRequestIrqExit->len; i++)
885 {
886 average = &g_array_index(FirstRequestIrqExit,Irq,i);
887 if(irq_id == average->id)
888 {
6b0817c2 889 duration_inner_part = Xi_in_ns - average->average_duration;
890 FrequencyHZ = FrequencyInHZ(average->frequency, event_data->time_window);
891
dc06b1bc 892 sum.irqId = irq_id;
893 sum.frequency = average->frequency;
6b0817c2 894 sum.sumOfDurations = pow (duration_inner_part , 2);
895 period_inner_part = CalculatePeriodInnerPart(Xi_in_ns, FrequencyHZ);
896 sum.sumOfPeriods = period_inner_part;
dc06b1bc 897 if(event_data->SumArray->len == NO_ITEMS)
898 {
899 g_array_append_val (SumArray, sum);
900 }
901 else
6b0817c2 902 {
dc06b1bc 903 for(i = 0; i < SumArray->len; i++)
904 {
905 sumItem = &g_array_index(SumArray, SumId, i);
906 if(sumItem->irqId == irq_id)
907 {
908 notFound = TRUE;
909 sumItem->sumOfDurations += sum.sumOfDurations;
6b0817c2 910 sumItem->sumOfPeriods += sum.sumOfPeriods;
911 }
dc06b1bc 912 }
913 if(!notFound)
914 {
915 g_array_append_val (SumArray, sum);
916 }
6b0817c2 917
dc06b1bc 918 }
919
920 }
921 }
922}
923
6b0817c2 924static guint64 CalculatePeriodInnerPart(guint Xi, guint FrequencyHZ)
925{
926
927 double periodInSec; /*period in sec*/
928 int periodInNSec;
929 gint difference;
930 guint64 result;
931 periodInSec = (double)1/FrequencyHZ;
932 periodInSec *= NANOSECONDS_PER_SECOND;
933 periodInNSec = (int)periodInSec;
934
935 difference = Xi - periodInNSec;
936 result = pow (difference , 2);
937
938
939 return result;
940
941
942
943}
f2ec7aa9 944/**
945 * This function displays the result on the viewer
946 *
947 */
dc06b1bc 948static gboolean DisplayViewer(void *hook_data, void *call_data)
949{
5f5119ee 950
dc06b1bc 951 guint average;
f2ec7aa9 952 gint i;
953 Irq element;
954 LttTime average_duration;
955 GtkTreeIter iter;
956 guint64 real_data;
446b4179 957 guint maxIRQduration;
6b0817c2 958 double periodInSec;
959 int periodInNsec;
e5258c09 960 char maxIrqHandler[80];
f2ec7aa9 961 InterruptEventData *event_data = (InterruptEventData *)hook_data;
dc06b1bc 962 GArray *FirstRequestIrqExit = event_data->FirstRequestIrqExit;
52948a62 963 int FrequencyHZ = 0;
6b0817c2 964 periodInSec = 0;
f2ec7aa9 965 gtk_list_store_clear(event_data->ListStore);
dc06b1bc 966 for(i = 0; i < FirstRequestIrqExit->len; i++)
231a6432 967 {
dc06b1bc 968 element = g_array_index(FirstRequestIrqExit,Irq,i);
f2ec7aa9 969 real_data = element.total_duration.tv_sec;
970 real_data *= NANOSECONDS_PER_SECOND;
971 real_data += element.total_duration.tv_nsec;
446b4179 972
973
974 maxIRQduration = element.max_irq_handler.duration.tv_sec;
975 maxIRQduration *= NANOSECONDS_PER_SECOND;
976 maxIRQduration += element.max_irq_handler.duration.tv_nsec;
e5258c09 977
fc77fe59 978 sprintf(maxIrqHandler, "%d [%d.%d - %d.%d]",maxIRQduration, element.max_irq_handler.start_time.tv_sec, \
979 element.max_irq_handler.start_time.tv_nsec, element.max_irq_handler.end_time.tv_sec, \
980 element.max_irq_handler.end_time.tv_nsec) ;
52948a62 981 FrequencyHZ = FrequencyInHZ(element.frequency,event_data->time_window);
6b0817c2 982
52948a62 983 if(FrequencyHZ != 0)
984 {
6b0817c2 985 periodInSec = (double)1/FrequencyHZ;
986 periodInSec *= NANOSECONDS_PER_SECOND;
987 periodInNsec = (int)periodInSec;
988 //printf("period1:%d\n", periodInNsec);
52948a62 989 }
6b0817c2 990
f2ec7aa9 991 gtk_list_store_append (event_data->ListStore, &iter);
992 gtk_list_store_set (event_data->ListStore, &iter,
993 CPUID_COLUMN, element.cpu_id,
994 IRQ_ID_COLUMN, element.id,
52948a62 995 FREQUENCY_COLUMN, FrequencyHZ,
f2ec7aa9 996 DURATION_COLUMN, real_data,
6b0817c2 997 DURATION_STANDARD_DEV_COLUMN, CalculateDurationStandardDeviation(element.id, event_data),
e5258c09 998 MAX_IRQ_HANDLER_COLUMN, maxIrqHandler,
6b0817c2 999 AVERAGE_PERIOD , periodInNsec,
1000 PERIOD_STANDARD_DEV_COLUMN, CalculatePeriodStandardDeviation(element.id, event_data),
f2ec7aa9 1001 -1);
dc06b1bc 1002
446b4179 1003
f2ec7aa9 1004 }
dc06b1bc 1005
dc06b1bc 1006
1007 if(event_data->FirstRequestIrqExit->len)
231a6432 1008 {
dc06b1bc 1009 g_array_remove_range (event_data->FirstRequestIrqExit,0,event_data->FirstRequestIrqExit->len);
231a6432 1010 }
1011
dc06b1bc 1012 if(event_data->FirstRequestIrqEntry->len)
231a6432 1013 {
dc06b1bc 1014 g_array_remove_range (event_data->FirstRequestIrqEntry,0,event_data->FirstRequestIrqEntry->len);
1015 }
1016
1017 if(event_data->SecondRequestIrqEntry->len)
1018 {
1019 g_array_remove_range (event_data->SecondRequestIrqEntry,0,event_data->SecondRequestIrqEntry->len);
1020 }
231a6432 1021
dc06b1bc 1022 if(event_data->SecondRequestIrqExit->len)
1023 {
1024 g_array_remove_range (event_data->SecondRequestIrqExit,0, event_data->SecondRequestIrqExit->len);
1025 }
1026
1027 if(event_data->SumArray->len)
1028 {
1029 g_array_remove_range (event_data->SumArray,0, event_data->SumArray->len);
231a6432 1030 }
dc06b1bc 1031
f2ec7aa9 1032 return FALSE;
5f5119ee 1033}
dc06b1bc 1034
25c6412d 1035
6b0817c2 1036/**
1037 * This function converts the number of interrupts over a time window to
1038 * frequency in HZ
1039 */
25c6412d 1040static int FrequencyInHZ(gint frequency, TimeWindow time_window)
1041{
1042 guint64 frequencyHz = 0;
6b0817c2 1043 double timeSec; // time in second
1044 double result;
1045 result = ltt_time_to_double(time_window.time_width);
1046 timeSec = (result/NANOSECONDS_PER_SECOND); //time in second
1047 frequencyHz = frequency / timeSec;
25c6412d 1048 return frequencyHz;
1049}
1050
e5258c09 1051/**
6b0817c2 1052 * This function calculates the duration standard deviation
e5258c09 1053 *
1054 */
6b0817c2 1055static int CalculateDurationStandardDeviation(gint id, InterruptEventData *event_data)
dc06b1bc 1056{
1057 int i;
1058 SumId sumId;
1059 double inner_component;
1060 int deviation = 0;
1061 for(i = 0; i < event_data->SumArray->len; i++)
1062 {
1063 sumId = g_array_index(event_data->SumArray, SumId, i);
1064 if(id == sumId.irqId)
1065 {
25c6412d 1066 inner_component = sumId.sumOfDurations/ sumId.frequency;
dc06b1bc 1067 deviation = sqrt(inner_component);
25c6412d 1068 return deviation;
dc06b1bc 1069 }
1070 }
1071 return deviation;
1072}
6b0817c2 1073
1074
1075/**
1076 * This function calculates the period standard deviation
1077 *
1078 */
1079static int CalculatePeriodStandardDeviation(gint id, InterruptEventData *event_data)
1080{
1081 int i;
1082 SumId sumId;
1083 guint64 inner_component;
1084 guint64 period_standard_deviation = 0;
1085 for(i = 0; i < event_data->SumArray->len; i++)
1086 {
1087 sumId = g_array_index(event_data->SumArray, SumId, i);
1088 if(id == sumId.irqId)
1089 {
1090 inner_component = sumId.sumOfPeriods / sumId.frequency;
1091 period_standard_deviation = sqrt(inner_component);
1092 }
1093 }
1094
1095 return period_standard_deviation;
1096}
f2ec7aa9 1097/*
1098 * This function is called by the main window
1099 * when the time interval needs to be updated.
1100 **/
1101gboolean interrupt_update_time_window(void * hook_data, void * call_data)
1102{
5f5119ee 1103 InterruptEventData *event_data = (InterruptEventData *) hook_data;
1104 const TimeWindowNotifyData *time_window_nofify_data = ((const TimeWindowNotifyData *)call_data);
1105 event_data->time_window = *time_window_nofify_data->new_time_window;
1106 g_info("interrupts: interrupt_update_time_window()\n");
1107 Tab *tab = event_data->tab;
1108 lttvwindow_events_request_remove_all(tab, event_data);
dc06b1bc 1109 FirstRequest(event_data );
f2ec7aa9 1110 return FALSE;
5f5119ee 1111}
1112
f2ec7aa9 1113
1114gboolean trace_header(void *hook_data, void *call_data)
1115{
1116
1117 InterruptEventData *event_data = (InterruptEventData *)hook_data;
1118 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
f2ec7aa9 1119 LttEvent *e;
1120 LttTime event_time;
1121 return FALSE;
5f5119ee 1122}
1123
f2ec7aa9 1124void interrupt_destroy_walk(gpointer data, gpointer user_data)
1125{
5f5119ee 1126 g_info("interrupt_destroy_walk");
fc77fe59 1127 InterruptEventData *event_data = (InterruptEventData*) data;
1128
1129
5f5119ee 1130 interrupt_destructor((InterruptEventData*)data);
1131
1132}
1133
fc77fe59 1134
f2ec7aa9 1135void interrupt_destructor(InterruptEventData *event_viewer_data)
1136{
1137 /* May already been done by GTK window closing */
1138 g_info("enter interrupt_destructor \n");
1139 if(GTK_IS_WIDGET(event_viewer_data->Hbox))
1140 {
1141 gtk_widget_destroy(event_viewer_data->Hbox);
1142 }
1143}
1144
fc77fe59 1145/**
1146 This function is called when the viewer is destroyed to free hooks and memory
1147*/
1148static void InterruptFree(InterruptEventData *event_viewer_data)
1149{
1150 Tab *tab = event_viewer_data->tab;
1151 if(tab != NULL)
1152 {
1153
1154 g_array_free(event_viewer_data->FirstRequestIrqExit, TRUE);
1155 g_array_free(event_viewer_data->FirstRequestIrqEntry, TRUE);
1156 g_array_free(event_viewer_data->SecondRequestIrqEntry, TRUE);
1157 g_array_free(event_viewer_data->SecondRequestIrqExit, TRUE);
1158 g_array_free(event_viewer_data->SumArray, TRUE);
1159
1160 lttvwindow_unregister_time_window_notify(tab, interrupt_update_time_window, event_viewer_data);
1161
1162 lttvwindow_events_request_remove_all(event_viewer_data->tab,
1163 event_viewer_data);
1164
1165 interrupt_data_list = g_slist_remove(interrupt_data_list, event_viewer_data);
1166
1167 }
1168
1169}
1170
5f5119ee 1171/**
1172 * plugin's destroy function
1173 *
1174 * This function releases the memory reserved by the module and unregisters
1175 * everything that has been registered in the gtkTraceSet API.
1176 */
dc06b1bc 1177static void destroy()
1178{
1179
5f5119ee 1180 g_info("Destroy interrupts");
1181 g_slist_foreach(interrupt_data_list, interrupt_destroy_walk, NULL );
1182 g_slist_free(interrupt_data_list);
1183 lttvwindow_unregister_constructor(interrupts);
1184
1185}
1186
1187LTTV_MODULE("interrupts", "interrupts info view", \
1188 "Graphical module to display interrupts performance", \
1189 init, destroy, "lttvwindow")
This page took 0.08113 seconds and 4 git commands to generate.