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,
24 #include <lttv/module.h>
25 #include <lttv/stats.h>
26 #include <lttv/lttv.h>
27 #include <lttv/attribute.h>
28 #include <ltt/facility.h>
29 #include <ltt/trace.h>
30 #include <ltt/event.h>
34 #define MAX_64_HEX_STRING_LEN 19
37 LTTV_STATS_PROCESS_UNKNOWN
,
40 LTTV_STATS_MODE_TYPES
,
44 LTTV_STATS_EVENT_TYPES
,
46 LTTV_STATS_CUMULATIVE_CPU_TIME
,
47 LTTV_STATS_ELAPSED_TIME
,
49 LTTV_STATS_EVENTS_COUNT
,
52 LTTV_STATS_TRACEFILES
,
54 LTTV_STATS_BEFORE_HOOKS
,
55 LTTV_STATS_AFTER_HOOKS
;
58 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, guint cpu
,
60 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
61 LttvAttribute
**event_types_tree
);
64 static void lttv_stats_init(LttvTracesetStats
*self
)
66 guint i
, j
, nb_trace
, nb_tracefile
;
72 LttvTracefileContext
*tfc
;
74 LttvTracefileContext
**tfs
;
75 LttvTracefileStats
*tfcs
;
77 LttTime timestamp
= {0,0};
85 LttvTraceset
*ts
= self
->parent
.parent
.ts
;
87 self
->stats
= lttv_attribute_find_subdir(
88 lttv_traceset_attribute(self
->parent
.parent
.ts
),
90 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
95 if(*(v
.v_uint
) == 1) {
96 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
99 nb_trace
= lttv_traceset_number(ts
);
101 for(i
= 0 ; i
< nb_trace
; i
++) {
102 tc
= self
->parent
.parent
.traces
[i
];
103 tcs
= LTTV_TRACE_STATS(tc
);
105 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
106 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
107 LTTV_STATS_TRACEFILES
);
108 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
112 if(*(v
.v_uint
) == 1) {
113 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
116 nb_tracefile
= tc
->tracefiles
->len
;
118 for(j
= 0 ; j
< nb_tracefile
; j
++) {
119 tfs
= &g_array_index(tc
->tracefiles
,
120 LttvTracefileContext
*, j
);
121 tfcs
= LTTV_TRACEFILE_STATS(*tfs
);
122 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
123 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
));
124 guint cpu
= tfcs
->parent
.cpu
;
125 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
128 LTTV_STATE_MODE_UNKNOWN
,
129 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
130 &tfcs
->current_event_types_tree
);
136 static void lttv_stats_fini(LttvTracesetStats
*self
)
138 guint i
, j
, nb_trace
, nb_tracefile
;
142 LttvTraceContext
*tc
;
146 LttvTracefileContext
*tfc
;
148 LttvTracefileStats
*tfcs
;
150 LttTime timestamp
= {0,0};
152 LttvAttributeValue v
;
154 LttvAttribute
*tracefiles_stats
;
156 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
160 if(*(v
.v_uint
) == 0) {
161 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
165 ts
= self
->parent
.parent
.ts
;
166 nb_trace
= lttv_traceset_number(ts
);
168 for(i
= 0 ; i
< nb_trace
; i
++) {
169 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
171 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
175 if(*(v
.v_uint
) == 0) {
176 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
177 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
178 LTTV_STATS_TRACEFILES
);
179 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
180 LTTV_STATS_TRACEFILES
);
184 nb_tracefile
= tc
->tracefiles
->len
;
186 for(j
= 0 ; j
< nb_tracefile
; j
++) {
187 tfc
= g_array_index(tc
->tracefiles
,
188 LttvTracefileContext
*, j
);
189 tfcs
= (LttvTracefileStats
*)tfc
;
191 tfcs
->current_events_tree
= NULL
;
192 tfcs
->current_event_types_tree
= NULL
;
198 void lttv_stats_reset(LttvTracesetStats
*self
)
200 lttv_stats_fini(self
);
201 lttv_stats_init(self
);
207 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
209 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
210 init((LttvTracesetContext
*)self
, ts
);
212 lttv_stats_init(self
);
217 fini(LttvTracesetStats
*self
)
219 lttv_stats_fini(self
);
221 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
222 fini((LttvTracesetContext
*)self
);
226 static LttvTracesetContext
*
227 new_traceset_context(LttvTracesetContext
*self
)
229 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
233 static LttvTraceContext
*
234 new_trace_context(LttvTracesetContext
*self
)
236 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
240 static LttvTracefileContext
*
241 new_tracefile_context(LttvTracesetContext
*self
)
243 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
248 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
254 traceset_stats_finalize (LttvTracesetStats
*self
)
256 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
257 finalize(G_OBJECT(self
));
262 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
264 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
266 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
267 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
268 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
269 klass
->new_traceset_context
= new_traceset_context
;
270 klass
->new_trace_context
= new_trace_context
;
271 klass
->new_tracefile_context
= new_tracefile_context
;
276 lttv_traceset_stats_get_type(void)
278 static GType type
= 0;
280 static const GTypeInfo info
= {
281 sizeof (LttvTracesetStatsClass
),
282 NULL
, /* base_init */
283 NULL
, /* base_finalize */
284 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
285 NULL
, /* class_finalize */
286 NULL
, /* class_data */
287 sizeof (LttvTracesetStats
),
289 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
290 NULL
/* Value handling */
293 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
294 "LttvTracesetStatsType",
302 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
308 trace_stats_finalize (LttvTraceStats
*self
)
310 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
311 finalize(G_OBJECT(self
));
316 trace_stats_class_init (LttvTraceContextClass
*klass
)
318 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
320 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
325 lttv_trace_stats_get_type(void)
327 static GType type
= 0;
329 static const GTypeInfo info
= {
330 sizeof (LttvTraceStatsClass
),
331 NULL
, /* base_init */
332 NULL
, /* base_finalize */
333 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
334 NULL
, /* class_finalize */
335 NULL
, /* class_data */
336 sizeof (LttvTraceStats
),
338 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
339 NULL
/* Value handling */
342 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
343 "LttvTraceStatsType", &info
, 0);
350 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
356 tracefile_stats_finalize (LttvTracefileStats
*self
)
358 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
359 finalize(G_OBJECT(self
));
364 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
366 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
368 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
373 lttv_tracefile_stats_get_type(void)
375 static GType type
= 0;
377 static const GTypeInfo info
= {
378 sizeof (LttvTracefileStatsClass
),
379 NULL
, /* base_init */
380 NULL
, /* base_finalize */
381 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
382 NULL
, /* class_finalize */
383 NULL
, /* class_data */
384 sizeof (LttvTracefileStats
),
386 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
387 NULL
/* Value handling */
390 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
391 "LttvTracefileStatsType", &info
, 0);
398 find_event_tree(LttvTracefileStats
*tfcs
,
404 LttvAttribute
**events_tree
,
405 LttvAttribute
**event_types_tree
)
407 LttvAttribute
*a
, *prev_a
;
408 gchar fstring
[MAX_64_HEX_STRING_LEN
];
411 ret
= snprintf(fstring
, MAX_64_HEX_STRING_LEN
-1,
412 "0x%llX", function
) > 0;
414 fstring
[MAX_64_HEX_STRING_LEN
-1] = '\0';
416 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
417 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
418 a
= lttv_attribute_find_subdir(a
, pid_time
);
419 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
420 a
= lttv_attribute_find_subdir_unnamed(a
, cpu
);
421 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_FUNCTIONS
);
422 a
= lttv_attribute_find_subdir(a
, g_quark_from_string(fstring
));
423 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
424 a
= lttv_attribute_find_subdir(a
, mode
);
425 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
426 a
= lttv_attribute_find_subdir(a
, sub_mode
);
428 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
429 *event_types_tree
= a
;
433 /* Update the trace event tree for the specified cpu */
434 static void update_trace_event_tree(LttvTracefileStats
*tfcs
, guint cpu
)
436 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
437 LttvProcessState
*process
= ts
->running_process
[cpu
];
438 LttvExecutionState
*es
= process
->state
;
440 find_event_tree(tfcs
, process
->pid_time
,
442 process
->current_function
,
443 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
444 &(tfcs
->current_event_types_tree
));
447 static void update_event_tree(LttvTracefileStats
*tfcs
)
449 update_trace_event_tree(tfcs
, tfcs
->parent
.cpu
);
452 static void mode_change(LttvTracefileStats
*tfcs
)
454 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
455 guint cpu
= tfcs
->parent
.cpu
;
456 LttvProcessState
*process
= ts
->running_process
[cpu
];
457 LttvAttributeValue cpu_time
, cum_cpu_time
;
461 if(process
->state
->s
== LTTV_STATE_RUN
&&
462 process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
)
463 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
464 process
->state
->change
);
466 delta
= ltt_time_zero
;
468 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
469 LTTV_TIME
, &cpu_time
);
470 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
472 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
476 /* Note : every mode_end must come with a cumulative cpu time update in the
478 static void mode_end(LttvTracefileStats
*tfcs
)
480 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
481 guint cpu
= tfcs
->parent
.cpu
;
482 LttvProcessState
*process
= ts
->running_process
[cpu
];
483 LttvAttributeValue elapsed_time
, cpu_time
, cum_cpu_time
;
487 /* FIXME put there in case of a missing update after a state modification */
488 //update_event_tree(tfcs);
490 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
491 LTTV_TIME
, &elapsed_time
);
493 if(process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
)
494 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
495 process
->state
->entry
);
497 delta
= ltt_time_zero
;
499 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
501 //g_assert(delta.tv_nsec != 14736);
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
];
530 LttvAttributeValue cum_cpu_time
;
532 LttTime nested_delta
;
534 nested_delta
= process
->state
->cum_cpu_time
;
535 process
->state
->cum_cpu_time
= ltt_time_zero
; /* For after traceset hook */
537 update_event_tree(tfcs
);
539 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
543 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
545 mode_change((LttvTracefileStats
*)call_data
);
550 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
552 update_event_tree((LttvTracefileStats
*)call_data
);
557 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
559 mode_end((LttvTracefileStats
*)call_data
);
564 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
566 after_mode_end((LttvTracefileStats
*)call_data
);
571 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
573 mode_change((LttvTracefileStats
*)call_data
);
578 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
580 update_event_tree((LttvTracefileStats
*)call_data
);
585 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
587 mode_end((LttvTracefileStats
*)call_data
);
592 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
594 after_mode_end((LttvTracefileStats
*)call_data
);
599 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
601 mode_change((LttvTracefileStats
*)call_data
);
605 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
607 update_event_tree((LttvTracefileStats
*)call_data
);
612 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
614 mode_end((LttvTracefileStats
*)call_data
);
619 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
621 after_mode_end((LttvTracefileStats
*)call_data
);
626 gboolean
before_soft_irq_entry(void *hook_data
, void *call_data
)
628 mode_change((LttvTracefileStats
*)call_data
);
632 gboolean
after_soft_irq_entry(void *hook_data
, void *call_data
)
634 update_event_tree((LttvTracefileStats
*)call_data
);
639 gboolean
before_soft_irq_exit(void *hook_data
, void *call_data
)
641 mode_end((LttvTracefileStats
*)call_data
);
646 gboolean
after_soft_irq_exit(void *hook_data
, void *call_data
)
648 after_mode_end((LttvTracefileStats
*)call_data
);
652 gboolean
before_function_entry(void *hook_data
, void *call_data
)
654 mode_change((LttvTracefileStats
*)call_data
);
658 gboolean
after_function_entry(void *hook_data
, void *call_data
)
660 update_event_tree((LttvTracefileStats
*)call_data
);
664 gboolean
before_function_exit(void *hook_data
, void *call_data
)
666 mode_end((LttvTracefileStats
*)call_data
);
670 gboolean
after_function_exit(void *hook_data
, void *call_data
)
672 after_mode_end((LttvTracefileStats
*)call_data
);
677 gboolean
before_schedchange(void *hook_data
, void *call_data
)
679 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
681 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
683 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
685 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
687 guint pid_in
, pid_out
;
691 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
692 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
693 state_out
= ltt_event_get_int(e
, thf
->f3
);
695 /* compute the time for the process to schedule out */
701 gboolean
after_schedchange(void *hook_data
, void *call_data
)
703 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
705 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
707 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
709 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
711 guint pid_in
, pid_out
;
715 LttvProcessState
*process
;
717 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
718 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
719 state_out
= ltt_event_get_int(e
, thf
->f3
);
721 /* get the information for the process scheduled in */
722 guint cpu
= tfcs
->parent
.cpu
;
723 process
= ts
->running_process
[cpu
];
725 find_event_tree(tfcs
, process
->pid_time
,
727 process
->current_function
,
728 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
729 &(tfcs
->current_event_types_tree
));
731 /* compute the time waiting for the process to schedule in */
737 gboolean
process_fork(void *hook_data
, void *call_data
)
739 /* nothing to do for now */
744 gboolean
process_exit(void *hook_data
, void *call_data
)
746 /* We should probably exit all modes here or we could do that at
751 gboolean
before_enum_process_state(void *hook_data
, void *call_data
)
754 /* Broken : adds up time in the current process doing the dump */
755 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
757 after_mode_end(tfcs
);
763 gboolean
after_enum_process_state(void *hook_data
, void *call_data
)
765 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
766 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
767 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
770 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
771 for(i
=0; i
<nb_cpus
; i
++) {
772 update_trace_event_tree(tfcs
, i
);
777 static gboolean
after_statedump_end(void *hook_data
, void *call_data
)
779 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
780 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
781 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
784 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
785 for(i
=0; i
<nb_cpus
; i
++) {
786 update_trace_event_tree(tfcs
, i
);
791 gboolean
process_free(void *hook_data
, void *call_data
)
796 gboolean
every_event(void *hook_data
, void *call_data
)
798 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
800 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
802 LttvAttributeValue v
;
804 /* The current branch corresponds to the tracefile/process/interrupt state.
805 Statistics are added within it, to count the number of events of this
806 type occuring in this context. A quark has been pre-allocated for each
807 event type and is used as name. */
809 lttv_attribute_find(tfcs
->current_event_types_tree
,
810 ltt_eventtype_name(ltt_event_eventtype(e
)),
816 static void lttv_stats_cleanup_process_state(LttvTraceState
*ts
,
817 LttvProcessState
*process
)
819 LttvTraceStats
*tcs
= (LttvTraceStats
*)ts
;
820 LttvTracesetContext
*tsc
= ts
->parent
.ts_context
;
822 LttvTracefileStats
**tfs
= (LttvTracefileStats
**)
823 &g_array_index(ts
->parent
.tracefiles
, LttvTracefileContext
*,
825 int cleanup_empty
= 0;
826 LttTime nested_delta
= ltt_time_zero
;
827 /* FIXME : ok, this is a hack. The time is infinite here :( */
828 LttTime save_time
= (*tfs
)->parent
.parent
.timestamp
;
830 ltt_trace_time_span_get(ts
->parent
.t
, &start
, &end
);
831 (*tfs
)->parent
.parent
.timestamp
= end
;
834 if(ltt_time_compare(process
->state
->cum_cpu_time
, ltt_time_zero
) != 0) {
835 find_event_tree(*tfs
, process
->pid_time
,
837 process
->current_function
,
838 process
->state
->t
, process
->state
->n
, &((*tfs
)->current_events_tree
),
839 &((*tfs
)->current_event_types_tree
));
841 nested_delta
= process
->state
->cum_cpu_time
;
843 cleanup_empty
= lttv_state_pop_state_cleanup(process
,
844 (LttvTracefileState
*)*tfs
);
845 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
848 } while(cleanup_empty
!= 1);
850 (*tfs
)->parent
.parent
.timestamp
= save_time
;
853 /* For each cpu, for each of their stacked states,
854 * perform sum of needed values. */
855 static void lttv_stats_cleanup_state(LttvTraceStats
*tcs
)
857 LttvTraceState
*ts
= (LttvTraceState
*)tcs
;
860 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
862 for(i
=0; i
<nb_cpus
; i
++) {
863 lttv_stats_cleanup_process_state(ts
, ts
->running_process
[i
]);
868 lttv_stats_sum_trace(LttvTraceStats
*self
, LttvAttribute
*ts_stats
)
870 LttvAttribute
*sum_container
= self
->stats
;
872 LttvAttributeType type
;
874 LttvAttributeValue value
;
876 LttvAttributeName name
;
884 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
885 nb_event_type
, nf
, nb_functions
;
887 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
888 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
889 *submode_tree
, *event_types_tree
, *mode_events_tree
,
892 *function_mode_types_tree
,
896 main_tree
= sum_container
;
898 lttv_attribute_find(sum_container
,
901 trace_is_summed
= *(value
.v_uint
);
904 /* First cleanup the state : sum all stalled information (never ending
907 lttv_stats_cleanup_state(self
);
909 processes_tree
= lttv_attribute_find_subdir(main_tree
,
910 LTTV_STATS_PROCESSES
);
911 nb_process
= lttv_attribute_get_number(processes_tree
);
913 for(i
= 0 ; i
< nb_process
; i
++) {
914 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
, &is_named
);
915 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
917 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
918 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
920 for(j
= 0 ; j
< nb_cpu
; j
++) {
921 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
, &is_named
);
922 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
924 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
925 trace_cpu_tree
= lttv_attribute_find_subdir_unnamed(trace_cpu_tree
, name
);
926 cpu_functions_tree
= lttv_attribute_find_subdir(cpu_tree
,
927 LTTV_STATS_FUNCTIONS
);
928 nb_functions
= lttv_attribute_get_number(cpu_functions_tree
);
930 for(nf
=0; nf
< nb_functions
; nf
++) {
931 type
= lttv_attribute_get(cpu_functions_tree
, nf
, &name
, &value
,
933 function_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
934 function_mode_types_tree
= lttv_attribute_find_subdir(function_tree
,
935 LTTV_STATS_MODE_TYPES
);
936 nb_mode_type
= lttv_attribute_get_number(function_mode_types_tree
);
937 for(k
= 0 ; k
< nb_mode_type
; k
++) {
938 type
= lttv_attribute_get(function_mode_types_tree
, k
, &name
, &value
,
940 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
942 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
943 LTTV_STATS_SUBMODES
);
944 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
946 mode_types_tree
= lttv_attribute_find_subdir(mode_tree
,
947 LTTV_STATS_MODE_TYPES
);
949 nb_submode
= lttv_attribute_get_number(submodes_tree
);
951 for(l
= 0 ; l
< nb_submode
; l
++) {
952 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
954 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
956 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
957 LTTV_STATS_EVENT_TYPES
);
958 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
961 for(m
= 0 ; m
< nb_event_type
; m
++) {
962 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
,
964 sum
+= *(value
.v_uint
);
966 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
968 *(value
.v_uint
) = sum
;
970 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
972 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
973 if(!trace_is_summed
) {
974 lttv_attribute_recursive_add(mode_events_tree
, event_types_tree
);
975 lttv_attribute_recursive_add(mode_types_tree
, submode_tree
);
978 if(!trace_is_summed
) {
979 lttv_attribute_recursive_add(function_tree
, mode_types_tree
);
982 if(!trace_is_summed
) {
983 lttv_attribute_recursive_add(cpu_tree
, function_tree
);
984 lttv_attribute_recursive_add(process_tree
, function_tree
);
985 lttv_attribute_recursive_add(trace_cpu_tree
, function_tree
);
986 lttv_attribute_recursive_add(main_tree
, function_tree
);
988 lttv_attribute_recursive_add(ts_stats
, function_tree
);
995 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
997 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
1002 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
1004 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1005 LttvAttribute
*sum_container
= self
->stats
;
1007 LttvTraceStats
*tcs
;
1011 LttvAttribute
*main_tree
;
1013 LttvAttributeValue value
;
1015 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
1017 if(*(value
.v_uint
) != 0) return;
1018 *(value
.v_uint
) = 1;
1020 nb_trace
= lttv_traceset_number(traceset
);
1022 for(i
= 0 ; i
< nb_trace
; i
++) {
1023 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
1024 lttv_stats_sum_trace(tcs
, self
->stats
);
1025 // lttv_attribute_recursive_add(sum_container, tcs->stats);
1030 // Hook wrapper. call_data is a traceset context.
1031 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
1033 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1035 lttv_stats_add_event_hooks(tss
);
1040 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
1042 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1044 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1048 LttvTracefileStats
*tfs
;
1050 GArray
*hooks
, *before_hooks
, *after_hooks
;
1052 LttvTraceHook
*hook
;
1054 LttvTraceHookByFacility
*thf
;
1056 LttvAttributeValue val
;
1061 nb_trace
= lttv_traceset_number(traceset
);
1062 for(i
= 0 ; i
< nb_trace
; i
++) {
1063 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1065 /* Find the eventtype id for the following events and register the
1066 associated by id hooks. */
1068 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 12);
1069 g_array_set_size(hooks
, 12);
1072 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1073 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
1074 LTT_FIELD_SYSCALL_ID
, 0, 0,
1075 before_syscall_entry
, NULL
,
1076 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1079 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1080 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
1082 before_syscall_exit
, NULL
,
1083 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1086 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1087 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
1088 LTT_FIELD_TRAP_ID
, 0, 0,
1089 before_trap_entry
, NULL
,
1090 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1093 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1094 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1096 before_trap_exit
, NULL
,
1097 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1100 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1101 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1102 LTT_FIELD_IRQ_ID
, 0, 0,
1103 before_irq_entry
, NULL
,
1104 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1107 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1108 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1110 before_irq_exit
, NULL
,
1111 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1114 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1115 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
1116 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
1117 before_soft_irq_entry
, NULL
,
1118 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1121 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1122 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
1124 before_soft_irq_exit
, NULL
,
1125 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1128 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1129 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
1130 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
1131 before_schedchange
, NULL
,
1132 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1135 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1136 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
1137 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1138 before_function_entry
, NULL
,
1139 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1142 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1143 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
1144 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1145 before_function_exit
, NULL
,
1146 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1149 /* statedump-related hooks */
1150 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1151 LTT_FACILITY_STATEDUMP
, LTT_EVENT_ENUM_PROCESS_STATE
,
1152 LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
1153 before_enum_process_state
, NULL
,
1154 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1157 g_array_set_size(hooks
, hn
);
1159 before_hooks
= hooks
;
1161 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 16);
1162 g_array_set_size(hooks
, 16);
1165 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1166 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
1167 LTT_FIELD_SYSCALL_ID
, 0, 0,
1168 after_syscall_entry
, NULL
,
1169 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1172 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1173 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
1175 after_syscall_exit
, NULL
,
1176 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1179 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1180 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
1181 LTT_FIELD_TRAP_ID
, 0, 0,
1182 after_trap_entry
, NULL
,
1183 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1186 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1187 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1189 after_trap_exit
, NULL
,
1190 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1193 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1194 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1195 LTT_FIELD_IRQ_ID
, 0, 0,
1196 after_irq_entry
, NULL
,
1197 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1200 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1201 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1203 after_irq_exit
, NULL
,
1204 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1207 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1208 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
1209 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
1210 after_irq_entry
, NULL
,
1211 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1214 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1215 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
1217 after_soft_irq_exit
, NULL
,
1218 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1221 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1222 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
1223 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
1224 after_schedchange
, NULL
,
1225 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1228 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1229 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
1230 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1232 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1235 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1236 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
1237 LTT_FIELD_PID
, 0, 0,
1239 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1242 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1243 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
1244 LTT_FIELD_PID
, 0, 0,
1246 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1249 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1250 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
1251 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1252 after_function_entry
, NULL
,
1253 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1256 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1257 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
1258 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1259 after_function_exit
, NULL
,
1260 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1263 /* statedump-related hooks */
1264 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1265 LTT_FACILITY_STATEDUMP
, LTT_EVENT_ENUM_PROCESS_STATE
,
1266 LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
1267 after_enum_process_state
, NULL
,
1268 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1271 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1272 LTT_FACILITY_STATEDUMP
, LTT_EVENT_STATEDUMP_END
,
1274 after_statedump_end
, NULL
,
1275 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1278 g_array_set_size(hooks
, hn
);
1280 after_hooks
= hooks
;
1282 /* Add these hooks to each event_by_id hooks list */
1284 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1286 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1287 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1288 LttvTracefileContext
*, j
));
1289 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
1292 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1293 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1294 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1295 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1297 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1300 LTTV_PRIO_STATS_BEFORE_STATE
);
1303 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1304 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1305 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1306 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1308 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1311 LTTV_PRIO_STATS_AFTER_STATE
);
1315 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1316 LTTV_POINTER
, &val
);
1317 *(val
.v_pointer
) = before_hooks
;
1318 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1319 LTTV_POINTER
, &val
);
1320 *(val
.v_pointer
) = after_hooks
;
1324 // Hook wrapper. call_data is a traceset context.
1325 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1327 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1329 lttv_stats_remove_event_hooks(tss
);
1334 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1336 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1338 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1342 LttvTracefileStats
*tfs
;
1346 GArray
*before_hooks
, *after_hooks
;
1348 LttvTraceHook
*hook
;
1350 LttvTraceHookByFacility
*thf
;
1352 LttvAttributeValue val
;
1354 nb_trace
= lttv_traceset_number(traceset
);
1355 for(i
= 0 ; i
< nb_trace
; i
++) {
1356 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1357 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1358 LTTV_POINTER
, &val
);
1359 before_hooks
= *(val
.v_pointer
);
1360 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1361 LTTV_POINTER
, &val
);
1362 after_hooks
= *(val
.v_pointer
);
1364 /* Remove these hooks from each event_by_id hooks list */
1366 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1368 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1369 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1370 LttvTracefileContext
*, j
));
1371 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1374 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1375 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1376 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1377 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1378 lttv_hooks_remove_data(
1379 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1384 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1385 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1386 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1387 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1388 lttv_hooks_remove_data(
1389 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1395 g_debug("lttv_stats_remove_event_hooks()");
1396 g_array_free(before_hooks
, TRUE
);
1397 g_array_free(after_hooks
, TRUE
);
1402 static void module_init()
1404 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1405 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1406 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1407 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1408 LTTV_STATS_MODES
= g_quark_from_string("modes");
1409 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1410 LTTV_STATS_FUNCTIONS
= g_quark_from_string("functions");
1411 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1412 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1413 LTTV_STATS_CUMULATIVE_CPU_TIME
= g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1414 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time (includes per process waiting time)");
1415 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1416 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1417 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1418 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1419 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1420 LTTV_STATS
= g_quark_from_string("statistics");
1421 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1422 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1425 static void module_destroy()
1430 LTTV_MODULE("stats", "Compute processes statistics", \
1431 "Accumulate statistics for event types, processes and CPUs", \
1432 module_init
, module_destroy
, "state");
1434 /* Change the places where stats are called (create/read/write stats)
1436 Check for options in batchtest.c to reduce writing and see what tests are
1437 best candidates for performance analysis. Once OK, commit, move to main
1438 and run tests. Update the gui for statistics. */