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
;
53 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, GQuark cpu
,
54 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
55 LttvAttribute
**event_types_tree
);
58 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
60 guint i
, j
, nb_trace
, nb_tracefile
;
66 LttvTracefileContext
*tfc
;
68 LttvTracefileStats
*tfcs
;
70 LttTime timestamp
= {0,0};
78 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
79 init((LttvTracesetContext
*)self
, ts
);
81 self
->stats
= lttv_attribute_find_subdir(
82 lttv_traceset_attribute(self
->parent
.parent
.ts
),
84 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
89 if(*(v
.v_uint
) == 1) {
90 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
93 nb_trace
= lttv_traceset_number(ts
);
95 for(i
= 0 ; i
< nb_trace
; i
++) {
96 tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
97 tcs
= (LttvTraceStats
*)tc
;
99 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
100 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
101 LTTV_STATS_TRACEFILES
);
102 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
106 if(*(v
.v_uint
) == 1) {
107 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
110 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
111 ltt_trace_per_cpu_tracefile_number(tc
->t
);
113 for(j
= 0 ; j
< nb_tracefile
; j
++) {
114 tfcs
= LTTV_TRACEFILE_STATS(tc
->tracefiles
[j
]);
115 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
116 tfcs
->parent
.cpu_name
);
117 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
118 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
119 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
120 &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 */
254 NULL
/* Value handling */
257 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
258 "LttvTracesetStatsType",
266 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
272 trace_stats_finalize (LttvTraceStats
*self
)
274 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
275 finalize(G_OBJECT(self
));
280 trace_stats_class_init (LttvTraceContextClass
*klass
)
282 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
284 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
289 lttv_trace_stats_get_type(void)
291 static GType type
= 0;
293 static const GTypeInfo info
= {
294 sizeof (LttvTraceStatsClass
),
295 NULL
, /* base_init */
296 NULL
, /* base_finalize */
297 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
298 NULL
, /* class_finalize */
299 NULL
, /* class_data */
300 sizeof (LttvTraceStats
),
302 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
303 NULL
/* Value handling */
306 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
307 "LttvTraceStatsType", &info
, 0);
314 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
320 tracefile_stats_finalize (LttvTracefileStats
*self
)
322 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
323 finalize(G_OBJECT(self
));
328 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
330 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
332 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
337 lttv_tracefile_stats_get_type(void)
339 static GType type
= 0;
341 static const GTypeInfo info
= {
342 sizeof (LttvTracefileStatsClass
),
343 NULL
, /* base_init */
344 NULL
, /* base_finalize */
345 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
346 NULL
, /* class_finalize */
347 NULL
, /* class_data */
348 sizeof (LttvTracefileStats
),
350 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
351 NULL
/* Value handling */
354 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
355 "LttvTracefileStatsType", &info
, 0);
362 find_event_tree(LttvTracefileStats
*tfcs
,
367 LttvAttribute
**events_tree
,
368 LttvAttribute
**event_types_tree
)
372 LttvTraceStats
*tcs
= LTTV_TRACE_STATS(tfcs
->parent
.parent
.t_context
);
373 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
374 a
= lttv_attribute_find_subdir(a
, pid_time
);
375 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
376 a
= lttv_attribute_find_subdir(a
, cpu
);
377 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
378 a
= lttv_attribute_find_subdir(a
, mode
);
379 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
380 a
= lttv_attribute_find_subdir(a
, sub_mode
);
382 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
383 *event_types_tree
= a
;
387 static void update_event_tree(LttvTracefileStats
*tfcs
)
389 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
391 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
,
392 tfcs
->parent
.cpu_name
,
393 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
394 &(tfcs
->current_event_types_tree
));
398 static void mode_change(LttvTracefileStats
*tfcs
)
400 LttvAttributeValue cpu_time
;
404 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
405 LTTV_TIME
, &cpu_time
);
406 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
407 tfcs
->parent
.process
->state
->change
);
408 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
412 static void mode_end(LttvTracefileStats
*tfcs
)
414 LttvAttributeValue elapsed_time
, cpu_time
;
418 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
419 LTTV_TIME
, &elapsed_time
);
420 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
421 tfcs
->parent
.process
->state
->entry
);
422 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
424 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
425 LTTV_TIME
, &cpu_time
);
426 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
427 tfcs
->parent
.process
->state
->change
);
428 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
432 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
434 mode_change((LttvTracefileStats
*)call_data
);
439 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
441 update_event_tree((LttvTracefileStats
*)call_data
);
446 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
448 mode_end((LttvTracefileStats
*)call_data
);
453 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
455 update_event_tree((LttvTracefileStats
*)call_data
);
460 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
462 mode_change((LttvTracefileStats
*)call_data
);
467 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
469 update_event_tree((LttvTracefileStats
*)call_data
);
474 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
476 mode_end((LttvTracefileStats
*)call_data
);
481 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
483 update_event_tree((LttvTracefileStats
*)call_data
);
488 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
490 mode_change((LttvTracefileStats
*)call_data
);
495 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
497 update_event_tree((LttvTracefileStats
*)call_data
);
502 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
504 mode_end((LttvTracefileStats
*)call_data
);
509 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
511 update_event_tree((LttvTracefileStats
*)call_data
);
516 gboolean
before_schedchange(void *hook_data
, void *call_data
)
518 LttvTraceHook
*h
= (LttvTraceHook
*)hook_data
;
520 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
522 guint pid_in
, pid_out
, state_out
;
524 LttvProcessState
*process
;
526 pid_in
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f1
);
527 pid_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f2
);
528 state_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f3
);
530 /* compute the time for the process to schedule out */
534 /* get the information for the process scheduled in */
536 process
= lttv_state_find_process_or_create(&(tfcs
->parent
), pid_in
);
538 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
539 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
540 &(tfcs
->current_event_types_tree
));
542 /* compute the time waiting for the process to schedule in */
549 gboolean
process_fork(void *hook_data
, void *call_data
)
551 /* nothing to do for now */
556 gboolean
process_exit(void *hook_data
, void *call_data
)
558 /* We should probably exit all modes here or we could do that at
564 gboolean
every_event(void *hook_data
, void *call_data
)
566 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
568 LttvAttributeValue v
;
570 /* The current branch corresponds to the tracefile/process/interrupt state.
571 Statistics are added within it, to count the number of events of this
572 type occuring in this context. A quark has been pre-allocated for each
573 event type and is used as name. */
575 lttv_attribute_find(tfcs
->current_event_types_tree
,
576 ((LttvTraceState
*)(tfcs
->parent
.parent
.t_context
))->
577 eventtype_names
[ltt_event_eventtype_id(tfcs
->parent
.parent
.e
)],
585 lttv_stats_sum_trace(LttvTraceStats
*self
)
587 LttvAttribute
*sum_container
= self
->stats
;
589 LttvAttributeType type
;
591 LttvAttributeValue value
;
593 LttvAttributeName name
;
597 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
600 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
601 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
602 *submode_tree
, *event_types_tree
, *mode_events_tree
,
603 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
606 main_tree
= sum_container
;
608 lttv_attribute_find(sum_container
,
611 if(*(value
.v_uint
) != 0) return;
614 processes_tree
= lttv_attribute_find_subdir(main_tree
,
615 LTTV_STATS_PROCESSES
);
616 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
,
618 nb_process
= lttv_attribute_get_number(processes_tree
);
620 for(i
= 0 ; i
< nb_process
; i
++) {
621 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
622 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
624 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
625 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
627 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
629 for(j
= 0 ; j
< nb_cpu
; j
++) {
630 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
631 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
633 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
634 LTTV_STATS_MODE_TYPES
);
635 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
637 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
638 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
639 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
641 for(k
= 0 ; k
< nb_mode_type
; k
++) {
642 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
643 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
645 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
646 LTTV_STATS_SUBMODES
);
647 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
649 nb_submode
= lttv_attribute_get_number(submodes_tree
);
651 for(l
= 0 ; l
< nb_submode
; l
++) {
652 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
653 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
655 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
656 LTTV_STATS_EVENT_TYPES
);
657 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
660 for(m
= 0 ; m
< nb_event_type
; m
++) {
661 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
662 sum
+= *(value
.v_uint
);
664 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
666 *(value
.v_uint
) = sum
;
667 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
669 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
671 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
672 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
674 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
679 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
681 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
686 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
688 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
689 LttvAttribute
*sum_container
= self
->stats
;
695 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
697 LttvAttributeValue value
;
699 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
701 if(*(value
.v_uint
) != 0) return;
704 traceset_modes_tree
= lttv_attribute_find_subdir(sum_container
,
706 nb_trace
= lttv_traceset_number(traceset
);
708 for(i
= 0 ; i
< nb_trace
; i
++) {
709 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
710 lttv_stats_sum_trace(tcs
);
711 main_tree
= tcs
->stats
;
712 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
713 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
718 // Hook wrapper. call_data is a traceset context.
719 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
721 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
723 lttv_stats_add_event_hooks(tss
);
728 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
730 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
732 guint i
, j
, k
, nb_trace
, nb_tracefile
;
740 LttvTracefileStats
*tfs
;
744 GArray
*hooks
, *before_hooks
, *after_hooks
;
748 LttvAttributeValue val
;
750 nb_trace
= lttv_traceset_number(traceset
);
751 for(i
= 0 ; i
< nb_trace
; i
++) {
752 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
754 /* Find the eventtype id for the following events and register the
755 associated by id hooks. */
757 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
758 g_array_set_size(hooks
, 7);
760 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
761 "syscall_id", NULL
, NULL
, before_syscall_entry
,
762 &g_array_index(hooks
, LttvTraceHook
, 0));
764 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
765 NULL
, NULL
, before_syscall_exit
,
766 &g_array_index(hooks
, LttvTraceHook
, 1));
768 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
769 NULL
, NULL
, before_trap_entry
,
770 &g_array_index(hooks
, LttvTraceHook
, 2));
772 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
773 NULL
, before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
775 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
776 NULL
, NULL
, before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
778 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
779 NULL
, before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
781 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "schedchange", "in",
782 "out", "out_state", before_schedchange
,
783 &g_array_index(hooks
, LttvTraceHook
, 6));
785 before_hooks
= hooks
;
787 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
788 g_array_set_size(hooks
, 8);
790 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
791 "syscall_id", NULL
, NULL
, after_syscall_entry
,
792 &g_array_index(hooks
, LttvTraceHook
, 0));
794 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
795 NULL
, NULL
, after_syscall_exit
,
796 &g_array_index(hooks
, LttvTraceHook
, 1));
798 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
799 NULL
, NULL
, after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
801 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
802 NULL
, after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
804 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
805 NULL
, NULL
, after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
807 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
808 NULL
, after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
810 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_fork",
811 "child_pid", NULL
, NULL
, process_fork
,
812 &g_array_index(hooks
, LttvTraceHook
, 6));
814 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_exit", NULL
,
815 NULL
, NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
819 /* Add these hooks to each event_by_id hooks list */
821 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
822 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
824 for(j
= 0 ; j
< nb_tracefile
; j
++) {
825 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
826 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
829 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
830 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
831 lttv_hooks_add(lttv_hooks_by_id_find(
832 tfs
->parent
.parent
.event_by_id
,
833 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
),
834 LTTV_PRIO_STATS_BEFORE_STATE
);
836 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
837 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
838 lttv_hooks_add(lttv_hooks_by_id_find(
839 tfs
->parent
.parent
.event_by_id
,
840 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
),
841 LTTV_PRIO_STATS_AFTER_STATE
);
844 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
846 *(val
.v_pointer
) = before_hooks
;
847 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
849 *(val
.v_pointer
) = after_hooks
;
853 // Hook wrapper. call_data is a traceset context.
854 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
856 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
858 lttv_stats_remove_event_hooks(tss
);
863 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
865 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
867 guint i
, j
, k
, nb_trace
, nb_tracefile
;
871 LttvTracefileStats
*tfs
;
875 GArray
*before_hooks
, *after_hooks
;
879 LttvAttributeValue val
;
881 nb_trace
= lttv_traceset_number(traceset
);
882 for(i
= 0 ; i
< nb_trace
; i
++) {
883 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
884 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
886 before_hooks
= *(val
.v_pointer
);
887 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
889 after_hooks
= *(val
.v_pointer
);
891 /* Remove these hooks from each event_by_id hooks list */
893 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
894 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
896 for(j
= 0 ; j
< nb_tracefile
; j
++) {
897 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
898 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
901 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
902 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
903 lttv_hooks_remove_data(
904 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
905 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
907 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
908 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
909 lttv_hooks_remove_data(
910 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
911 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
914 g_debug("lttv_stats_remove_event_hooks()");
915 g_array_free(before_hooks
, TRUE
);
916 g_array_free(after_hooks
, TRUE
);
921 static void module_init()
923 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
924 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
925 LTTV_STATS_CPU
= g_quark_from_string("cpu");
926 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
927 LTTV_STATS_MODES
= g_quark_from_string("modes");
928 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
929 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
930 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
931 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
932 LTTV_STATS_EVENTS
= g_quark_from_string("events");
933 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
934 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
935 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
936 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
937 LTTV_STATS
= g_quark_from_string("statistics");
938 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
939 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
942 static void module_destroy()
947 LTTV_MODULE("stats", "Compute processes statistics", \
948 "Accumulate statistics for event types, processes and CPUs", \
949 module_init
, module_destroy
, "state");
951 /* Change the places where stats are called (create/read/write stats)
953 Check for options in batchtest.c to reduce writing and see what tests are
954 best candidates for performance analysis. Once OK, commit, move to main
955 and run tests. Update the gui for statistics. */