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>
36 LTTV_STATS_PROCESS_UNKNOWN
,
39 LTTV_STATS_MODE_TYPES
,
42 LTTV_STATS_EVENT_TYPES
,
44 LTTV_STATS_ELAPSED_TIME
,
46 LTTV_STATS_EVENTS_COUNT
,
49 LTTV_STATS_TRACEFILES
,
51 LTTV_STATS_BEFORE_HOOKS
,
52 LTTV_STATS_AFTER_HOOKS
;
55 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, GQuark cpu
,
56 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
57 LttvAttribute
**event_types_tree
);
60 static void lttv_stats_init(LttvTracesetStats
*self
)
62 guint i
, j
, nb_trace
, nb_tracefile
;
68 LttvTracefileContext
*tfc
;
70 LttvTracefileContext
**tfs
;
71 LttvTracefileStats
*tfcs
;
73 LttTime timestamp
= {0,0};
81 LttvTraceset
*ts
= self
->parent
.parent
.ts
;
83 self
->stats
= lttv_attribute_find_subdir(
84 lttv_traceset_attribute(self
->parent
.parent
.ts
),
86 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
91 if(*(v
.v_uint
) == 1) {
92 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
95 nb_trace
= lttv_traceset_number(ts
);
97 for(i
= 0 ; i
< nb_trace
; i
++) {
98 tc
= self
->parent
.parent
.traces
[i
];
99 tcs
= LTTV_TRACE_STATS(tc
);
101 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
102 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
103 LTTV_STATS_TRACEFILES
);
104 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
108 if(*(v
.v_uint
) == 1) {
109 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
112 nb_tracefile
= tc
->tracefiles
->len
;
114 for(j
= 0 ; j
< nb_tracefile
; j
++) {
115 tfs
= &g_array_index(tc
->tracefiles
,
116 LttvTracefileContext
*, j
);
117 tfcs
= LTTV_TRACEFILE_STATS(*tfs
);
118 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
119 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
));
120 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
121 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
122 LTTV_STATE_MODE_UNKNOWN
,
123 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
124 &tfcs
->current_event_types_tree
);
130 static void lttv_stats_fini(LttvTracesetStats
*self
)
132 guint i
, j
, nb_trace
, nb_tracefile
;
136 LttvTraceContext
*tc
;
140 LttvTracefileContext
*tfc
;
142 LttvTracefileStats
*tfcs
;
144 LttTime timestamp
= {0,0};
146 LttvAttributeValue v
;
148 LttvAttribute
*tracefiles_stats
;
150 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
154 if(*(v
.v_uint
) == 0) {
155 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
159 ts
= self
->parent
.parent
.ts
;
160 nb_trace
= lttv_traceset_number(ts
);
162 for(i
= 0 ; i
< nb_trace
; i
++) {
163 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
165 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
169 if(*(v
.v_uint
) == 0) {
170 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
171 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
172 LTTV_STATS_TRACEFILES
);
173 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
174 LTTV_STATS_TRACEFILES
);
178 nb_tracefile
= tc
->tracefiles
->len
;
180 for(j
= 0 ; j
< nb_tracefile
; j
++) {
181 tfc
= g_array_index(tc
->tracefiles
,
182 LttvTracefileContext
*, j
);
183 tfcs
= (LttvTracefileStats
*)tfc
;
185 tfcs
->current_events_tree
= NULL
;
186 tfcs
->current_event_types_tree
= NULL
;
192 void lttv_stats_reset(LttvTracesetStats
*self
)
194 lttv_stats_fini(self
);
195 lttv_stats_init(self
);
201 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
203 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
204 init((LttvTracesetContext
*)self
, ts
);
206 lttv_stats_init(self
);
211 fini(LttvTracesetStats
*self
)
213 lttv_stats_fini(self
);
215 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
216 fini((LttvTracesetContext
*)self
);
220 static LttvTracesetContext
*
221 new_traceset_context(LttvTracesetContext
*self
)
223 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
227 static LttvTraceContext
*
228 new_trace_context(LttvTracesetContext
*self
)
230 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
234 static LttvTracefileContext
*
235 new_tracefile_context(LttvTracesetContext
*self
)
237 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
242 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
248 traceset_stats_finalize (LttvTracesetStats
*self
)
250 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
251 finalize(G_OBJECT(self
));
256 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
258 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
260 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
261 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
262 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
263 klass
->new_traceset_context
= new_traceset_context
;
264 klass
->new_trace_context
= new_trace_context
;
265 klass
->new_tracefile_context
= new_tracefile_context
;
270 lttv_traceset_stats_get_type(void)
272 static GType type
= 0;
274 static const GTypeInfo info
= {
275 sizeof (LttvTracesetStatsClass
),
276 NULL
, /* base_init */
277 NULL
, /* base_finalize */
278 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
279 NULL
, /* class_finalize */
280 NULL
, /* class_data */
281 sizeof (LttvTracesetStats
),
283 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
284 NULL
/* Value handling */
287 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
288 "LttvTracesetStatsType",
296 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
302 trace_stats_finalize (LttvTraceStats
*self
)
304 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
305 finalize(G_OBJECT(self
));
310 trace_stats_class_init (LttvTraceContextClass
*klass
)
312 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
314 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
319 lttv_trace_stats_get_type(void)
321 static GType type
= 0;
323 static const GTypeInfo info
= {
324 sizeof (LttvTraceStatsClass
),
325 NULL
, /* base_init */
326 NULL
, /* base_finalize */
327 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
328 NULL
, /* class_finalize */
329 NULL
, /* class_data */
330 sizeof (LttvTraceStats
),
332 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
333 NULL
/* Value handling */
336 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
337 "LttvTraceStatsType", &info
, 0);
344 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
350 tracefile_stats_finalize (LttvTracefileStats
*self
)
352 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
353 finalize(G_OBJECT(self
));
358 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
360 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
362 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
367 lttv_tracefile_stats_get_type(void)
369 static GType type
= 0;
371 static const GTypeInfo info
= {
372 sizeof (LttvTracefileStatsClass
),
373 NULL
, /* base_init */
374 NULL
, /* base_finalize */
375 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
376 NULL
, /* class_finalize */
377 NULL
, /* class_data */
378 sizeof (LttvTracefileStats
),
380 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
381 NULL
/* Value handling */
384 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
385 "LttvTracefileStatsType", &info
, 0);
392 find_event_tree(LttvTracefileStats
*tfcs
,
397 LttvAttribute
**events_tree
,
398 LttvAttribute
**event_types_tree
)
402 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
403 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
404 a
= lttv_attribute_find_subdir(a
, pid_time
);
405 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
406 a
= lttv_attribute_find_subdir(a
, cpu
);
407 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
408 a
= lttv_attribute_find_subdir(a
, mode
);
409 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
410 a
= lttv_attribute_find_subdir(a
, sub_mode
);
412 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
413 *event_types_tree
= a
;
417 static void update_event_tree(LttvTracefileStats
*tfcs
)
419 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
420 guint cpu
= tfcs
->parent
.cpu
;
421 LttvProcessState
*process
= ts
->running_process
[cpu
];
422 LttvExecutionState
*es
= process
->state
;
424 find_event_tree(tfcs
, process
->pid_time
,
425 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
426 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
427 &(tfcs
->current_event_types_tree
));
431 static void mode_change(LttvTracefileStats
*tfcs
)
433 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
434 guint cpu
= tfcs
->parent
.cpu
;
435 LttvProcessState
*process
= ts
->running_process
[cpu
];
436 LttvAttributeValue cpu_time
;
440 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
441 LTTV_TIME
, &cpu_time
);
442 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
443 process
->state
->change
);
444 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
448 static void mode_end(LttvTracefileStats
*tfcs
)
450 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
451 guint cpu
= tfcs
->parent
.cpu
;
452 LttvProcessState
*process
= ts
->running_process
[cpu
];
453 LttvAttributeValue elapsed_time
, cpu_time
;
457 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
458 LTTV_TIME
, &elapsed_time
);
459 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
460 process
->state
->entry
);
461 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
463 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
464 LTTV_TIME
, &cpu_time
);
465 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
466 process
->state
->change
);
467 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
471 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
473 mode_change((LttvTracefileStats
*)call_data
);
478 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
480 update_event_tree((LttvTracefileStats
*)call_data
);
485 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
487 mode_end((LttvTracefileStats
*)call_data
);
492 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
494 update_event_tree((LttvTracefileStats
*)call_data
);
499 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
501 mode_change((LttvTracefileStats
*)call_data
);
506 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
508 update_event_tree((LttvTracefileStats
*)call_data
);
513 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
515 mode_end((LttvTracefileStats
*)call_data
);
520 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
522 update_event_tree((LttvTracefileStats
*)call_data
);
527 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
529 mode_change((LttvTracefileStats
*)call_data
);
533 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
535 update_event_tree((LttvTracefileStats
*)call_data
);
540 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
542 mode_end((LttvTracefileStats
*)call_data
);
547 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
549 update_event_tree((LttvTracefileStats
*)call_data
);
554 gboolean
before_soft_irq_entry(void *hook_data
, void *call_data
)
556 mode_change((LttvTracefileStats
*)call_data
);
560 gboolean
after_soft_irq_entry(void *hook_data
, void *call_data
)
562 update_event_tree((LttvTracefileStats
*)call_data
);
567 gboolean
before_soft_irq_exit(void *hook_data
, void *call_data
)
569 mode_end((LttvTracefileStats
*)call_data
);
574 gboolean
after_soft_irq_exit(void *hook_data
, void *call_data
)
576 update_event_tree((LttvTracefileStats
*)call_data
);
581 gboolean
before_schedchange(void *hook_data
, void *call_data
)
583 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
585 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
587 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
589 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
591 guint pid_in
, pid_out
;
595 LttvProcessState
*process
;
597 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
598 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
599 state_out
= ltt_event_get_int(e
, thf
->f3
);
601 /* compute the time for the process to schedule out */
605 /* get the information for the process scheduled in */
607 process
= lttv_state_find_process_or_create(ts
,
608 ANY_CPU
, pid_in
, &tfcs
->parent
.parent
.timestamp
);
610 find_event_tree(tfcs
, process
->pid_time
,
611 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
612 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
613 &(tfcs
->current_event_types_tree
));
615 /* compute the time waiting for the process to schedule in */
622 gboolean
process_fork(void *hook_data
, void *call_data
)
624 /* nothing to do for now */
629 gboolean
process_exit(void *hook_data
, void *call_data
)
631 /* We should probably exit all modes here or we could do that at
636 gboolean
process_free(void *hook_data
, void *call_data
)
641 gboolean
every_event(void *hook_data
, void *call_data
)
643 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
645 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
647 LttvAttributeValue v
;
649 /* The current branch corresponds to the tracefile/process/interrupt state.
650 Statistics are added within it, to count the number of events of this
651 type occuring in this context. A quark has been pre-allocated for each
652 event type and is used as name. */
654 lttv_attribute_find(tfcs
->current_event_types_tree
,
655 ltt_eventtype_name(ltt_event_eventtype(e
)),
663 lttv_stats_sum_trace(LttvTraceStats
*self
)
665 LttvAttribute
*sum_container
= self
->stats
;
667 LttvAttributeType type
;
669 LttvAttributeValue value
;
671 LttvAttributeName name
;
675 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
678 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
679 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
680 *submode_tree
, *event_types_tree
, *mode_events_tree
,
681 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
684 main_tree
= sum_container
;
686 lttv_attribute_find(sum_container
,
689 if(*(value
.v_uint
) != 0) return;
692 processes_tree
= lttv_attribute_find_subdir(main_tree
,
693 LTTV_STATS_PROCESSES
);
694 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
,
696 nb_process
= lttv_attribute_get_number(processes_tree
);
698 for(i
= 0 ; i
< nb_process
; i
++) {
699 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
700 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
702 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
703 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
705 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
707 for(j
= 0 ; j
< nb_cpu
; j
++) {
708 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
709 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
711 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
712 LTTV_STATS_MODE_TYPES
);
713 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
715 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
716 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
717 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
719 for(k
= 0 ; k
< nb_mode_type
; k
++) {
720 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
721 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
723 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
724 LTTV_STATS_SUBMODES
);
725 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
727 nb_submode
= lttv_attribute_get_number(submodes_tree
);
729 for(l
= 0 ; l
< nb_submode
; l
++) {
730 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
731 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
733 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
734 LTTV_STATS_EVENT_TYPES
);
735 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
738 for(m
= 0 ; m
< nb_event_type
; m
++) {
739 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
740 sum
+= *(value
.v_uint
);
742 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
744 *(value
.v_uint
) = sum
;
745 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
747 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
749 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
750 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
752 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
757 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
759 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
764 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
766 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
767 LttvAttribute
*sum_container
= self
->stats
;
773 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
775 LttvAttributeValue value
;
777 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
779 if(*(value
.v_uint
) != 0) return;
782 traceset_modes_tree
= lttv_attribute_find_subdir(sum_container
,
784 nb_trace
= lttv_traceset_number(traceset
);
786 for(i
= 0 ; i
< nb_trace
; i
++) {
787 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
788 lttv_stats_sum_trace(tcs
);
789 main_tree
= tcs
->stats
;
790 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
791 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
796 // Hook wrapper. call_data is a traceset context.
797 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
799 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
801 lttv_stats_add_event_hooks(tss
);
806 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
808 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
810 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
814 LttvTracefileStats
*tfs
;
816 GArray
*hooks
, *before_hooks
, *after_hooks
;
820 LttvTraceHookByFacility
*thf
;
822 LttvAttributeValue val
;
826 nb_trace
= lttv_traceset_number(traceset
);
827 for(i
= 0 ; i
< nb_trace
; i
++) {
828 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
830 /* Find the eventtype id for the following events and register the
831 associated by id hooks. */
833 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 9);
834 g_array_set_size(hooks
, 9);
836 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
837 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
838 LTT_FIELD_SYSCALL_ID
, 0, 0,
839 before_syscall_entry
, NULL
,
840 &g_array_index(hooks
, LttvTraceHook
, 0));
843 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
844 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
846 before_syscall_exit
, NULL
,
847 &g_array_index(hooks
, LttvTraceHook
, 1));
850 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
851 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
852 LTT_FIELD_TRAP_ID
, 0, 0,
853 before_trap_entry
, NULL
,
854 &g_array_index(hooks
, LttvTraceHook
, 2));
857 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
858 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
860 before_trap_exit
, NULL
,
861 &g_array_index(hooks
, LttvTraceHook
, 3));
864 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
865 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
866 LTT_FIELD_IRQ_ID
, 0, 0,
867 before_irq_entry
, NULL
,
868 &g_array_index(hooks
, LttvTraceHook
, 4));
871 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
872 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
874 before_irq_exit
, NULL
,
875 &g_array_index(hooks
, LttvTraceHook
, 5));
878 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
879 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
880 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
881 before_soft_irq_entry
, NULL
,
882 &g_array_index(hooks
, LttvTraceHook
, 6));
885 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
886 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
888 before_soft_irq_exit
, NULL
,
889 &g_array_index(hooks
, LttvTraceHook
, 7));
892 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
893 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
894 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
895 before_schedchange
, NULL
,
896 &g_array_index(hooks
, LttvTraceHook
, 8));
899 before_hooks
= hooks
;
901 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
902 g_array_set_size(hooks
, 11);
904 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
905 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
906 LTT_FIELD_SYSCALL_ID
, 0, 0,
907 after_syscall_entry
, NULL
,
908 &g_array_index(hooks
, LttvTraceHook
, 0));
911 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
912 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
914 after_syscall_exit
, NULL
,
915 &g_array_index(hooks
, LttvTraceHook
, 1));
918 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
919 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
920 LTT_FIELD_TRAP_ID
, 0, 0,
921 after_trap_entry
, NULL
,
922 &g_array_index(hooks
, LttvTraceHook
, 2));
925 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
926 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
928 after_trap_exit
, NULL
,
929 &g_array_index(hooks
, LttvTraceHook
, 3));
932 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
933 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
934 LTT_FIELD_IRQ_ID
, 0, 0,
935 after_irq_entry
, NULL
,
936 &g_array_index(hooks
, LttvTraceHook
, 4));
939 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
940 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
942 after_irq_exit
, NULL
,
943 &g_array_index(hooks
, LttvTraceHook
, 5));
946 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
947 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
948 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
949 after_irq_entry
, NULL
,
950 &g_array_index(hooks
, LttvTraceHook
, 6));
953 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
954 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
956 after_soft_irq_exit
, NULL
,
957 &g_array_index(hooks
, LttvTraceHook
, 7));
960 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
961 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
962 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
964 &g_array_index(hooks
, LttvTraceHook
, 8));
967 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
968 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
971 &g_array_index(hooks
, LttvTraceHook
, 9));
974 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
975 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
978 &g_array_index(hooks
, LttvTraceHook
, 10));
984 /* Add these hooks to each event_by_id hooks list */
986 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
988 for(j
= 0 ; j
< nb_tracefile
; j
++) {
989 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
990 LttvTracefileContext
*, j
));
991 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
994 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
995 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
996 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
997 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
999 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1002 LTTV_PRIO_STATS_BEFORE_STATE
);
1005 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1006 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1007 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1008 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1010 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1013 LTTV_PRIO_STATS_AFTER_STATE
);
1017 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1018 LTTV_POINTER
, &val
);
1019 *(val
.v_pointer
) = before_hooks
;
1020 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1021 LTTV_POINTER
, &val
);
1022 *(val
.v_pointer
) = after_hooks
;
1026 // Hook wrapper. call_data is a traceset context.
1027 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1029 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1031 lttv_stats_remove_event_hooks(tss
);
1036 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1038 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1040 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1044 LttvTracefileStats
*tfs
;
1048 GArray
*before_hooks
, *after_hooks
;
1050 LttvTraceHook
*hook
;
1052 LttvTraceHookByFacility
*thf
;
1054 LttvAttributeValue val
;
1056 nb_trace
= lttv_traceset_number(traceset
);
1057 for(i
= 0 ; i
< nb_trace
; i
++) {
1058 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1059 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1060 LTTV_POINTER
, &val
);
1061 before_hooks
= *(val
.v_pointer
);
1062 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1063 LTTV_POINTER
, &val
);
1064 after_hooks
= *(val
.v_pointer
);
1066 /* Remove these hooks from each event_by_id hooks list */
1068 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1070 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1071 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1072 LttvTracefileContext
*, j
));
1073 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1076 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1077 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1078 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1079 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1080 lttv_hooks_remove_data(
1081 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1086 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1087 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1088 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1089 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1090 lttv_hooks_remove_data(
1091 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1097 g_debug("lttv_stats_remove_event_hooks()");
1098 g_array_free(before_hooks
, TRUE
);
1099 g_array_free(after_hooks
, TRUE
);
1104 static void module_init()
1106 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1107 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1108 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1109 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1110 LTTV_STATS_MODES
= g_quark_from_string("modes");
1111 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1112 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1113 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1114 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
1115 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1116 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1117 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1118 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1119 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1120 LTTV_STATS
= g_quark_from_string("statistics");
1121 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1122 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1125 static void module_destroy()
1130 LTTV_MODULE("stats", "Compute processes statistics", \
1131 "Accumulate statistics for event types, processes and CPUs", \
1132 module_init
, module_destroy
, "state");
1134 /* Change the places where stats are called (create/read/write stats)
1136 Check for options in batchtest.c to reduce writing and see what tests are
1137 best candidates for performance analysis. Once OK, commit, move to main
1138 and run tests. Update the gui for statistics. */