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>
34 #define MAX_64_HEX_STRING_LEN 19
37 LTTV_STATS_PROCESS_UNKNOWN
,
40 LTTV_STATS_MODE_TYPES
,
44 LTTV_STATS_EVENT_TYPES
,
46 LTTV_STATS_ELAPSED_TIME
,
48 LTTV_STATS_EVENTS_COUNT
,
51 LTTV_STATS_TRACEFILES
,
53 LTTV_STATS_BEFORE_HOOKS
,
54 LTTV_STATS_AFTER_HOOKS
;
57 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, GQuark cpu
,
59 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
60 LttvAttribute
**event_types_tree
);
63 static void lttv_stats_init(LttvTracesetStats
*self
)
65 guint i
, j
, nb_trace
, nb_tracefile
;
71 LttvTracefileContext
*tfc
;
73 LttvTracefileContext
**tfs
;
74 LttvTracefileStats
*tfcs
;
76 LttTime timestamp
= {0,0};
84 LttvTraceset
*ts
= self
->parent
.parent
.ts
;
86 self
->stats
= lttv_attribute_find_subdir(
87 lttv_traceset_attribute(self
->parent
.parent
.ts
),
89 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
94 if(*(v
.v_uint
) == 1) {
95 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
98 nb_trace
= lttv_traceset_number(ts
);
100 for(i
= 0 ; i
< nb_trace
; i
++) {
101 tc
= self
->parent
.parent
.traces
[i
];
102 tcs
= LTTV_TRACE_STATS(tc
);
104 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
105 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
106 LTTV_STATS_TRACEFILES
);
107 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
111 if(*(v
.v_uint
) == 1) {
112 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
115 nb_tracefile
= tc
->tracefiles
->len
;
117 for(j
= 0 ; j
< nb_tracefile
; j
++) {
118 tfs
= &g_array_index(tc
->tracefiles
,
119 LttvTracefileContext
*, j
);
120 tfcs
= LTTV_TRACEFILE_STATS(*tfs
);
121 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
122 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
));
123 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
124 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
126 LTTV_STATE_MODE_UNKNOWN
,
127 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
128 &tfcs
->current_event_types_tree
);
134 static void lttv_stats_fini(LttvTracesetStats
*self
)
136 guint i
, j
, nb_trace
, nb_tracefile
;
140 LttvTraceContext
*tc
;
144 LttvTracefileContext
*tfc
;
146 LttvTracefileStats
*tfcs
;
148 LttTime timestamp
= {0,0};
150 LttvAttributeValue v
;
152 LttvAttribute
*tracefiles_stats
;
154 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
158 if(*(v
.v_uint
) == 0) {
159 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
163 ts
= self
->parent
.parent
.ts
;
164 nb_trace
= lttv_traceset_number(ts
);
166 for(i
= 0 ; i
< nb_trace
; i
++) {
167 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
169 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
173 if(*(v
.v_uint
) == 0) {
174 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
175 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
176 LTTV_STATS_TRACEFILES
);
177 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
178 LTTV_STATS_TRACEFILES
);
182 nb_tracefile
= tc
->tracefiles
->len
;
184 for(j
= 0 ; j
< nb_tracefile
; j
++) {
185 tfc
= g_array_index(tc
->tracefiles
,
186 LttvTracefileContext
*, j
);
187 tfcs
= (LttvTracefileStats
*)tfc
;
189 tfcs
->current_events_tree
= NULL
;
190 tfcs
->current_event_types_tree
= NULL
;
196 void lttv_stats_reset(LttvTracesetStats
*self
)
198 lttv_stats_fini(self
);
199 lttv_stats_init(self
);
205 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
207 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
208 init((LttvTracesetContext
*)self
, ts
);
210 lttv_stats_init(self
);
215 fini(LttvTracesetStats
*self
)
217 lttv_stats_fini(self
);
219 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
220 fini((LttvTracesetContext
*)self
);
224 static LttvTracesetContext
*
225 new_traceset_context(LttvTracesetContext
*self
)
227 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
231 static LttvTraceContext
*
232 new_trace_context(LttvTracesetContext
*self
)
234 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
238 static LttvTracefileContext
*
239 new_tracefile_context(LttvTracesetContext
*self
)
241 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
246 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
252 traceset_stats_finalize (LttvTracesetStats
*self
)
254 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
255 finalize(G_OBJECT(self
));
260 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
262 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
264 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
265 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
266 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
267 klass
->new_traceset_context
= new_traceset_context
;
268 klass
->new_trace_context
= new_trace_context
;
269 klass
->new_tracefile_context
= new_tracefile_context
;
274 lttv_traceset_stats_get_type(void)
276 static GType type
= 0;
278 static const GTypeInfo info
= {
279 sizeof (LttvTracesetStatsClass
),
280 NULL
, /* base_init */
281 NULL
, /* base_finalize */
282 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
283 NULL
, /* class_finalize */
284 NULL
, /* class_data */
285 sizeof (LttvTracesetStats
),
287 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
288 NULL
/* Value handling */
291 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
292 "LttvTracesetStatsType",
300 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
306 trace_stats_finalize (LttvTraceStats
*self
)
308 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
309 finalize(G_OBJECT(self
));
314 trace_stats_class_init (LttvTraceContextClass
*klass
)
316 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
318 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
323 lttv_trace_stats_get_type(void)
325 static GType type
= 0;
327 static const GTypeInfo info
= {
328 sizeof (LttvTraceStatsClass
),
329 NULL
, /* base_init */
330 NULL
, /* base_finalize */
331 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
332 NULL
, /* class_finalize */
333 NULL
, /* class_data */
334 sizeof (LttvTraceStats
),
336 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
337 NULL
/* Value handling */
340 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
341 "LttvTraceStatsType", &info
, 0);
348 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
354 tracefile_stats_finalize (LttvTracefileStats
*self
)
356 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
357 finalize(G_OBJECT(self
));
362 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
364 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
366 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
371 lttv_tracefile_stats_get_type(void)
373 static GType type
= 0;
375 static const GTypeInfo info
= {
376 sizeof (LttvTracefileStatsClass
),
377 NULL
, /* base_init */
378 NULL
, /* base_finalize */
379 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
380 NULL
, /* class_finalize */
381 NULL
, /* class_data */
382 sizeof (LttvTracefileStats
),
384 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
385 NULL
/* Value handling */
388 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
389 "LttvTracefileStatsType", &info
, 0);
396 find_event_tree(LttvTracefileStats
*tfcs
,
402 LttvAttribute
**events_tree
,
403 LttvAttribute
**event_types_tree
)
406 gchar fstring
[MAX_64_HEX_STRING_LEN
];
408 g_assert(snprintf(fstring
, MAX_64_HEX_STRING_LEN
-1,
409 "0x%llX", function
) > 0);
410 fstring
[MAX_64_HEX_STRING_LEN
-1] = '\0';
412 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
413 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
414 a
= lttv_attribute_find_subdir(a
, pid_time
);
415 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
416 a
= lttv_attribute_find_subdir(a
, cpu
);
417 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_FUNCTIONS
);
418 a
= lttv_attribute_find_subdir(a
, g_quark_from_string(fstring
));
419 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
420 a
= lttv_attribute_find_subdir(a
, mode
);
421 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
422 a
= lttv_attribute_find_subdir(a
, sub_mode
);
424 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
425 *event_types_tree
= a
;
429 static void update_event_tree(LttvTracefileStats
*tfcs
)
431 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
432 guint cpu
= tfcs
->parent
.cpu
;
433 LttvProcessState
*process
= ts
->running_process
[cpu
];
434 LttvExecutionState
*es
= process
->state
;
436 find_event_tree(tfcs
, process
->pid_time
,
437 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
438 process
->current_function
,
439 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
440 &(tfcs
->current_event_types_tree
));
444 static void mode_change(LttvTracefileStats
*tfcs
)
446 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
447 guint cpu
= tfcs
->parent
.cpu
;
448 LttvProcessState
*process
= ts
->running_process
[cpu
];
449 LttvAttributeValue cpu_time
;
453 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
454 LTTV_TIME
, &cpu_time
);
455 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
456 process
->state
->change
);
457 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
461 static void mode_end(LttvTracefileStats
*tfcs
)
463 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
464 guint cpu
= tfcs
->parent
.cpu
;
465 LttvProcessState
*process
= ts
->running_process
[cpu
];
466 LttvAttributeValue elapsed_time
, cpu_time
;
470 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
471 LTTV_TIME
, &elapsed_time
);
472 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
473 process
->state
->entry
);
474 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
476 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
477 LTTV_TIME
, &cpu_time
);
478 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
479 process
->state
->change
);
480 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
484 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
486 mode_change((LttvTracefileStats
*)call_data
);
491 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
493 update_event_tree((LttvTracefileStats
*)call_data
);
498 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
500 mode_end((LttvTracefileStats
*)call_data
);
505 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
507 update_event_tree((LttvTracefileStats
*)call_data
);
512 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
514 mode_change((LttvTracefileStats
*)call_data
);
519 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
521 update_event_tree((LttvTracefileStats
*)call_data
);
526 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
528 mode_end((LttvTracefileStats
*)call_data
);
533 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
535 update_event_tree((LttvTracefileStats
*)call_data
);
540 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
542 mode_change((LttvTracefileStats
*)call_data
);
546 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
548 update_event_tree((LttvTracefileStats
*)call_data
);
553 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
555 mode_end((LttvTracefileStats
*)call_data
);
560 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
562 update_event_tree((LttvTracefileStats
*)call_data
);
567 gboolean
before_soft_irq_entry(void *hook_data
, void *call_data
)
569 mode_change((LttvTracefileStats
*)call_data
);
573 gboolean
after_soft_irq_entry(void *hook_data
, void *call_data
)
575 update_event_tree((LttvTracefileStats
*)call_data
);
580 gboolean
before_soft_irq_exit(void *hook_data
, void *call_data
)
582 mode_end((LttvTracefileStats
*)call_data
);
587 gboolean
after_soft_irq_exit(void *hook_data
, void *call_data
)
589 update_event_tree((LttvTracefileStats
*)call_data
);
593 gboolean
before_function_entry(void *hook_data
, void *call_data
)
595 mode_end((LttvTracefileStats
*)call_data
);
599 gboolean
after_function_entry(void *hook_data
, void *call_data
)
601 update_event_tree((LttvTracefileStats
*)call_data
);
605 gboolean
before_function_exit(void *hook_data
, void *call_data
)
607 mode_end((LttvTracefileStats
*)call_data
);
611 gboolean
after_function_exit(void *hook_data
, void *call_data
)
613 update_event_tree((LttvTracefileStats
*)call_data
);
618 gboolean
before_schedchange(void *hook_data
, void *call_data
)
620 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
622 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
624 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
626 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
628 guint pid_in
, pid_out
;
632 LttvProcessState
*process
;
634 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
635 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
636 state_out
= ltt_event_get_int(e
, thf
->f3
);
638 /* compute the time for the process to schedule out */
642 /* get the information for the process scheduled in */
644 process
= lttv_state_find_process_or_create(ts
,
645 ANY_CPU
, pid_in
, &tfcs
->parent
.parent
.timestamp
);
647 find_event_tree(tfcs
, process
->pid_time
,
648 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
649 process
->current_function
,
650 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
651 &(tfcs
->current_event_types_tree
));
653 /* compute the time waiting for the process to schedule in */
660 gboolean
process_fork(void *hook_data
, void *call_data
)
662 /* nothing to do for now */
667 gboolean
process_exit(void *hook_data
, void *call_data
)
669 /* We should probably exit all modes here or we could do that at
674 gboolean
process_free(void *hook_data
, void *call_data
)
679 gboolean
every_event(void *hook_data
, void *call_data
)
681 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
683 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
685 LttvAttributeValue v
;
687 /* The current branch corresponds to the tracefile/process/interrupt state.
688 Statistics are added within it, to count the number of events of this
689 type occuring in this context. A quark has been pre-allocated for each
690 event type and is used as name. */
692 lttv_attribute_find(tfcs
->current_event_types_tree
,
693 ltt_eventtype_name(ltt_event_eventtype(e
)),
701 lttv_stats_sum_trace(LttvTraceStats
*self
)
703 LttvAttribute
*sum_container
= self
->stats
;
705 LttvAttributeType type
;
707 LttvAttributeValue value
;
709 LttvAttributeName name
;
713 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
716 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
717 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
718 *submode_tree
, *event_types_tree
, *mode_events_tree
,
719 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
722 main_tree
= sum_container
;
724 lttv_attribute_find(sum_container
,
727 if(*(value
.v_uint
) != 0) return;
730 processes_tree
= lttv_attribute_find_subdir(main_tree
,
731 LTTV_STATS_PROCESSES
);
732 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
,
734 nb_process
= lttv_attribute_get_number(processes_tree
);
736 for(i
= 0 ; i
< nb_process
; i
++) {
737 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
738 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
740 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
741 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
743 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
745 for(j
= 0 ; j
< nb_cpu
; j
++) {
746 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
747 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
749 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
750 LTTV_STATS_MODE_TYPES
);
751 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
753 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
754 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
755 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
757 for(k
= 0 ; k
< nb_mode_type
; k
++) {
758 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
759 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
761 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
762 LTTV_STATS_SUBMODES
);
763 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
765 nb_submode
= lttv_attribute_get_number(submodes_tree
);
767 for(l
= 0 ; l
< nb_submode
; l
++) {
768 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
769 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
771 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
772 LTTV_STATS_EVENT_TYPES
);
773 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
776 for(m
= 0 ; m
< nb_event_type
; m
++) {
777 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
778 sum
+= *(value
.v_uint
);
780 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
782 *(value
.v_uint
) = sum
;
783 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
785 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
787 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
788 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
790 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
795 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
797 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
802 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
804 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
805 LttvAttribute
*sum_container
= self
->stats
;
811 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
813 LttvAttributeValue value
;
815 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
817 if(*(value
.v_uint
) != 0) return;
820 traceset_modes_tree
= lttv_attribute_find_subdir(sum_container
,
822 nb_trace
= lttv_traceset_number(traceset
);
824 for(i
= 0 ; i
< nb_trace
; i
++) {
825 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
826 lttv_stats_sum_trace(tcs
);
827 main_tree
= tcs
->stats
;
828 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
829 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
834 // Hook wrapper. call_data is a traceset context.
835 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
837 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
839 lttv_stats_add_event_hooks(tss
);
844 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
846 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
848 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
852 LttvTracefileStats
*tfs
;
854 GArray
*hooks
, *before_hooks
, *after_hooks
;
858 LttvTraceHookByFacility
*thf
;
860 LttvAttributeValue val
;
865 nb_trace
= lttv_traceset_number(traceset
);
866 for(i
= 0 ; i
< nb_trace
; i
++) {
867 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
869 /* Find the eventtype id for the following events and register the
870 associated by id hooks. */
872 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
873 g_array_set_size(hooks
, 11);
876 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
877 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
878 LTT_FIELD_SYSCALL_ID
, 0, 0,
879 before_syscall_entry
, NULL
,
880 &g_array_index(hooks
, LttvTraceHook
, hn
++));
883 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
884 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
886 before_syscall_exit
, NULL
,
887 &g_array_index(hooks
, LttvTraceHook
, hn
++));
890 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
891 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
892 LTT_FIELD_TRAP_ID
, 0, 0,
893 before_trap_entry
, NULL
,
894 &g_array_index(hooks
, LttvTraceHook
, hn
++));
897 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
898 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
900 before_trap_exit
, NULL
,
901 &g_array_index(hooks
, LttvTraceHook
, hn
++));
904 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
905 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
906 LTT_FIELD_IRQ_ID
, 0, 0,
907 before_irq_entry
, NULL
,
908 &g_array_index(hooks
, LttvTraceHook
, hn
++));
911 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
912 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
914 before_irq_exit
, NULL
,
915 &g_array_index(hooks
, LttvTraceHook
, hn
++));
918 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
919 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
920 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
921 before_soft_irq_entry
, NULL
,
922 &g_array_index(hooks
, LttvTraceHook
, hn
++));
925 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
926 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
928 before_soft_irq_exit
, NULL
,
929 &g_array_index(hooks
, LttvTraceHook
, hn
++));
932 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
933 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
934 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
935 before_schedchange
, NULL
,
936 &g_array_index(hooks
, LttvTraceHook
, hn
++));
939 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
940 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
941 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
942 before_function_entry
, NULL
,
943 &g_array_index(hooks
, LttvTraceHook
, hn
++));
946 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
947 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
948 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
949 before_function_exit
, NULL
,
950 &g_array_index(hooks
, LttvTraceHook
, hn
++));
953 g_array_set_size(hooks
, hn
);
955 before_hooks
= hooks
;
957 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 13);
958 g_array_set_size(hooks
, 13);
961 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
962 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
963 LTT_FIELD_SYSCALL_ID
, 0, 0,
964 after_syscall_entry
, NULL
,
965 &g_array_index(hooks
, LttvTraceHook
, hn
++));
968 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
969 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
971 after_syscall_exit
, NULL
,
972 &g_array_index(hooks
, LttvTraceHook
, hn
++));
975 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
976 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
977 LTT_FIELD_TRAP_ID
, 0, 0,
978 after_trap_entry
, NULL
,
979 &g_array_index(hooks
, LttvTraceHook
, hn
++));
982 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
983 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
985 after_trap_exit
, NULL
,
986 &g_array_index(hooks
, LttvTraceHook
, hn
++));
989 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
990 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
991 LTT_FIELD_IRQ_ID
, 0, 0,
992 after_irq_entry
, NULL
,
993 &g_array_index(hooks
, LttvTraceHook
, hn
++));
996 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
997 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
999 after_irq_exit
, NULL
,
1000 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1003 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1004 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
1005 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
1006 after_irq_entry
, NULL
,
1007 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1010 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1011 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
1013 after_soft_irq_exit
, NULL
,
1014 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1017 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1018 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
1019 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1021 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1024 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1025 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
1026 LTT_FIELD_PID
, 0, 0,
1028 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1031 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1032 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
1033 LTT_FIELD_PID
, 0, 0,
1035 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1038 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1039 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
1040 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1041 after_function_entry
, NULL
,
1042 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1045 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1046 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
1047 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1048 after_function_exit
, NULL
,
1049 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1052 g_array_set_size(hooks
, hn
);
1054 after_hooks
= hooks
;
1056 /* Add these hooks to each event_by_id hooks list */
1058 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1060 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1061 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1062 LttvTracefileContext
*, j
));
1063 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
1066 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1067 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1068 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1069 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1071 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1074 LTTV_PRIO_STATS_BEFORE_STATE
);
1077 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1078 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1079 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1080 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1082 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1085 LTTV_PRIO_STATS_AFTER_STATE
);
1089 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1090 LTTV_POINTER
, &val
);
1091 *(val
.v_pointer
) = before_hooks
;
1092 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1093 LTTV_POINTER
, &val
);
1094 *(val
.v_pointer
) = after_hooks
;
1098 // Hook wrapper. call_data is a traceset context.
1099 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1101 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1103 lttv_stats_remove_event_hooks(tss
);
1108 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1110 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1112 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1116 LttvTracefileStats
*tfs
;
1120 GArray
*before_hooks
, *after_hooks
;
1122 LttvTraceHook
*hook
;
1124 LttvTraceHookByFacility
*thf
;
1126 LttvAttributeValue val
;
1128 nb_trace
= lttv_traceset_number(traceset
);
1129 for(i
= 0 ; i
< nb_trace
; i
++) {
1130 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1131 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1132 LTTV_POINTER
, &val
);
1133 before_hooks
= *(val
.v_pointer
);
1134 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1135 LTTV_POINTER
, &val
);
1136 after_hooks
= *(val
.v_pointer
);
1138 /* Remove these hooks from each event_by_id hooks list */
1140 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1142 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1143 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1144 LttvTracefileContext
*, j
));
1145 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1148 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1149 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1150 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1151 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1152 lttv_hooks_remove_data(
1153 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1158 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1159 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1160 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1161 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1162 lttv_hooks_remove_data(
1163 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1169 g_debug("lttv_stats_remove_event_hooks()");
1170 g_array_free(before_hooks
, TRUE
);
1171 g_array_free(after_hooks
, TRUE
);
1176 static void module_init()
1178 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1179 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1180 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1181 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1182 LTTV_STATS_MODES
= g_quark_from_string("modes");
1183 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1184 LTTV_STATS_FUNCTIONS
= g_quark_from_string("functions");
1185 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1186 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1187 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
1188 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1189 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1190 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1191 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1192 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1193 LTTV_STATS
= g_quark_from_string("statistics");
1194 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1195 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1198 static void module_destroy()
1203 LTTV_MODULE("stats", "Compute processes statistics", \
1204 "Accumulate statistics for event types, processes and CPUs", \
1205 module_init
, module_destroy
, "state");
1207 /* Change the places where stats are called (create/read/write stats)
1209 Check for options in batchtest.c to reduce writing and see what tests are
1210 best candidates for performance analysis. Once OK, commit, move to main
1211 and run tests. Update the gui for statistics. */