1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 #include <lttv/module.h>
26 #include <lttv/stats.h>
27 #include <lttv/lttv.h>
28 #include <lttv/attribute.h>
29 #include <ltt/trace.h>
30 #include <ltt/event.h>
33 #define MAX_64_HEX_STRING_LEN 19
36 LTTV_STATS_PROCESS_UNKNOWN
,
39 LTTV_STATS_MODE_TYPES
,
43 LTTV_STATS_EVENT_TYPES
,
45 LTTV_STATS_CUMULATIVE_CPU_TIME
,
46 LTTV_STATS_ELAPSED_TIME
,
48 LTTV_STATS_EVENTS_COUNT
,
51 LTTV_STATS_TRACEFILES
,
53 LTTV_STATS_BEFORE_HOOKS
,
54 LTTV_STATS_AFTER_HOOKS
;
57 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, guint cpu
,
59 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
60 LttvAttribute
**event_types_tree
);
63 static void lttv_stats_init(LttvTracesetStats
*self
)
65 guint i
, j
, nb_trace
, nb_tracefile
;
71 LttvTracefileContext
**tfs
;
72 LttvTracefileStats
*tfcs
;
76 LttvAttribute
*tracefiles_stats
;
78 LttvTraceset
*ts
= self
->parent
.parent
.ts
;
80 self
->stats
= lttv_attribute_find_subdir(
81 lttv_traceset_attribute(self
->parent
.parent
.ts
),
83 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
88 if(*(v
.v_uint
) == 1) {
89 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
92 nb_trace
= lttv_traceset_number(ts
);
94 for(i
= 0 ; i
< nb_trace
; i
++) {
95 tc
= self
->parent
.parent
.traces
[i
];
96 tcs
= LTTV_TRACE_STATS(tc
);
98 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
99 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
100 LTTV_STATS_TRACEFILES
);
101 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
105 if(*(v
.v_uint
) == 1) {
106 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
109 nb_tracefile
= tc
->tracefiles
->len
;
111 for(j
= 0 ; j
< nb_tracefile
; j
++) {
112 tfs
= &g_array_index(tc
->tracefiles
,
113 LttvTracefileContext
*, j
);
114 tfcs
= LTTV_TRACEFILE_STATS(*tfs
);
115 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
116 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
));
117 guint cpu
= tfcs
->parent
.cpu
;
118 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
121 LTTV_STATE_MODE_UNKNOWN
,
122 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
123 &tfcs
->current_event_types_tree
);
129 static void lttv_stats_fini(LttvTracesetStats
*self
)
131 guint i
, j
, nb_trace
, nb_tracefile
;
135 LttvTraceContext
*tc
;
139 LttvTracefileContext
*tfc
;
141 LttvTracefileStats
*tfcs
;
143 LttvAttributeValue v
;
145 LttvAttribute
*tracefiles_stats
;
147 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
151 if(*(v
.v_uint
) == 0) {
152 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
156 ts
= self
->parent
.parent
.ts
;
157 nb_trace
= lttv_traceset_number(ts
);
159 for(i
= 0 ; i
< nb_trace
; i
++) {
160 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
162 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
166 if(*(v
.v_uint
) == 0) {
167 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
168 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
169 LTTV_STATS_TRACEFILES
);
170 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
171 LTTV_STATS_TRACEFILES
);
175 nb_tracefile
= tc
->tracefiles
->len
;
177 for(j
= 0 ; j
< nb_tracefile
; j
++) {
178 tfc
= g_array_index(tc
->tracefiles
,
179 LttvTracefileContext
*, j
);
180 tfcs
= (LttvTracefileStats
*)tfc
;
182 tfcs
->current_events_tree
= NULL
;
183 tfcs
->current_event_types_tree
= NULL
;
189 void lttv_stats_reset(LttvTracesetStats
*self
)
191 lttv_stats_fini(self
);
192 lttv_stats_init(self
);
198 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
200 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
201 init((LttvTracesetContext
*)self
, ts
);
203 lttv_stats_init(self
);
208 fini(LttvTracesetStats
*self
)
210 lttv_stats_fini(self
);
212 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
213 fini((LttvTracesetContext
*)self
);
217 static LttvTracesetContext
*
218 new_traceset_context(LttvTracesetContext
*self
)
220 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
224 static LttvTraceContext
*
225 new_trace_context(LttvTracesetContext
*self
)
227 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
231 static LttvTracefileContext
*
232 new_tracefile_context(LttvTracesetContext
*self
)
234 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
239 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
245 traceset_stats_finalize (LttvTracesetStats
*self
)
247 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
248 finalize(G_OBJECT(self
));
253 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
255 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
257 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
258 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
259 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
260 klass
->new_traceset_context
= new_traceset_context
;
261 klass
->new_trace_context
= new_trace_context
;
262 klass
->new_tracefile_context
= new_tracefile_context
;
267 lttv_traceset_stats_get_type(void)
269 static GType type
= 0;
271 static const GTypeInfo info
= {
272 sizeof (LttvTracesetStatsClass
),
273 NULL
, /* base_init */
274 NULL
, /* base_finalize */
275 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
276 NULL
, /* class_finalize */
277 NULL
, /* class_data */
278 sizeof (LttvTracesetStats
),
280 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
281 NULL
/* Value handling */
284 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
285 "LttvTracesetStatsType",
293 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
299 trace_stats_finalize (LttvTraceStats
*self
)
301 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
302 finalize(G_OBJECT(self
));
307 trace_stats_class_init (LttvTraceContextClass
*klass
)
309 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
311 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
316 lttv_trace_stats_get_type(void)
318 static GType type
= 0;
320 static const GTypeInfo info
= {
321 sizeof (LttvTraceStatsClass
),
322 NULL
, /* base_init */
323 NULL
, /* base_finalize */
324 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
325 NULL
, /* class_finalize */
326 NULL
, /* class_data */
327 sizeof (LttvTraceStats
),
329 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
330 NULL
/* Value handling */
333 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
334 "LttvTraceStatsType", &info
, 0);
341 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
347 tracefile_stats_finalize (LttvTracefileStats
*self
)
349 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
350 finalize(G_OBJECT(self
));
355 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
357 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
359 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
364 lttv_tracefile_stats_get_type(void)
366 static GType type
= 0;
368 static const GTypeInfo info
= {
369 sizeof (LttvTracefileStatsClass
),
370 NULL
, /* base_init */
371 NULL
, /* base_finalize */
372 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
373 NULL
, /* class_finalize */
374 NULL
, /* class_data */
375 sizeof (LttvTracefileStats
),
377 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
378 NULL
/* Value handling */
381 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
382 "LttvTracefileStatsType", &info
, 0);
388 find_event_tree(LttvTracefileStats
*tfcs
,
394 LttvAttribute
**events_tree
,
395 LttvAttribute
**event_types_tree
)
398 gchar fstring
[MAX_64_HEX_STRING_LEN
];
401 ret
= snprintf(fstring
, MAX_64_HEX_STRING_LEN
-1,
402 "0x%" PRIX64
, function
) > 0;
404 fstring
[MAX_64_HEX_STRING_LEN
-1] = '\0';
406 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
407 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
408 a
= lttv_attribute_find_subdir(a
, pid_time
);
409 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
410 a
= lttv_attribute_find_subdir_unnamed(a
, cpu
);
411 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_FUNCTIONS
);
412 a
= lttv_attribute_find_subdir(a
, g_quark_from_string(fstring
));
413 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
414 a
= lttv_attribute_find_subdir(a
, mode
);
415 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
416 a
= lttv_attribute_find_subdir(a
, sub_mode
);
418 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
419 *event_types_tree
= a
;
422 static void update_event_tree(LttvTracefileStats
*tfcs
)
424 guint cpu
= tfcs
->parent
.cpu
;
425 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
426 LttvProcessState
*process
= ts
->running_process
[cpu
];
427 LttvExecutionState
*es
= process
->state
;
429 find_event_tree(tfcs
, process
->pid_time
,
431 process
->current_function
,
432 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
433 &(tfcs
->current_event_types_tree
));
437 /* Update the trace event tree for the specified cpu */
438 static void update_trace_event_tree(LttvTraceStats
*tcs
)
440 LttvTracefileStats
*tfcs
;
441 LttvTraceContext
*tc
= (LttvTraceContext
*)tcs
;
442 guint j
, nb_tracefile
;
444 /* For each tracefile, update the event tree */
445 nb_tracefile
= tc
->tracefiles
->len
;
446 for(j
= 0; j
< nb_tracefile
; j
++) {
447 tfcs
= LTTV_TRACEFILE_STATS(g_array_index(tc
->tracefiles
,
448 LttvTracefileContext
*, j
));
449 update_event_tree(tfcs
);
453 static void mode_change(LttvTracefileStats
*tfcs
)
455 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
456 guint cpu
= tfcs
->parent
.cpu
;
457 LttvProcessState
*process
= ts
->running_process
[cpu
];
458 LttvAttributeValue cpu_time
;
462 if(process
->state
->s
== LTTV_STATE_RUN
&&
463 process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
)
464 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
465 process
->state
->change
);
467 delta
= ltt_time_zero
;
469 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
470 LTTV_TIME
, &cpu_time
);
471 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
473 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
477 /* Note : every mode_end must come with a cumulative cpu time update in the
479 static void mode_end(LttvTracefileStats
*tfcs
)
481 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
482 guint cpu
= tfcs
->parent
.cpu
;
483 LttvProcessState
*process
= ts
->running_process
[cpu
];
484 LttvAttributeValue elapsed_time
, cpu_time
, cum_cpu_time
;
488 /* FIXME put there in case of a missing update after a state modification */
489 //void *lasttree = tfcs->current_events_tree;
490 //update_event_tree(tfcs);
491 //g_assert (lasttree == tfcs->current_events_tree);
492 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
493 LTTV_TIME
, &elapsed_time
);
495 if(process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
) {
496 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
497 process
->state
->entry
);
499 delta
= ltt_time_zero
;
501 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
503 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
504 LTTV_TIME
, &cpu_time
);
506 /* if it is a running mode, we must count its cpu time */
507 if(process
->state
->s
== LTTV_STATE_RUN
&&
508 process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
)
509 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
510 process
->state
->change
);
512 delta
= ltt_time_zero
;
514 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
515 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
518 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CUMULATIVE_CPU_TIME
,
519 LTTV_TIME
, &cum_cpu_time
);
520 *(cum_cpu_time
.v_time
) = ltt_time_add(*(cum_cpu_time
.v_time
),
521 process
->state
->cum_cpu_time
);
525 static void after_mode_end(LttvTracefileStats
*tfcs
)
527 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
528 guint cpu
= tfcs
->parent
.cpu
;
529 LttvProcessState
*process
= ts
->running_process
[cpu
];
531 LttTime nested_delta
;
533 nested_delta
= process
->state
->cum_cpu_time
;
534 process
->state
->cum_cpu_time
= ltt_time_zero
; /* For after traceset hook */
536 update_event_tree(tfcs
);
538 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
542 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
544 mode_change((LttvTracefileStats
*)call_data
);
549 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
551 update_event_tree((LttvTracefileStats
*)call_data
);
556 static gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
558 mode_end((LttvTracefileStats
*)call_data
);
563 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
565 after_mode_end((LttvTracefileStats
*)call_data
);
570 static gboolean
before_trap_entry(void *hook_data
, void *call_data
)
572 mode_change((LttvTracefileStats
*)call_data
);
577 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
579 update_event_tree((LttvTracefileStats
*)call_data
);
584 static gboolean
before_trap_exit(void *hook_data
, void *call_data
)
586 mode_end((LttvTracefileStats
*)call_data
);
591 static gboolean
after_trap_exit(void *hook_data
, void *call_data
)
593 after_mode_end((LttvTracefileStats
*)call_data
);
598 static gboolean
before_irq_entry(void *hook_data
, void *call_data
)
600 mode_change((LttvTracefileStats
*)call_data
);
604 static gboolean
after_irq_entry(void *hook_data
, void *call_data
)
606 update_event_tree((LttvTracefileStats
*)call_data
);
611 static gboolean
before_irq_exit(void *hook_data
, void *call_data
)
613 mode_end((LttvTracefileStats
*)call_data
);
618 static gboolean
after_irq_exit(void *hook_data
, void *call_data
)
620 after_mode_end((LttvTracefileStats
*)call_data
);
625 static gboolean
before_soft_irq_entry(void *hook_data
, void *call_data
)
627 mode_change((LttvTracefileStats
*)call_data
);
631 static gboolean
after_soft_irq_entry(void *hook_data
, void *call_data
)
633 update_event_tree((LttvTracefileStats
*)call_data
);
637 static gboolean
before_soft_irq_exit(void *hook_data
, void *call_data
)
639 mode_end((LttvTracefileStats
*)call_data
);
644 static gboolean
after_soft_irq_exit(void *hook_data
, void *call_data
)
646 after_mode_end((LttvTracefileStats
*)call_data
);
650 static gboolean
before_function_entry(void *hook_data
, void *call_data
)
652 mode_change((LttvTracefileStats
*)call_data
);
656 static gboolean
after_function_entry(void *hook_data
, void *call_data
)
658 update_event_tree((LttvTracefileStats
*)call_data
);
662 static gboolean
before_function_exit(void *hook_data
, void *call_data
)
664 mode_end((LttvTracefileStats
*)call_data
);
668 static gboolean
after_function_exit(void *hook_data
, void *call_data
)
670 after_mode_end((LttvTracefileStats
*)call_data
);
675 static gboolean
before_schedchange(void *hook_data
, void *call_data
)
677 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
679 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
681 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
683 guint pid_in
, pid_out
;
687 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
688 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
689 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
691 /* compute the time for the process to schedule out */
697 static gboolean
after_schedchange(void *hook_data
, void *call_data
)
699 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
701 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
703 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
705 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
707 guint pid_in
, pid_out
;
711 LttvProcessState
*process
;
713 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
714 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
715 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
717 /* get the information for the process scheduled in */
718 guint cpu
= tfcs
->parent
.cpu
;
719 process
= ts
->running_process
[cpu
];
721 find_event_tree(tfcs
, process
->pid_time
,
723 process
->current_function
,
724 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
725 &(tfcs
->current_event_types_tree
));
727 /* compute the time waiting for the process to schedule in */
733 static gboolean
process_fork(void *hook_data
, void *call_data
)
738 static gboolean
process_exit(void *hook_data
, void *call_data
)
740 update_event_tree((LttvTracefileStats
*)call_data
);
744 static gboolean
before_enum_process_state(void *hook_data
, void *call_data
)
747 /* Broken : adds up time in the current process doing the dump */
748 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
750 after_mode_end(tfcs
);
756 static gboolean
after_enum_process_state(void *hook_data
, void *call_data
)
758 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
759 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfc
->t_context
;
760 update_trace_event_tree(tcs
);
764 static gboolean
after_statedump_end(void *hook_data
, void *call_data
)
766 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
767 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfc
->t_context
;
768 update_trace_event_tree(tcs
);
772 static gboolean
process_free(void *hook_data
, void *call_data
)
777 static gboolean
every_event(void *hook_data
, void *call_data
)
779 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
781 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
783 LttvAttributeValue v
;
785 struct marker_info
*info
;
787 /* The current branch corresponds to the tracefile/process/interrupt state.
788 Statistics are added within it, to count the number of events of this
789 type occuring in this context. A quark has been pre-allocated for each
790 event type and is used as name. */
792 info
= marker_get_info_from_id(tfcs
->parent
.parent
.tf
->mdata
, e
->event_id
);
794 lttv_attribute_find(tfcs
->current_event_types_tree
,
795 info
->name
, LTTV_UINT
, &v
);
800 struct cleanup_state_struct
{
802 LttTime current_time
;
805 //static void lttv_stats_cleanup_process_state(LttvTraceState *ts,
806 // LttvProcessState *process, LttTime current_time)
807 static void lttv_stats_cleanup_process_state(gpointer key
, gpointer value
,
810 struct cleanup_state_struct
*cleanup_closure
=
811 (struct cleanup_state_struct
*)user_data
;
812 LttvTraceState
*ts
= cleanup_closure
->ts
;
813 LttvProcessState
*process
= (LttvProcessState
*)value
;
814 LttTime current_time
= cleanup_closure
->current_time
;
815 LttvTracefileStats
**tfs
= (LttvTracefileStats
**)
816 &g_array_index(ts
->parent
.tracefiles
, LttvTracefileContext
*,
818 int cleanup_empty
= 0;
819 LttTime nested_delta
= ltt_time_zero
;
821 /* FIXME : ok, this is a hack. The time is infinite here :( */
822 //LttTime save_time = (*tfs)->parent.parent.timestamp;
823 //LttTime start, end;
824 //ltt_trace_time_span_get(ts->parent.t, &start, &end);
825 //(*tfs)->parent.parent.timestamp = end;
828 if(ltt_time_compare(process
->state
->cum_cpu_time
, ltt_time_zero
) != 0) {
829 find_event_tree(*tfs
, process
->pid_time
,
831 process
->current_function
,
832 process
->state
->t
, process
->state
->n
, &((*tfs
)->current_events_tree
),
833 &((*tfs
)->current_event_types_tree
));
834 /* Call mode_end only if not at end of trace */
835 if(ltt_time_compare(current_time
, ltt_time_infinite
) != 0)
837 nested_delta
= process
->state
->cum_cpu_time
;
839 cleanup_empty
= lttv_state_pop_state_cleanup(process
,
840 (LttvTracefileState
*)*tfs
);
841 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
844 } while(cleanup_empty
!= 1);
846 //(*tfs)->parent.parent.timestamp = save_time;
849 /* For each cpu, for each of their stacked states,
850 * perform sum of needed values. */
851 static void lttv_stats_cleanup_state(LttvTraceStats
*tcs
, LttTime current_time
)
853 LttvTraceState
*ts
= (LttvTraceState
*)tcs
;
854 struct cleanup_state_struct cleanup_closure
;
858 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
860 for(i
=0; i
<nb_cpus
; i
++) {
861 lttv_stats_cleanup_process_state(ts
, ts
->running_process
[i
], current_time
);
864 cleanup_closure
.ts
= ts
;
865 cleanup_closure
.current_time
= current_time
;
866 g_hash_table_foreach(ts
->processes
, lttv_stats_cleanup_process_state
,
871 lttv_stats_sum_trace(LttvTraceStats
*self
, LttvAttribute
*ts_stats
,
872 LttTime current_time
)
874 LttvAttribute
*sum_container
= self
->stats
;
876 LttvAttributeType type
;
878 LttvAttributeValue value
;
880 LttvAttributeName name
;
888 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
889 nb_event_type
, nf
, nb_functions
;
891 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
892 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
893 *submode_tree
, *event_types_tree
, *mode_events_tree
,
896 *function_mode_types_tree
,
900 main_tree
= sum_container
;
902 lttv_attribute_find(sum_container
,
905 trace_is_summed
= *(value
.v_uint
);
908 /* First cleanup the state : sum all stalled information (never ending
911 lttv_stats_cleanup_state(self
, current_time
);
913 processes_tree
= lttv_attribute_find_subdir(main_tree
,
914 LTTV_STATS_PROCESSES
);
915 nb_process
= lttv_attribute_get_number(processes_tree
);
917 for(i
= 0 ; i
< nb_process
; i
++) {
918 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
, &is_named
);
919 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
921 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
922 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
924 for(j
= 0 ; j
< nb_cpu
; j
++) {
925 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
, &is_named
);
926 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
928 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
929 trace_cpu_tree
= lttv_attribute_find_subdir_unnamed(trace_cpu_tree
, name
);
930 cpu_functions_tree
= lttv_attribute_find_subdir(cpu_tree
,
931 LTTV_STATS_FUNCTIONS
);
932 nb_functions
= lttv_attribute_get_number(cpu_functions_tree
);
934 for(nf
=0; nf
< nb_functions
; nf
++) {
935 type
= lttv_attribute_get(cpu_functions_tree
, nf
, &name
, &value
,
937 function_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
938 function_mode_types_tree
= lttv_attribute_find_subdir(function_tree
,
939 LTTV_STATS_MODE_TYPES
);
940 nb_mode_type
= lttv_attribute_get_number(function_mode_types_tree
);
941 for(k
= 0 ; k
< nb_mode_type
; k
++) {
942 type
= lttv_attribute_get(function_mode_types_tree
, k
, &name
, &value
,
944 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
946 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
947 LTTV_STATS_SUBMODES
);
948 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
950 mode_types_tree
= lttv_attribute_find_subdir(mode_tree
,
951 LTTV_STATS_MODE_TYPES
);
953 nb_submode
= lttv_attribute_get_number(submodes_tree
);
955 for(l
= 0 ; l
< nb_submode
; l
++) {
956 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
958 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
960 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
961 LTTV_STATS_EVENT_TYPES
);
962 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
965 for(m
= 0 ; m
< nb_event_type
; m
++) {
966 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
,
968 sum
+= *(value
.v_uint
);
970 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
972 *(value
.v_uint
) = sum
;
974 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
976 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
977 if(!trace_is_summed
) {
978 lttv_attribute_recursive_add(mode_events_tree
, event_types_tree
);
979 lttv_attribute_recursive_add(mode_types_tree
, submode_tree
);
982 if(!trace_is_summed
) {
983 lttv_attribute_recursive_add(function_tree
, mode_types_tree
);
986 if(!trace_is_summed
) {
987 lttv_attribute_recursive_add(cpu_tree
, function_tree
);
988 lttv_attribute_recursive_add(process_tree
, function_tree
);
989 lttv_attribute_recursive_add(trace_cpu_tree
, function_tree
);
990 lttv_attribute_recursive_add(main_tree
, function_tree
);
992 lttv_attribute_recursive_add(ts_stats
, function_tree
);
999 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
1001 struct sum_traceset_closure
*closure
=
1002 (struct sum_traceset_closure
*)call_data
;
1003 lttv_stats_sum_traceset(closure
->tss
, closure
->current_time
);
1008 lttv_stats_sum_traceset(LttvTracesetStats
*self
, LttTime current_time
)
1010 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1011 LttvAttribute
*sum_container
= self
->stats
;
1013 LttvTraceStats
*tcs
;
1017 LttvAttributeValue value
;
1019 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
1021 if(*(value
.v_uint
) != 0) return;
1022 *(value
.v_uint
) = 1;
1024 nb_trace
= lttv_traceset_number(traceset
);
1026 for(i
= 0 ; i
< nb_trace
; i
++) {
1027 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
1028 lttv_stats_sum_trace(tcs
, self
->stats
, current_time
);
1029 // lttv_attribute_recursive_add(sum_container, tcs->stats);
1034 // Hook wrapper. call_data is a traceset context.
1035 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
1037 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1039 lttv_stats_add_event_hooks(tss
);
1044 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
1046 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1048 guint i
, j
, k
, nb_trace
, nb_tracefile
;
1052 LttvTracefileStats
*tfs
;
1054 GArray
*hooks
, *before_hooks
, *after_hooks
;
1058 LttvAttributeValue val
;
1060 nb_trace
= lttv_traceset_number(traceset
);
1061 for(i
= 0 ; i
< nb_trace
; i
++) {
1062 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1064 /* Find the eventtype id for the following events and register the
1065 associated by id hooks. */
1067 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 12);
1069 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1071 LTT_EVENT_SYSCALL_ENTRY
,
1072 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1073 before_syscall_entry
, NULL
,
1076 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1078 LTT_EVENT_SYSCALL_EXIT
,
1080 before_syscall_exit
, NULL
,
1083 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1085 LTT_EVENT_TRAP_ENTRY
,
1086 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1087 before_trap_entry
, NULL
,
1090 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1092 LTT_EVENT_TRAP_EXIT
,
1094 before_trap_exit
, NULL
,
1097 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1099 LTT_EVENT_IRQ_ENTRY
,
1100 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1101 before_irq_entry
, NULL
,
1104 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1108 before_irq_exit
, NULL
,
1111 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1113 LTT_EVENT_SOFT_IRQ_ENTRY
,
1114 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
1115 before_soft_irq_entry
, NULL
,
1118 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1120 LTT_EVENT_SOFT_IRQ_EXIT
,
1122 before_soft_irq_exit
, NULL
,
1125 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1127 LTT_EVENT_SCHED_SCHEDULE
,
1128 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
, LTT_FIELD_PREV_STATE
),
1129 before_schedchange
, NULL
,
1132 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1133 LTT_CHANNEL_USERSPACE
,
1134 LTT_EVENT_FUNCTION_ENTRY
,
1135 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
1136 before_function_entry
, NULL
,
1139 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1140 LTT_CHANNEL_USERSPACE
,
1141 LTT_EVENT_FUNCTION_EXIT
,
1142 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
1143 before_function_exit
, NULL
,
1146 /* statedump-related hooks */
1147 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1148 LTT_CHANNEL_TASK_STATE
,
1149 LTT_EVENT_PROCESS_STATE
,
1150 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
),
1151 before_enum_process_state
, NULL
,
1154 before_hooks
= hooks
;
1156 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 16);
1158 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1160 LTT_EVENT_SYSCALL_ENTRY
,
1161 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1162 after_syscall_entry
, NULL
,
1165 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1167 LTT_EVENT_SYSCALL_EXIT
,
1169 after_syscall_exit
, NULL
,
1172 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1174 LTT_EVENT_TRAP_ENTRY
,
1175 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1176 after_trap_entry
, NULL
,
1179 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1181 LTT_EVENT_TRAP_EXIT
,
1183 after_trap_exit
, NULL
,
1186 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1188 LTT_EVENT_IRQ_ENTRY
,
1189 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1190 after_irq_entry
, NULL
,
1193 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1197 after_irq_exit
, NULL
,
1200 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1202 LTT_EVENT_SOFT_IRQ_ENTRY
,
1203 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
1204 after_soft_irq_entry
, NULL
,
1207 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1209 LTT_EVENT_SOFT_IRQ_EXIT
,
1211 after_soft_irq_exit
, NULL
,
1214 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1216 LTT_EVENT_SCHED_SCHEDULE
,
1217 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
, LTT_FIELD_PREV_STATE
),
1218 after_schedchange
, NULL
,
1221 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1223 LTT_EVENT_PROCESS_FORK
,
1224 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
),
1228 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1230 LTT_EVENT_PROCESS_EXIT
,
1231 FIELD_ARRAY(LTT_FIELD_PID
),
1235 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1237 LTT_EVENT_PROCESS_FREE
,
1238 FIELD_ARRAY(LTT_FIELD_PID
),
1242 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1243 LTT_CHANNEL_USERSPACE
,
1244 LTT_EVENT_FUNCTION_ENTRY
,
1245 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
1246 after_function_entry
, NULL
,
1249 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1250 LTT_CHANNEL_USERSPACE
,
1251 LTT_EVENT_FUNCTION_EXIT
,
1252 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
1253 after_function_exit
, NULL
,
1256 /* statedump-related hooks */
1257 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1258 LTT_CHANNEL_TASK_STATE
,
1259 LTT_EVENT_PROCESS_STATE
,
1260 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
),
1261 after_enum_process_state
, NULL
,
1264 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1265 LTT_CHANNEL_GLOBAL_STATE
,
1266 LTT_EVENT_STATEDUMP_END
,
1268 after_statedump_end
, NULL
,
1271 after_hooks
= hooks
;
1273 /* Add these hooks to each event_by_id hooks list */
1275 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1277 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1278 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1279 LttvTracefileContext
*, j
));
1280 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
1283 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1284 th
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1285 if (th
->mdata
== tfs
->parent
.parent
.tf
->mdata
)
1287 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, th
->id
),
1290 LTTV_PRIO_STATS_BEFORE_STATE
);
1292 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1293 th
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1294 if (th
->mdata
== tfs
->parent
.parent
.tf
->mdata
)
1296 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, th
->id
),
1299 LTTV_PRIO_STATS_AFTER_STATE
);
1302 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1303 LTTV_POINTER
, &val
);
1304 *(val
.v_pointer
) = before_hooks
;
1305 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1306 LTTV_POINTER
, &val
);
1307 *(val
.v_pointer
) = after_hooks
;
1311 // Hook wrapper. call_data is a traceset context.
1312 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1314 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1316 lttv_stats_remove_event_hooks(tss
);
1321 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1323 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1325 guint i
, j
, k
, nb_trace
, nb_tracefile
;
1329 LttvTracefileStats
*tfs
;
1331 GArray
*before_hooks
, *after_hooks
;
1335 LttvAttributeValue val
;
1337 nb_trace
= lttv_traceset_number(traceset
);
1338 for(i
= 0 ; i
< nb_trace
; i
++) {
1339 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1340 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1341 LTTV_POINTER
, &val
);
1342 before_hooks
= *(val
.v_pointer
);
1343 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1344 LTTV_POINTER
, &val
);
1345 after_hooks
= *(val
.v_pointer
);
1347 /* Remove these hooks from each event_by_id hooks list */
1349 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1351 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1352 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1353 LttvTracefileContext
*, j
));
1354 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1357 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1358 th
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1359 if (th
->mdata
== tfs
->parent
.parent
.tf
->mdata
)
1360 lttv_hooks_remove_data(
1361 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, th
->id
),
1365 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1366 th
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1367 if (th
->mdata
== tfs
->parent
.parent
.tf
->mdata
)
1368 lttv_hooks_remove_data(
1369 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, th
->id
),
1375 g_debug("lttv_stats_remove_event_hooks()");
1376 lttv_trace_hook_remove_all(&before_hooks
);
1377 lttv_trace_hook_remove_all(&after_hooks
);
1378 g_array_free(before_hooks
, TRUE
);
1379 g_array_free(after_hooks
, TRUE
);
1384 static void module_init()
1386 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1387 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1388 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1389 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1390 LTTV_STATS_MODES
= g_quark_from_string("modes");
1391 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1392 LTTV_STATS_FUNCTIONS
= g_quark_from_string("functions");
1393 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1394 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1395 LTTV_STATS_CUMULATIVE_CPU_TIME
= g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1396 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time (includes per process waiting time)");
1397 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1398 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1399 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1400 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1401 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1402 LTTV_STATS
= g_quark_from_string("statistics");
1403 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1404 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1407 static void module_destroy()
1412 LTTV_MODULE("stats", "Compute processes statistics", \
1413 "Accumulate statistics for event types, processes and CPUs", \
1414 module_init
, module_destroy
, "state");
1416 /* Change the places where stats are called (create/read/write stats)
1418 Check for options in batchtest.c to reduce writing and see what tests are
1419 best candidates for performance analysis. Once OK, commit, move to main
1420 and run tests. Update the gui for statistics. */