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,
21 #include <lttv/module.h>
22 #include <lttv/stats.h>
23 #include <lttv/lttv.h>
24 #include <lttv/attribute.h>
25 #include <ltt/facility.h>
26 #include <ltt/trace.h>
27 #include <ltt/event.h>
32 LTTV_STATS_PROCESS_UNKNOWN
,
35 LTTV_STATS_MODE_TYPES
,
38 LTTV_STATS_EVENT_TYPES
,
40 LTTV_STATS_ELAPSED_TIME
,
42 LTTV_STATS_EVENTS_COUNT
,
45 LTTV_STATS_TRACEFILES
,
49 LTTV_STATS_BEFORE_HOOKS
,
50 LTTV_STATS_AFTER_HOOKS
;
52 static void remove_all_processes(GHashTable
*processes
);
55 find_event_tree(LttvTracefileStats
*tfcs
, GQuark process
, GQuark cpu
,
56 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
57 LttvAttribute
**event_types_tree
);
60 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
62 guint i
, j
, nb_trace
, nb_tracefile
;
68 LttvTracefileContext
*tfc
;
70 LttvTracefileStats
*tfcs
;
72 LttTime timestamp
= {0,0};
80 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
81 init((LttvTracesetContext
*)self
, ts
);
83 self
->stats
=lttv_attribute_find_subdir(self
->parent
.parent
.ts_a
,LTTV_STATS
);
84 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
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
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
96 tcs
= (LttvTraceStats
*)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
= ltt_trace_control_tracefile_number(tc
->t
) +
110 ltt_trace_per_cpu_tracefile_number(tc
->t
);
112 for(j
= 0 ; j
< nb_tracefile
; j
++) {
113 tfcs
= LTTV_TRACEFILE_STATS(tc
->tracefiles
[j
]);
114 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
115 tfcs
->parent
.cpu_name
);
116 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
117 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
118 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
119 &tfcs
->current_event_types_tree
);
126 fini(LttvTracesetStats
*self
)
128 guint i
, j
, nb_trace
, nb_tracefile
;
132 LttvTraceContext
*tc
;
136 LttvTracefileContext
*tfc
;
138 LttvTracefileStats
*tfcs
;
140 LttTime timestamp
= {0,0};
142 LttvAttributeValue v
;
144 LttvAttribute
*tracefiles_stats
;
146 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
150 if(*(v
.v_uint
) == 0) {
151 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
155 ts
= self
->parent
.parent
.ts
;
156 nb_trace
= lttv_traceset_number(ts
);
158 for(i
= 0 ; i
< nb_trace
; i
++) {
159 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
161 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
165 if(*(v
.v_uint
) == 0) {
166 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
167 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
168 LTTV_STATS_TRACEFILES
);
169 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
170 LTTV_STATS_TRACEFILES
);
174 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
175 ltt_trace_per_cpu_tracefile_number(tc
->t
);
177 for(j
= 0 ; j
< nb_tracefile
; j
++) {
178 tfc
= tc
->tracefiles
[j
];
179 tfcs
= (LttvTracefileStats
*)tfc
;
181 tfcs
->current_events_tree
= NULL
;
182 tfcs
->current_event_types_tree
= NULL
;
185 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
186 fini((LttvTracesetContext
*)self
);
190 static LttvTracesetContext
*
191 new_traceset_context(LttvTracesetContext
*self
)
193 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
197 static LttvTraceContext
*
198 new_trace_context(LttvTracesetContext
*self
)
200 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
204 static LttvTracefileContext
*
205 new_tracefile_context(LttvTracesetContext
*self
)
207 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
212 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
218 traceset_stats_finalize (LttvTracesetStats
*self
)
220 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
221 finalize(G_OBJECT(self
));
226 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
228 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
230 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
231 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
232 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
233 klass
->new_traceset_context
= new_traceset_context
;
234 klass
->new_trace_context
= new_trace_context
;
235 klass
->new_tracefile_context
= new_tracefile_context
;
240 lttv_traceset_stats_get_type(void)
242 static GType type
= 0;
244 static const GTypeInfo info
= {
245 sizeof (LttvTracesetStatsClass
),
246 NULL
, /* base_init */
247 NULL
, /* base_finalize */
248 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
249 NULL
, /* class_finalize */
250 NULL
, /* class_data */
251 sizeof (LttvTracesetStats
),
253 (GInstanceInitFunc
) traceset_stats_instance_init
/* instance_init */
256 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
, "LttvTracesetStatsType",
264 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
270 trace_stats_finalize (LttvTraceStats
*self
)
272 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
273 finalize(G_OBJECT(self
));
278 trace_stats_class_init (LttvTraceContextClass
*klass
)
280 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
282 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
287 lttv_trace_stats_get_type(void)
289 static GType type
= 0;
291 static const GTypeInfo info
= {
292 sizeof (LttvTraceStatsClass
),
293 NULL
, /* base_init */
294 NULL
, /* base_finalize */
295 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
296 NULL
, /* class_finalize */
297 NULL
, /* class_data */
298 sizeof (LttvTraceStats
),
300 (GInstanceInitFunc
) trace_stats_instance_init
/* instance_init */
303 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
304 "LttvTraceStatsType", &info
, 0);
311 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
317 tracefile_stats_finalize (LttvTracefileStats
*self
)
319 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
320 finalize(G_OBJECT(self
));
325 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
327 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
329 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
334 lttv_tracefile_stats_get_type(void)
336 static GType type
= 0;
338 static const GTypeInfo info
= {
339 sizeof (LttvTracefileStatsClass
),
340 NULL
, /* base_init */
341 NULL
, /* base_finalize */
342 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
343 NULL
, /* class_finalize */
344 NULL
, /* class_data */
345 sizeof (LttvTracefileStats
),
347 (GInstanceInitFunc
) tracefile_stats_instance_init
/* instance_init */
350 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
351 "LttvTracefileStatsType", &info
, 0);
358 find_event_tree(LttvTracefileStats
*tfcs
, GQuark process
, GQuark cpu
,
359 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
360 LttvAttribute
**event_types_tree
)
364 LttvTraceStats
*tcs
= LTTV_TRACE_STATS(tfcs
->parent
.parent
.t_context
);
365 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
366 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->pid_time
);
367 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
368 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.cpu_name
);
369 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
370 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->t
);
371 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
372 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->n
);
374 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
375 *event_types_tree
= a
;
379 static void update_event_tree(LttvTracefileStats
*tfcs
)
381 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
383 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
, tfcs
->parent
.cpu_name
,
384 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
385 &(tfcs
->current_event_types_tree
));
389 static void mode_change(LttvTracefileStats
*tfcs
)
391 LttvAttributeValue cpu_time
;
395 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
396 LTTV_TIME
, &cpu_time
);
397 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
398 tfcs
->parent
.process
->state
->change
);
399 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
403 static void mode_end(LttvTracefileStats
*tfcs
)
405 LttvAttributeValue elapsed_time
, cpu_time
;
409 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
410 LTTV_TIME
, &elapsed_time
);
411 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
412 tfcs
->parent
.process
->state
->entry
);
413 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
415 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
416 LTTV_TIME
, &cpu_time
);
417 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
418 tfcs
->parent
.process
->state
->change
);
419 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
423 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
425 mode_change((LttvTracefileStats
*)call_data
);
430 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
432 update_event_tree((LttvTracefileStats
*)call_data
);
437 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
439 mode_end((LttvTracefileStats
*)call_data
);
444 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
446 update_event_tree((LttvTracefileStats
*)call_data
);
451 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
453 mode_change((LttvTracefileStats
*)call_data
);
458 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
460 update_event_tree((LttvTracefileStats
*)call_data
);
465 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
467 mode_end((LttvTracefileStats
*)call_data
);
472 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
474 update_event_tree((LttvTracefileStats
*)call_data
);
479 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
481 mode_change((LttvTracefileStats
*)call_data
);
486 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
488 update_event_tree((LttvTracefileStats
*)call_data
);
493 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
495 mode_end((LttvTracefileStats
*)call_data
);
500 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
502 update_event_tree((LttvTracefileStats
*)call_data
);
507 gboolean
before_schedchange(void *hook_data
, void *call_data
)
509 LttvTraceHook
*h
= (LttvTraceHook
*)hook_data
;
511 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
513 guint pid_in
, pid_out
, state_out
;
515 LttvProcessState
*process
;
517 pid_in
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f1
);
518 pid_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f2
);
519 state_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f3
);
521 /* compute the time for the process to schedule out */
525 /* get the information for the process scheduled in */
527 process
= lttv_state_find_process_or_create(&(tfcs
->parent
), pid_in
);
529 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
530 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
531 &(tfcs
->current_event_types_tree
));
533 /* compute the time waiting for the process to schedule in */
540 gboolean
process_fork(void *hook_data
, void *call_data
)
542 /* nothing to do for now */
547 gboolean
process_exit(void *hook_data
, void *call_data
)
549 /* We should probably exit all modes here or we could do that at
555 gboolean
every_event(void *hook_data
, void *call_data
)
557 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
559 LttvAttributeValue v
;
561 /* The current branch corresponds to the tracefile/process/interrupt state.
562 Statistics are added within it, to count the number of events of this
563 type occuring in this context. A quark has been pre-allocated for each
564 event type and is used as name. */
566 lttv_attribute_find(tfcs
->current_event_types_tree
,
567 ((LttvTraceState
*)(tfcs
->parent
.parent
.t_context
))->
568 eventtype_names
[ltt_event_eventtype_id(tfcs
->parent
.parent
.e
)],
576 lttv_stats_sum_trace(LttvTraceStats
*self
)
580 LttvAttributeType type
;
582 LttvAttributeValue value
;
584 LttvAttributeName name
;
588 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
591 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
592 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
593 *submode_tree
, *event_types_tree
, *mode_events_tree
,
594 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
597 main_tree
= self
->stats
;
599 lttv_attribute_find(self
->parent
.parent
.t_a
, LTTV_STATS_SUMMED
,
601 if(*(value
.v_uint
) != 0) return;
604 processes_tree
= lttv_attribute_find_subdir(main_tree
,
605 LTTV_STATS_PROCESSES
);
606 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
607 nb_process
= lttv_attribute_get_number(processes_tree
);
609 for(i
= 0 ; i
< nb_process
; i
++) {
610 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
611 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
613 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
614 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
616 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
618 for(j
= 0 ; j
< nb_cpu
; j
++) {
619 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
620 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
622 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
623 LTTV_STATS_MODE_TYPES
);
624 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
626 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
627 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
628 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
630 for(k
= 0 ; k
< nb_mode_type
; k
++) {
631 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
632 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
634 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
635 LTTV_STATS_SUBMODES
);
636 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
638 nb_submode
= lttv_attribute_get_number(submodes_tree
);
640 for(l
= 0 ; l
< nb_submode
; l
++) {
641 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
642 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
644 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
645 LTTV_STATS_EVENT_TYPES
);
646 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
649 for(m
= 0 ; m
< nb_event_type
; m
++) {
650 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
651 sum
+= *(value
.v_uint
);
653 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
655 *(value
.v_uint
) = sum
;
656 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
658 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
660 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
661 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
663 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
669 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
671 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
677 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
679 LttvAttributeValue value
;
681 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_SUMMED
,
683 if(*(value
.v_uint
) != 0) return;
686 traceset_modes_tree
= lttv_attribute_find_subdir(self
->stats
,
688 nb_trace
= lttv_traceset_number(traceset
);
690 for(i
= 0 ; i
< nb_trace
; i
++) {
691 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
692 lttv_stats_sum_trace(tcs
);
693 main_tree
= tcs
->stats
;
694 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
695 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
700 lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
702 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
704 guint i
, j
, k
, nb_trace
, nb_tracefile
;
712 LttvTracefileStats
*tfs
;
716 GArray
*hooks
, *before_hooks
, *after_hooks
;
720 LttvAttributeValue val
;
722 nb_trace
= lttv_traceset_number(traceset
);
723 for(i
= 0 ; i
< nb_trace
; i
++) {
724 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
726 /* Find the eventtype id for the following events and register the
727 associated by id hooks. */
729 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
730 g_array_set_size(hooks
, 7);
732 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
733 "syscall_id", NULL
, NULL
, before_syscall_entry
,
734 &g_array_index(hooks
, LttvTraceHook
, 0));
736 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
737 NULL
, NULL
, before_syscall_exit
,
738 &g_array_index(hooks
, LttvTraceHook
, 1));
740 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
741 NULL
, NULL
, before_trap_entry
,
742 &g_array_index(hooks
, LttvTraceHook
, 2));
744 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
745 NULL
, before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
747 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
748 NULL
, NULL
, before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
750 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
751 NULL
, before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
753 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "schedchange", "in",
754 "out", "out_state", before_schedchange
,
755 &g_array_index(hooks
, LttvTraceHook
, 6));
757 before_hooks
= hooks
;
759 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
760 g_array_set_size(hooks
, 8);
762 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
763 "syscall_id", NULL
, NULL
, after_syscall_entry
,
764 &g_array_index(hooks
, LttvTraceHook
, 0));
766 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
767 NULL
, NULL
, after_syscall_exit
,
768 &g_array_index(hooks
, LttvTraceHook
, 1));
770 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
771 NULL
, NULL
, after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
773 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
774 NULL
, after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
776 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
777 NULL
, NULL
, after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
779 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
780 NULL
, after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
782 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_fork",
783 "child_pid", NULL
, NULL
, process_fork
,
784 &g_array_index(hooks
, LttvTraceHook
, 6));
786 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_exit", NULL
,
787 NULL
, NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
791 /* Add these hooks to each event_by_id hooks list */
793 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
794 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
796 for(j
= 0 ; j
< nb_tracefile
; j
++) {
797 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
798 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
801 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
802 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
803 lttv_hooks_add(lttv_hooks_by_id_find(
804 tfs
->parent
.parent
.event_by_id
,
805 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
),
806 LTTV_PRIO_STATS_BEFORE_STATE
);
808 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
809 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
810 lttv_hooks_add(lttv_hooks_by_id_find(
811 tfs
->parent
.parent
.event_by_id
,
812 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
),
813 LTTV_PRIO_STATS_AFTER_STATE
);
816 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
818 *(val
.v_pointer
) = before_hooks
;
819 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
821 *(val
.v_pointer
) = after_hooks
;
826 lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
828 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
830 guint i
, j
, k
, nb_trace
, nb_tracefile
;
834 LttvTracefileStats
*tfs
;
838 GArray
*before_hooks
, *after_hooks
;
842 LttvAttributeValue val
;
844 nb_trace
= lttv_traceset_number(traceset
);
845 for(i
= 0 ; i
< nb_trace
; i
++) {
846 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
847 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
849 before_hooks
= *(val
.v_pointer
);
850 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
852 after_hooks
= *(val
.v_pointer
);
854 /* Remove these hooks from each event_by_id hooks list */
856 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
857 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
859 for(j
= 0 ; j
< nb_tracefile
; j
++) {
860 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
861 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
864 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
865 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
866 lttv_hooks_remove_data(
867 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
868 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
870 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
871 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
872 lttv_hooks_remove_data(
873 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
874 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
877 g_debug("lttv_stats_remove_event_hooks()");
878 g_array_free(before_hooks
, TRUE
);
879 g_array_free(after_hooks
, TRUE
);
884 static void module_init()
886 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
887 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
888 LTTV_STATS_CPU
= g_quark_from_string("cpu");
889 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
890 LTTV_STATS_MODES
= g_quark_from_string("modes");
891 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
892 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
893 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
894 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
895 LTTV_STATS_EVENTS
= g_quark_from_string("events");
896 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
897 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
898 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
899 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
900 LTTV_STATS
= g_quark_from_string("statistics");
901 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
902 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
905 static void module_destroy()
910 LTTV_MODULE("stats", "Compute processes statistics", \
911 "Accumulate statistics for event types, processes and CPUs", \
912 module_init
, module_destroy
, "state");
914 /* Change the places where stats are called (create/read/write stats)
916 Check for options in batchtest.c to reduce writing and see what tests are
917 best candidates for performance analysis. Once OK, commit, move to main
918 and run tests. Update the gui for statistics. */