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
;
828 nb_trace
= lttv_traceset_number(traceset
);
829 for(i
= 0 ; i
< nb_trace
; i
++) {
830 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
832 /* Find the eventtype id for the following events and register the
833 associated by id hooks. */
835 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 9);
836 g_array_set_size(hooks
, 9);
839 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
840 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
841 LTT_FIELD_SYSCALL_ID
, 0, 0,
842 before_syscall_entry
, NULL
,
843 &g_array_index(hooks
, LttvTraceHook
, hn
++));
846 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
847 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
849 before_syscall_exit
, NULL
,
850 &g_array_index(hooks
, LttvTraceHook
, hn
++));
853 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
854 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
855 LTT_FIELD_TRAP_ID
, 0, 0,
856 before_trap_entry
, NULL
,
857 &g_array_index(hooks
, LttvTraceHook
, hn
++));
860 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
861 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
863 before_trap_exit
, NULL
,
864 &g_array_index(hooks
, LttvTraceHook
, hn
++));
867 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
868 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
869 LTT_FIELD_IRQ_ID
, 0, 0,
870 before_irq_entry
, NULL
,
871 &g_array_index(hooks
, LttvTraceHook
, hn
++));
874 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
875 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
877 before_irq_exit
, NULL
,
878 &g_array_index(hooks
, LttvTraceHook
, hn
++));
881 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
882 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
883 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
884 before_soft_irq_entry
, NULL
,
885 &g_array_index(hooks
, LttvTraceHook
, hn
++));
888 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
889 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
891 before_soft_irq_exit
, NULL
,
892 &g_array_index(hooks
, LttvTraceHook
, hn
++));
895 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
896 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
897 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
898 before_schedchange
, NULL
,
899 &g_array_index(hooks
, LttvTraceHook
, hn
++));
901 g_array_set_size(hooks
, hn
);
903 before_hooks
= hooks
;
905 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
906 g_array_set_size(hooks
, 11);
909 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
910 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
911 LTT_FIELD_SYSCALL_ID
, 0, 0,
912 after_syscall_entry
, NULL
,
913 &g_array_index(hooks
, LttvTraceHook
, hn
++));
916 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
917 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
919 after_syscall_exit
, NULL
,
920 &g_array_index(hooks
, LttvTraceHook
, hn
++));
923 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
924 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
925 LTT_FIELD_TRAP_ID
, 0, 0,
926 after_trap_entry
, NULL
,
927 &g_array_index(hooks
, LttvTraceHook
, hn
++));
930 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
931 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
933 after_trap_exit
, NULL
,
934 &g_array_index(hooks
, LttvTraceHook
, hn
++));
937 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
938 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
939 LTT_FIELD_IRQ_ID
, 0, 0,
940 after_irq_entry
, NULL
,
941 &g_array_index(hooks
, LttvTraceHook
, hn
++));
944 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
945 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
947 after_irq_exit
, NULL
,
948 &g_array_index(hooks
, LttvTraceHook
, hn
++));
951 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
952 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
953 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
954 after_irq_entry
, NULL
,
955 &g_array_index(hooks
, LttvTraceHook
, hn
++));
958 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
959 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
961 after_soft_irq_exit
, NULL
,
962 &g_array_index(hooks
, LttvTraceHook
, hn
++));
965 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
966 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
967 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
969 &g_array_index(hooks
, LttvTraceHook
, hn
++));
972 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
973 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
976 &g_array_index(hooks
, LttvTraceHook
, hn
++));
979 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
980 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
983 &g_array_index(hooks
, LttvTraceHook
, hn
++));
986 g_array_set_size(hooks
, hn
);
990 /* Add these hooks to each event_by_id hooks list */
992 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
994 for(j
= 0 ; j
< nb_tracefile
; j
++) {
995 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
996 LttvTracefileContext
*, j
));
997 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
1000 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1001 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1002 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1003 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1005 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1008 LTTV_PRIO_STATS_BEFORE_STATE
);
1011 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1012 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1013 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1014 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1016 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1019 LTTV_PRIO_STATS_AFTER_STATE
);
1023 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1024 LTTV_POINTER
, &val
);
1025 *(val
.v_pointer
) = before_hooks
;
1026 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1027 LTTV_POINTER
, &val
);
1028 *(val
.v_pointer
) = after_hooks
;
1032 // Hook wrapper. call_data is a traceset context.
1033 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1035 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1037 lttv_stats_remove_event_hooks(tss
);
1042 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1044 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1046 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1050 LttvTracefileStats
*tfs
;
1054 GArray
*before_hooks
, *after_hooks
;
1056 LttvTraceHook
*hook
;
1058 LttvTraceHookByFacility
*thf
;
1060 LttvAttributeValue val
;
1062 nb_trace
= lttv_traceset_number(traceset
);
1063 for(i
= 0 ; i
< nb_trace
; i
++) {
1064 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1065 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1066 LTTV_POINTER
, &val
);
1067 before_hooks
= *(val
.v_pointer
);
1068 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1069 LTTV_POINTER
, &val
);
1070 after_hooks
= *(val
.v_pointer
);
1072 /* Remove these hooks from each event_by_id hooks list */
1074 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1076 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1077 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1078 LttvTracefileContext
*, j
));
1079 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1082 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1083 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1084 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1085 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1086 lttv_hooks_remove_data(
1087 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1092 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1093 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1094 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1095 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1096 lttv_hooks_remove_data(
1097 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1103 g_debug("lttv_stats_remove_event_hooks()");
1104 g_array_free(before_hooks
, TRUE
);
1105 g_array_free(after_hooks
, TRUE
);
1110 static void module_init()
1112 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1113 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1114 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1115 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1116 LTTV_STATS_MODES
= g_quark_from_string("modes");
1117 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1118 LTTV_STATS_SUBMODES
= g_quark_from_string("functions");
1119 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1120 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1121 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
1122 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1123 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1124 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1125 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1126 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1127 LTTV_STATS
= g_quark_from_string("statistics");
1128 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1129 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1132 static void module_destroy()
1137 LTTV_MODULE("stats", "Compute processes statistics", \
1138 "Accumulate statistics for event types, processes and CPUs", \
1139 module_init
, module_destroy
, "state");
1141 /* Change the places where stats are called (create/read/write stats)
1143 Check for options in batchtest.c to reduce writing and see what tests are
1144 best candidates for performance analysis. Once OK, commit, move to main
1145 and run tests. Update the gui for statistics. */