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
,
43 LTTV_STATS_EVENT_TYPES
,
45 LTTV_STATS_ELAPSED_TIME
,
47 LTTV_STATS_EVENTS_COUNT
,
50 LTTV_STATS_TRACEFILES
,
52 LTTV_STATS_BEFORE_HOOKS
,
53 LTTV_STATS_AFTER_HOOKS
;
56 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, GQuark cpu
,
57 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
58 LttvAttribute
**event_types_tree
);
61 static void lttv_stats_init(LttvTracesetStats
*self
)
63 guint i
, j
, nb_trace
, nb_tracefile
;
69 LttvTracefileContext
*tfc
;
71 LttvTracefileContext
**tfs
;
72 LttvTracefileStats
*tfcs
;
74 LttTime timestamp
= {0,0};
82 LttvTraceset
*ts
= self
->parent
.parent
.ts
;
84 self
->stats
= lttv_attribute_find_subdir(
85 lttv_traceset_attribute(self
->parent
.parent
.ts
),
87 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
92 if(*(v
.v_uint
) == 1) {
93 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
96 nb_trace
= lttv_traceset_number(ts
);
98 for(i
= 0 ; i
< nb_trace
; i
++) {
99 tc
= self
->parent
.parent
.traces
[i
];
100 tcs
= LTTV_TRACE_STATS(tc
);
102 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
103 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
104 LTTV_STATS_TRACEFILES
);
105 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
109 if(*(v
.v_uint
) == 1) {
110 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
113 nb_tracefile
= tc
->tracefiles
->len
;
115 for(j
= 0 ; j
< nb_tracefile
; j
++) {
116 tfs
= &g_array_index(tc
->tracefiles
,
117 LttvTracefileContext
*, j
);
118 tfcs
= LTTV_TRACEFILE_STATS(*tfs
);
119 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
120 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
));
121 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
122 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
123 LTTV_STATE_MODE_UNKNOWN
,
124 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
125 &tfcs
->current_event_types_tree
);
131 static void lttv_stats_fini(LttvTracesetStats
*self
)
133 guint i
, j
, nb_trace
, nb_tracefile
;
137 LttvTraceContext
*tc
;
141 LttvTracefileContext
*tfc
;
143 LttvTracefileStats
*tfcs
;
145 LttTime timestamp
= {0,0};
147 LttvAttributeValue v
;
149 LttvAttribute
*tracefiles_stats
;
151 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
155 if(*(v
.v_uint
) == 0) {
156 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
160 ts
= self
->parent
.parent
.ts
;
161 nb_trace
= lttv_traceset_number(ts
);
163 for(i
= 0 ; i
< nb_trace
; i
++) {
164 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
166 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
170 if(*(v
.v_uint
) == 0) {
171 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
172 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
173 LTTV_STATS_TRACEFILES
);
174 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
175 LTTV_STATS_TRACEFILES
);
179 nb_tracefile
= tc
->tracefiles
->len
;
181 for(j
= 0 ; j
< nb_tracefile
; j
++) {
182 tfc
= g_array_index(tc
->tracefiles
,
183 LttvTracefileContext
*, j
);
184 tfcs
= (LttvTracefileStats
*)tfc
;
186 tfcs
->current_events_tree
= NULL
;
187 tfcs
->current_event_types_tree
= NULL
;
193 void lttv_stats_reset(LttvTracesetStats
*self
)
195 lttv_stats_fini(self
);
196 lttv_stats_init(self
);
202 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
204 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
205 init((LttvTracesetContext
*)self
, ts
);
207 lttv_stats_init(self
);
212 fini(LttvTracesetStats
*self
)
214 lttv_stats_fini(self
);
216 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
217 fini((LttvTracesetContext
*)self
);
221 static LttvTracesetContext
*
222 new_traceset_context(LttvTracesetContext
*self
)
224 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
228 static LttvTraceContext
*
229 new_trace_context(LttvTracesetContext
*self
)
231 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
235 static LttvTracefileContext
*
236 new_tracefile_context(LttvTracesetContext
*self
)
238 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
243 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
249 traceset_stats_finalize (LttvTracesetStats
*self
)
251 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
252 finalize(G_OBJECT(self
));
257 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
259 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
261 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
262 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
263 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
264 klass
->new_traceset_context
= new_traceset_context
;
265 klass
->new_trace_context
= new_trace_context
;
266 klass
->new_tracefile_context
= new_tracefile_context
;
271 lttv_traceset_stats_get_type(void)
273 static GType type
= 0;
275 static const GTypeInfo info
= {
276 sizeof (LttvTracesetStatsClass
),
277 NULL
, /* base_init */
278 NULL
, /* base_finalize */
279 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
280 NULL
, /* class_finalize */
281 NULL
, /* class_data */
282 sizeof (LttvTracesetStats
),
284 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
285 NULL
/* Value handling */
288 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
289 "LttvTracesetStatsType",
297 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
303 trace_stats_finalize (LttvTraceStats
*self
)
305 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
306 finalize(G_OBJECT(self
));
311 trace_stats_class_init (LttvTraceContextClass
*klass
)
313 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
315 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
320 lttv_trace_stats_get_type(void)
322 static GType type
= 0;
324 static const GTypeInfo info
= {
325 sizeof (LttvTraceStatsClass
),
326 NULL
, /* base_init */
327 NULL
, /* base_finalize */
328 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
329 NULL
, /* class_finalize */
330 NULL
, /* class_data */
331 sizeof (LttvTraceStats
),
333 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
334 NULL
/* Value handling */
337 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
338 "LttvTraceStatsType", &info
, 0);
345 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
351 tracefile_stats_finalize (LttvTracefileStats
*self
)
353 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
354 finalize(G_OBJECT(self
));
359 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
361 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
363 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
368 lttv_tracefile_stats_get_type(void)
370 static GType type
= 0;
372 static const GTypeInfo info
= {
373 sizeof (LttvTracefileStatsClass
),
374 NULL
, /* base_init */
375 NULL
, /* base_finalize */
376 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
377 NULL
, /* class_finalize */
378 NULL
, /* class_data */
379 sizeof (LttvTracefileStats
),
381 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
382 NULL
/* Value handling */
385 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
386 "LttvTracefileStatsType", &info
, 0);
393 find_event_tree(LttvTracefileStats
*tfcs
,
398 LttvAttribute
**events_tree
,
399 LttvAttribute
**event_types_tree
)
403 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
404 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
405 a
= lttv_attribute_find_subdir(a
, pid_time
);
406 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
407 a
= lttv_attribute_find_subdir(a
, cpu
);
408 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
409 a
= lttv_attribute_find_subdir(a
, mode
);
410 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
411 a
= lttv_attribute_find_subdir(a
, sub_mode
);
413 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
414 *event_types_tree
= a
;
418 static void update_event_tree(LttvTracefileStats
*tfcs
)
420 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
421 guint cpu
= tfcs
->parent
.cpu
;
422 LttvProcessState
*process
= ts
->running_process
[cpu
];
423 LttvExecutionState
*es
= process
->state
;
425 find_event_tree(tfcs
, process
->pid_time
,
426 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
427 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
428 &(tfcs
->current_event_types_tree
));
432 static void mode_change(LttvTracefileStats
*tfcs
)
434 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
435 guint cpu
= tfcs
->parent
.cpu
;
436 LttvProcessState
*process
= ts
->running_process
[cpu
];
437 LttvAttributeValue cpu_time
;
441 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
442 LTTV_TIME
, &cpu_time
);
443 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
444 process
->state
->change
);
445 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
449 static void mode_end(LttvTracefileStats
*tfcs
)
451 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
452 guint cpu
= tfcs
->parent
.cpu
;
453 LttvProcessState
*process
= ts
->running_process
[cpu
];
454 LttvAttributeValue elapsed_time
, cpu_time
;
458 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
459 LTTV_TIME
, &elapsed_time
);
460 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
461 process
->state
->entry
);
462 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
464 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
465 LTTV_TIME
, &cpu_time
);
466 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
467 process
->state
->change
);
468 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
472 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
474 mode_change((LttvTracefileStats
*)call_data
);
479 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
481 update_event_tree((LttvTracefileStats
*)call_data
);
486 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
488 mode_end((LttvTracefileStats
*)call_data
);
493 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
495 update_event_tree((LttvTracefileStats
*)call_data
);
500 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
502 mode_change((LttvTracefileStats
*)call_data
);
507 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
509 update_event_tree((LttvTracefileStats
*)call_data
);
514 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
516 mode_end((LttvTracefileStats
*)call_data
);
521 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
523 update_event_tree((LttvTracefileStats
*)call_data
);
528 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
530 mode_change((LttvTracefileStats
*)call_data
);
534 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
536 update_event_tree((LttvTracefileStats
*)call_data
);
541 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
543 mode_end((LttvTracefileStats
*)call_data
);
548 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
550 update_event_tree((LttvTracefileStats
*)call_data
);
555 gboolean
before_soft_irq_entry(void *hook_data
, void *call_data
)
557 mode_change((LttvTracefileStats
*)call_data
);
561 gboolean
after_soft_irq_entry(void *hook_data
, void *call_data
)
563 update_event_tree((LttvTracefileStats
*)call_data
);
568 gboolean
before_soft_irq_exit(void *hook_data
, void *call_data
)
570 mode_end((LttvTracefileStats
*)call_data
);
575 gboolean
after_soft_irq_exit(void *hook_data
, void *call_data
)
577 update_event_tree((LttvTracefileStats
*)call_data
);
582 gboolean
before_schedchange(void *hook_data
, void *call_data
)
584 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
586 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
588 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
590 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
592 guint pid_in
, pid_out
;
596 LttvProcessState
*process
;
598 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
599 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
600 state_out
= ltt_event_get_int(e
, thf
->f3
);
602 /* compute the time for the process to schedule out */
606 /* get the information for the process scheduled in */
608 process
= lttv_state_find_process_or_create(ts
,
609 ANY_CPU
, pid_in
, &tfcs
->parent
.parent
.timestamp
);
611 find_event_tree(tfcs
, process
->pid_time
,
612 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
613 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
614 &(tfcs
->current_event_types_tree
));
616 /* compute the time waiting for the process to schedule in */
623 gboolean
process_fork(void *hook_data
, void *call_data
)
625 /* nothing to do for now */
630 gboolean
process_exit(void *hook_data
, void *call_data
)
632 /* We should probably exit all modes here or we could do that at
637 gboolean
process_free(void *hook_data
, void *call_data
)
642 gboolean
every_event(void *hook_data
, void *call_data
)
644 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
646 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
648 LttvAttributeValue v
;
650 /* The current branch corresponds to the tracefile/process/interrupt state.
651 Statistics are added within it, to count the number of events of this
652 type occuring in this context. A quark has been pre-allocated for each
653 event type and is used as name. */
655 lttv_attribute_find(tfcs
->current_event_types_tree
,
656 ltt_eventtype_name(ltt_event_eventtype(e
)),
664 lttv_stats_sum_trace(LttvTraceStats
*self
)
666 LttvAttribute
*sum_container
= self
->stats
;
668 LttvAttributeType type
;
670 LttvAttributeValue value
;
672 LttvAttributeName name
;
676 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
679 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
680 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
681 *submode_tree
, *event_types_tree
, *mode_events_tree
,
682 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
685 main_tree
= sum_container
;
687 lttv_attribute_find(sum_container
,
690 if(*(value
.v_uint
) != 0) return;
693 processes_tree
= lttv_attribute_find_subdir(main_tree
,
694 LTTV_STATS_PROCESSES
);
695 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
,
697 nb_process
= lttv_attribute_get_number(processes_tree
);
699 for(i
= 0 ; i
< nb_process
; i
++) {
700 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
701 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
703 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
704 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
706 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
708 for(j
= 0 ; j
< nb_cpu
; j
++) {
709 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
710 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
712 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
713 LTTV_STATS_MODE_TYPES
);
714 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
716 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
717 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
718 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
720 for(k
= 0 ; k
< nb_mode_type
; k
++) {
721 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
722 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
724 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
725 LTTV_STATS_SUBMODES
);
726 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
728 nb_submode
= lttv_attribute_get_number(submodes_tree
);
730 for(l
= 0 ; l
< nb_submode
; l
++) {
731 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
732 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
734 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
735 LTTV_STATS_EVENT_TYPES
);
736 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
739 for(m
= 0 ; m
< nb_event_type
; m
++) {
740 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
741 sum
+= *(value
.v_uint
);
743 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
745 *(value
.v_uint
) = sum
;
746 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
748 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
750 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
751 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
753 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
758 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
760 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
765 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
767 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
768 LttvAttribute
*sum_container
= self
->stats
;
774 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
776 LttvAttributeValue value
;
778 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
780 if(*(value
.v_uint
) != 0) return;
783 traceset_modes_tree
= lttv_attribute_find_subdir(sum_container
,
785 nb_trace
= lttv_traceset_number(traceset
);
787 for(i
= 0 ; i
< nb_trace
; i
++) {
788 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
789 lttv_stats_sum_trace(tcs
);
790 main_tree
= tcs
->stats
;
791 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
792 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
797 // Hook wrapper. call_data is a traceset context.
798 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
800 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
802 lttv_stats_add_event_hooks(tss
);
807 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
809 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
811 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
815 LttvTracefileStats
*tfs
;
817 GArray
*hooks
, *before_hooks
, *after_hooks
;
821 LttvTraceHookByFacility
*thf
;
823 LttvAttributeValue val
;
827 nb_trace
= lttv_traceset_number(traceset
);
828 for(i
= 0 ; i
< nb_trace
; i
++) {
829 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
831 /* Find the eventtype id for the following events and register the
832 associated by id hooks. */
834 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 9);
835 g_array_set_size(hooks
, 9);
837 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
838 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
839 LTT_FIELD_SYSCALL_ID
, 0, 0,
840 before_syscall_entry
, NULL
,
841 &g_array_index(hooks
, LttvTraceHook
, 0));
844 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
845 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
847 before_syscall_exit
, NULL
,
848 &g_array_index(hooks
, LttvTraceHook
, 1));
851 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
852 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
853 LTT_FIELD_TRAP_ID
, 0, 0,
854 before_trap_entry
, NULL
,
855 &g_array_index(hooks
, LttvTraceHook
, 2));
858 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
859 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
861 before_trap_exit
, NULL
,
862 &g_array_index(hooks
, LttvTraceHook
, 3));
865 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
866 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
867 LTT_FIELD_IRQ_ID
, 0, 0,
868 before_irq_entry
, NULL
,
869 &g_array_index(hooks
, LttvTraceHook
, 4));
872 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
873 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
875 before_irq_exit
, NULL
,
876 &g_array_index(hooks
, LttvTraceHook
, 5));
879 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
880 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
881 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
882 before_soft_irq_entry
, NULL
,
883 &g_array_index(hooks
, LttvTraceHook
, 6));
886 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
887 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
889 before_soft_irq_exit
, NULL
,
890 &g_array_index(hooks
, LttvTraceHook
, 7));
893 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
894 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
895 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
896 before_schedchange
, NULL
,
897 &g_array_index(hooks
, LttvTraceHook
, 8));
900 before_hooks
= hooks
;
902 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
903 g_array_set_size(hooks
, 11);
905 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
906 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
907 LTT_FIELD_SYSCALL_ID
, 0, 0,
908 after_syscall_entry
, NULL
,
909 &g_array_index(hooks
, LttvTraceHook
, 0));
912 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
913 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
915 after_syscall_exit
, NULL
,
916 &g_array_index(hooks
, LttvTraceHook
, 1));
919 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
920 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
921 LTT_FIELD_TRAP_ID
, 0, 0,
922 after_trap_entry
, NULL
,
923 &g_array_index(hooks
, LttvTraceHook
, 2));
926 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
927 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
929 after_trap_exit
, NULL
,
930 &g_array_index(hooks
, LttvTraceHook
, 3));
933 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
934 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
935 LTT_FIELD_IRQ_ID
, 0, 0,
936 after_irq_entry
, NULL
,
937 &g_array_index(hooks
, LttvTraceHook
, 4));
940 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
941 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
943 after_irq_exit
, NULL
,
944 &g_array_index(hooks
, LttvTraceHook
, 5));
947 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
948 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
949 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
950 after_irq_entry
, NULL
,
951 &g_array_index(hooks
, LttvTraceHook
, 6));
954 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
955 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
957 after_soft_irq_exit
, NULL
,
958 &g_array_index(hooks
, LttvTraceHook
, 7));
961 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
962 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
963 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
965 &g_array_index(hooks
, LttvTraceHook
, 8));
968 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
969 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
972 &g_array_index(hooks
, LttvTraceHook
, 9));
975 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
976 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
979 &g_array_index(hooks
, LttvTraceHook
, 10));
985 /* Add these hooks to each event_by_id hooks list */
987 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
989 for(j
= 0 ; j
< nb_tracefile
; j
++) {
990 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
991 LttvTracefileContext
*, j
));
992 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
995 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
996 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
997 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
998 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1000 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1003 LTTV_PRIO_STATS_BEFORE_STATE
);
1006 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1007 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1008 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1009 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1011 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1014 LTTV_PRIO_STATS_AFTER_STATE
);
1018 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1019 LTTV_POINTER
, &val
);
1020 *(val
.v_pointer
) = before_hooks
;
1021 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1022 LTTV_POINTER
, &val
);
1023 *(val
.v_pointer
) = after_hooks
;
1027 // Hook wrapper. call_data is a traceset context.
1028 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1030 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1032 lttv_stats_remove_event_hooks(tss
);
1037 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1039 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1041 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1045 LttvTracefileStats
*tfs
;
1049 GArray
*before_hooks
, *after_hooks
;
1051 LttvTraceHook
*hook
;
1053 LttvTraceHookByFacility
*thf
;
1055 LttvAttributeValue val
;
1057 nb_trace
= lttv_traceset_number(traceset
);
1058 for(i
= 0 ; i
< nb_trace
; i
++) {
1059 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1060 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1061 LTTV_POINTER
, &val
);
1062 before_hooks
= *(val
.v_pointer
);
1063 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1064 LTTV_POINTER
, &val
);
1065 after_hooks
= *(val
.v_pointer
);
1067 /* Remove these hooks from each event_by_id hooks list */
1069 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1071 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1072 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1073 LttvTracefileContext
*, j
));
1074 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1077 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1078 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1079 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1080 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1081 lttv_hooks_remove_data(
1082 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1087 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1088 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1089 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1090 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1091 lttv_hooks_remove_data(
1092 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1098 g_debug("lttv_stats_remove_event_hooks()");
1099 g_array_free(before_hooks
, TRUE
);
1100 g_array_free(after_hooks
, TRUE
);
1105 static void module_init()
1107 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1108 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1109 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1110 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1111 LTTV_STATS_MODES
= g_quark_from_string("modes");
1112 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1113 LTTV_STATS_SUBMODES
= g_quark_from_string("functions");
1114 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1115 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1116 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
1117 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1118 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1119 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1120 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1121 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1122 LTTV_STATS
= g_quark_from_string("statistics");
1123 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1124 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1127 static void module_destroy()
1132 LTTV_MODULE("stats", "Compute processes statistics", \
1133 "Accumulate statistics for event types, processes and CPUs", \
1134 module_init
, module_destroy
, "state");
1136 /* Change the places where stats are called (create/read/write stats)
1138 Check for options in batchtest.c to reduce writing and see what tests are
1139 best candidates for performance analysis. Once OK, commit, move to main
1140 and run tests. Update the gui for statistics. */