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
, guint 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 guint cpu
= tfcs
->parent
.cpu
;
124 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
127 LTTV_STATE_MODE_UNKNOWN
,
128 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
129 &tfcs
->current_event_types_tree
);
135 static void lttv_stats_fini(LttvTracesetStats
*self
)
137 guint i
, j
, nb_trace
, nb_tracefile
;
141 LttvTraceContext
*tc
;
145 LttvTracefileContext
*tfc
;
147 LttvTracefileStats
*tfcs
;
149 LttTime timestamp
= {0,0};
151 LttvAttributeValue v
;
153 LttvAttribute
*tracefiles_stats
;
155 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
159 if(*(v
.v_uint
) == 0) {
160 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
164 ts
= self
->parent
.parent
.ts
;
165 nb_trace
= lttv_traceset_number(ts
);
167 for(i
= 0 ; i
< nb_trace
; i
++) {
168 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
170 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
174 if(*(v
.v_uint
) == 0) {
175 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
176 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
177 LTTV_STATS_TRACEFILES
);
178 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
179 LTTV_STATS_TRACEFILES
);
183 nb_tracefile
= tc
->tracefiles
->len
;
185 for(j
= 0 ; j
< nb_tracefile
; j
++) {
186 tfc
= g_array_index(tc
->tracefiles
,
187 LttvTracefileContext
*, j
);
188 tfcs
= (LttvTracefileStats
*)tfc
;
190 tfcs
->current_events_tree
= NULL
;
191 tfcs
->current_event_types_tree
= NULL
;
197 void lttv_stats_reset(LttvTracesetStats
*self
)
199 lttv_stats_fini(self
);
200 lttv_stats_init(self
);
206 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
208 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
209 init((LttvTracesetContext
*)self
, ts
);
211 lttv_stats_init(self
);
216 fini(LttvTracesetStats
*self
)
218 lttv_stats_fini(self
);
220 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
221 fini((LttvTracesetContext
*)self
);
225 static LttvTracesetContext
*
226 new_traceset_context(LttvTracesetContext
*self
)
228 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
232 static LttvTraceContext
*
233 new_trace_context(LttvTracesetContext
*self
)
235 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
239 static LttvTracefileContext
*
240 new_tracefile_context(LttvTracesetContext
*self
)
242 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
247 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
253 traceset_stats_finalize (LttvTracesetStats
*self
)
255 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
256 finalize(G_OBJECT(self
));
261 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
263 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
265 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
266 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
267 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
268 klass
->new_traceset_context
= new_traceset_context
;
269 klass
->new_trace_context
= new_trace_context
;
270 klass
->new_tracefile_context
= new_tracefile_context
;
275 lttv_traceset_stats_get_type(void)
277 static GType type
= 0;
279 static const GTypeInfo info
= {
280 sizeof (LttvTracesetStatsClass
),
281 NULL
, /* base_init */
282 NULL
, /* base_finalize */
283 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
284 NULL
, /* class_finalize */
285 NULL
, /* class_data */
286 sizeof (LttvTracesetStats
),
288 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
289 NULL
/* Value handling */
292 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
293 "LttvTracesetStatsType",
301 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
307 trace_stats_finalize (LttvTraceStats
*self
)
309 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
310 finalize(G_OBJECT(self
));
315 trace_stats_class_init (LttvTraceContextClass
*klass
)
317 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
319 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
324 lttv_trace_stats_get_type(void)
326 static GType type
= 0;
328 static const GTypeInfo info
= {
329 sizeof (LttvTraceStatsClass
),
330 NULL
, /* base_init */
331 NULL
, /* base_finalize */
332 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
333 NULL
, /* class_finalize */
334 NULL
, /* class_data */
335 sizeof (LttvTraceStats
),
337 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
338 NULL
/* Value handling */
341 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
342 "LttvTraceStatsType", &info
, 0);
349 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
355 tracefile_stats_finalize (LttvTracefileStats
*self
)
357 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
358 finalize(G_OBJECT(self
));
363 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
365 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
367 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
372 lttv_tracefile_stats_get_type(void)
374 static GType type
= 0;
376 static const GTypeInfo info
= {
377 sizeof (LttvTracefileStatsClass
),
378 NULL
, /* base_init */
379 NULL
, /* base_finalize */
380 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
381 NULL
, /* class_finalize */
382 NULL
, /* class_data */
383 sizeof (LttvTracefileStats
),
385 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
386 NULL
/* Value handling */
389 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
390 "LttvTracefileStatsType", &info
, 0);
397 find_event_tree(LttvTracefileStats
*tfcs
,
403 LttvAttribute
**events_tree
,
404 LttvAttribute
**event_types_tree
)
406 LttvAttribute
*a
, *prev_a
;
407 gchar fstring
[MAX_64_HEX_STRING_LEN
];
409 g_assert(snprintf(fstring
, MAX_64_HEX_STRING_LEN
-1,
410 "0x%llX", function
) > 0);
411 fstring
[MAX_64_HEX_STRING_LEN
-1] = '\0';
413 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
414 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
415 a
= lttv_attribute_find_subdir(a
, pid_time
);
416 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
417 a
= lttv_attribute_find_subdir_unnamed(a
, cpu
);
418 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_FUNCTIONS
);
419 a
= lttv_attribute_find_subdir(a
, g_quark_from_string(fstring
));
420 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
421 a
= lttv_attribute_find_subdir(a
, mode
);
422 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
423 a
= lttv_attribute_find_subdir(a
, sub_mode
);
425 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
426 *event_types_tree
= a
;
430 static void update_event_tree(LttvTracefileStats
*tfcs
)
432 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
433 guint cpu
= tfcs
->parent
.cpu
;
434 LttvProcessState
*process
= ts
->running_process
[cpu
];
435 LttvExecutionState
*es
= process
->state
;
437 find_event_tree(tfcs
, process
->pid_time
,
439 process
->current_function
,
440 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
441 &(tfcs
->current_event_types_tree
));
445 static void mode_change(LttvTracefileStats
*tfcs
)
447 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
448 guint cpu
= tfcs
->parent
.cpu
;
449 LttvProcessState
*process
= ts
->running_process
[cpu
];
450 LttvAttributeValue cpu_time
;
454 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
455 LTTV_TIME
, &cpu_time
);
456 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
457 process
->state
->change
);
458 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
462 static void mode_end(LttvTracefileStats
*tfcs
)
464 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
465 guint cpu
= tfcs
->parent
.cpu
;
466 LttvProcessState
*process
= ts
->running_process
[cpu
];
467 LttvAttributeValue elapsed_time
, cpu_time
;
471 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
472 LTTV_TIME
, &elapsed_time
);
473 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
474 process
->state
->entry
);
475 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
477 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
478 LTTV_TIME
, &cpu_time
);
479 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
480 process
->state
->change
);
481 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
485 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
487 mode_change((LttvTracefileStats
*)call_data
);
492 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
494 update_event_tree((LttvTracefileStats
*)call_data
);
499 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
501 mode_end((LttvTracefileStats
*)call_data
);
506 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
508 update_event_tree((LttvTracefileStats
*)call_data
);
513 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
515 mode_change((LttvTracefileStats
*)call_data
);
520 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
522 update_event_tree((LttvTracefileStats
*)call_data
);
527 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
529 mode_end((LttvTracefileStats
*)call_data
);
534 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
536 update_event_tree((LttvTracefileStats
*)call_data
);
541 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
543 mode_change((LttvTracefileStats
*)call_data
);
547 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
549 update_event_tree((LttvTracefileStats
*)call_data
);
554 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
556 mode_end((LttvTracefileStats
*)call_data
);
561 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
563 update_event_tree((LttvTracefileStats
*)call_data
);
568 gboolean
before_soft_irq_entry(void *hook_data
, void *call_data
)
570 mode_change((LttvTracefileStats
*)call_data
);
574 gboolean
after_soft_irq_entry(void *hook_data
, void *call_data
)
576 update_event_tree((LttvTracefileStats
*)call_data
);
581 gboolean
before_soft_irq_exit(void *hook_data
, void *call_data
)
583 mode_end((LttvTracefileStats
*)call_data
);
588 gboolean
after_soft_irq_exit(void *hook_data
, void *call_data
)
590 update_event_tree((LttvTracefileStats
*)call_data
);
594 gboolean
before_function_entry(void *hook_data
, void *call_data
)
596 mode_end((LttvTracefileStats
*)call_data
);
600 gboolean
after_function_entry(void *hook_data
, void *call_data
)
602 update_event_tree((LttvTracefileStats
*)call_data
);
606 gboolean
before_function_exit(void *hook_data
, void *call_data
)
608 mode_end((LttvTracefileStats
*)call_data
);
612 gboolean
after_function_exit(void *hook_data
, void *call_data
)
614 update_event_tree((LttvTracefileStats
*)call_data
);
619 gboolean
before_schedchange(void *hook_data
, void *call_data
)
621 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
623 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
625 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
627 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
629 guint pid_in
, pid_out
;
633 LttvProcessState
*process
;
635 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
636 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
637 state_out
= ltt_event_get_int(e
, thf
->f3
);
639 /* compute the time for the process to schedule out */
643 /* get the information for the process scheduled in */
645 process
= lttv_state_find_process_or_create(ts
,
646 ANY_CPU
, pid_in
, &tfcs
->parent
.parent
.timestamp
);
648 guint cpu
= tfcs
->parent
.cpu
;
650 find_event_tree(tfcs
, process
->pid_time
,
652 process
->current_function
,
653 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
654 &(tfcs
->current_event_types_tree
));
656 /* compute the time waiting for the process to schedule in */
663 gboolean
process_fork(void *hook_data
, void *call_data
)
665 /* nothing to do for now */
670 gboolean
process_exit(void *hook_data
, void *call_data
)
672 /* We should probably exit all modes here or we could do that at
677 gboolean
process_free(void *hook_data
, void *call_data
)
682 gboolean
every_event(void *hook_data
, void *call_data
)
684 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
686 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
688 LttvAttributeValue v
;
690 /* The current branch corresponds to the tracefile/process/interrupt state.
691 Statistics are added within it, to count the number of events of this
692 type occuring in this context. A quark has been pre-allocated for each
693 event type and is used as name. */
695 lttv_attribute_find(tfcs
->current_event_types_tree
,
696 ltt_eventtype_name(ltt_event_eventtype(e
)),
704 lttv_stats_sum_trace(LttvTraceStats
*self
)
706 LttvAttribute
*sum_container
= self
->stats
;
708 LttvAttributeType type
;
710 LttvAttributeValue value
;
712 LttvAttributeName name
;
718 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
719 nb_event_type
, nf
, nb_functions
;
721 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
722 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
723 *submode_tree
, *event_types_tree
, *mode_events_tree
,
726 *function_mode_types_tree
,
729 main_tree
= sum_container
;
731 lttv_attribute_find(sum_container
,
734 if(*(value
.v_uint
) != 0) return;
737 processes_tree
= lttv_attribute_find_subdir(main_tree
,
738 LTTV_STATS_PROCESSES
);
739 nb_process
= lttv_attribute_get_number(processes_tree
);
741 for(i
= 0 ; i
< nb_process
; i
++) {
742 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
, &is_named
);
743 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
745 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
746 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
748 for(j
= 0 ; j
< nb_cpu
; j
++) {
749 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
, &is_named
);
750 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
752 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
753 trace_cpu_tree
= lttv_attribute_find_subdir_unnamed(trace_cpu_tree
, name
);
754 cpu_functions_tree
= lttv_attribute_find_subdir(cpu_tree
,
755 LTTV_STATS_FUNCTIONS
);
756 nb_functions
= lttv_attribute_get_number(cpu_functions_tree
);
758 for(nf
=0; nf
< nb_functions
; nf
++) {
759 type
= lttv_attribute_get(cpu_functions_tree
, nf
, &name
, &value
,
761 function_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
762 function_mode_types_tree
= lttv_attribute_find_subdir(function_tree
,
763 LTTV_STATS_MODE_TYPES
);
764 nb_mode_type
= lttv_attribute_get_number(function_mode_types_tree
);
765 for(k
= 0 ; k
< nb_mode_type
; k
++) {
766 type
= lttv_attribute_get(function_mode_types_tree
, k
, &name
, &value
,
768 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
770 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
771 LTTV_STATS_SUBMODES
);
772 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
774 mode_types_tree
= lttv_attribute_find_subdir(mode_tree
,
775 LTTV_STATS_MODE_TYPES
);
777 nb_submode
= lttv_attribute_get_number(submodes_tree
);
779 for(l
= 0 ; l
< nb_submode
; l
++) {
780 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
782 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
784 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
785 LTTV_STATS_EVENT_TYPES
);
786 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
789 for(m
= 0 ; m
< nb_event_type
; m
++) {
790 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
,
792 sum
+= *(value
.v_uint
);
794 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
796 *(value
.v_uint
) = sum
;
798 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
800 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
801 lttv_attribute_recursive_add(mode_events_tree
, event_types_tree
);
802 lttv_attribute_recursive_add(mode_types_tree
, submode_tree
);
805 lttv_attribute_recursive_add(main_tree
, mode_types_tree
);
806 lttv_attribute_recursive_add(trace_cpu_tree
, mode_types_tree
);
807 lttv_attribute_recursive_add(process_tree
, mode_types_tree
);
808 lttv_attribute_recursive_add(function_tree
, mode_types_tree
);
810 lttv_attribute_recursive_add(process_tree
, cpu_tree
);
816 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
818 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
823 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
825 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
826 LttvAttribute
*sum_container
= self
->stats
;
832 LttvAttribute
*main_tree
;
834 LttvAttributeValue value
;
836 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
838 if(*(value
.v_uint
) != 0) return;
841 nb_trace
= lttv_traceset_number(traceset
);
843 for(i
= 0 ; i
< nb_trace
; i
++) {
844 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
845 lttv_stats_sum_trace(tcs
);
846 main_tree
= tcs
->stats
;
847 lttv_attribute_recursive_add(sum_container
, main_tree
);
852 // Hook wrapper. call_data is a traceset context.
853 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
855 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
857 lttv_stats_add_event_hooks(tss
);
862 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
864 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
866 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
870 LttvTracefileStats
*tfs
;
872 GArray
*hooks
, *before_hooks
, *after_hooks
;
876 LttvTraceHookByFacility
*thf
;
878 LttvAttributeValue val
;
883 nb_trace
= lttv_traceset_number(traceset
);
884 for(i
= 0 ; i
< nb_trace
; i
++) {
885 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
887 /* Find the eventtype id for the following events and register the
888 associated by id hooks. */
890 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 11);
891 g_array_set_size(hooks
, 11);
894 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
895 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
896 LTT_FIELD_SYSCALL_ID
, 0, 0,
897 before_syscall_entry
, NULL
,
898 &g_array_index(hooks
, LttvTraceHook
, hn
++));
901 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
902 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
904 before_syscall_exit
, NULL
,
905 &g_array_index(hooks
, LttvTraceHook
, hn
++));
908 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
909 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
910 LTT_FIELD_TRAP_ID
, 0, 0,
911 before_trap_entry
, NULL
,
912 &g_array_index(hooks
, LttvTraceHook
, hn
++));
915 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
916 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
918 before_trap_exit
, NULL
,
919 &g_array_index(hooks
, LttvTraceHook
, hn
++));
922 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
923 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
924 LTT_FIELD_IRQ_ID
, 0, 0,
925 before_irq_entry
, NULL
,
926 &g_array_index(hooks
, LttvTraceHook
, hn
++));
929 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
930 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
932 before_irq_exit
, NULL
,
933 &g_array_index(hooks
, LttvTraceHook
, hn
++));
936 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
937 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
938 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
939 before_soft_irq_entry
, NULL
,
940 &g_array_index(hooks
, LttvTraceHook
, hn
++));
943 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
944 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
946 before_soft_irq_exit
, NULL
,
947 &g_array_index(hooks
, LttvTraceHook
, hn
++));
950 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
951 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
952 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
953 before_schedchange
, NULL
,
954 &g_array_index(hooks
, LttvTraceHook
, hn
++));
957 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
958 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
959 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
960 before_function_entry
, NULL
,
961 &g_array_index(hooks
, LttvTraceHook
, hn
++));
964 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
965 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
966 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
967 before_function_exit
, NULL
,
968 &g_array_index(hooks
, LttvTraceHook
, hn
++));
971 g_array_set_size(hooks
, hn
);
973 before_hooks
= hooks
;
975 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 13);
976 g_array_set_size(hooks
, 13);
979 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
980 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
981 LTT_FIELD_SYSCALL_ID
, 0, 0,
982 after_syscall_entry
, NULL
,
983 &g_array_index(hooks
, LttvTraceHook
, hn
++));
986 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
987 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
989 after_syscall_exit
, NULL
,
990 &g_array_index(hooks
, LttvTraceHook
, hn
++));
993 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
994 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
995 LTT_FIELD_TRAP_ID
, 0, 0,
996 after_trap_entry
, NULL
,
997 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1000 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1001 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1003 after_trap_exit
, NULL
,
1004 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1007 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1008 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1009 LTT_FIELD_IRQ_ID
, 0, 0,
1010 after_irq_entry
, NULL
,
1011 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1014 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1015 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1017 after_irq_exit
, NULL
,
1018 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1021 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1022 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
1023 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
1024 after_irq_entry
, NULL
,
1025 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1028 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1029 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
1031 after_soft_irq_exit
, NULL
,
1032 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1035 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1036 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
1037 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1039 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1042 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1043 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
1044 LTT_FIELD_PID
, 0, 0,
1046 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1049 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1050 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
1051 LTT_FIELD_PID
, 0, 0,
1053 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1056 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1057 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
1058 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1059 after_function_entry
, NULL
,
1060 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1063 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1064 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
1065 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1066 after_function_exit
, NULL
,
1067 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1070 g_array_set_size(hooks
, hn
);
1072 after_hooks
= hooks
;
1074 /* Add these hooks to each event_by_id hooks list */
1076 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1078 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1079 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1080 LttvTracefileContext
*, j
));
1081 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
1084 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1085 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1086 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1087 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1089 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1092 LTTV_PRIO_STATS_BEFORE_STATE
);
1095 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1096 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1097 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1098 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1100 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1103 LTTV_PRIO_STATS_AFTER_STATE
);
1107 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1108 LTTV_POINTER
, &val
);
1109 *(val
.v_pointer
) = before_hooks
;
1110 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1111 LTTV_POINTER
, &val
);
1112 *(val
.v_pointer
) = after_hooks
;
1116 // Hook wrapper. call_data is a traceset context.
1117 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1119 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1121 lttv_stats_remove_event_hooks(tss
);
1126 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1128 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1130 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1134 LttvTracefileStats
*tfs
;
1138 GArray
*before_hooks
, *after_hooks
;
1140 LttvTraceHook
*hook
;
1142 LttvTraceHookByFacility
*thf
;
1144 LttvAttributeValue val
;
1146 nb_trace
= lttv_traceset_number(traceset
);
1147 for(i
= 0 ; i
< nb_trace
; i
++) {
1148 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1149 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1150 LTTV_POINTER
, &val
);
1151 before_hooks
= *(val
.v_pointer
);
1152 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1153 LTTV_POINTER
, &val
);
1154 after_hooks
= *(val
.v_pointer
);
1156 /* Remove these hooks from each event_by_id hooks list */
1158 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1160 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1161 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1162 LttvTracefileContext
*, j
));
1163 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1166 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1167 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1168 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1169 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1170 lttv_hooks_remove_data(
1171 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1176 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1177 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1178 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1179 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1180 lttv_hooks_remove_data(
1181 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1187 g_debug("lttv_stats_remove_event_hooks()");
1188 g_array_free(before_hooks
, TRUE
);
1189 g_array_free(after_hooks
, TRUE
);
1194 static void module_init()
1196 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1197 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1198 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1199 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1200 LTTV_STATS_MODES
= g_quark_from_string("modes");
1201 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1202 LTTV_STATS_FUNCTIONS
= g_quark_from_string("functions");
1203 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1204 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1205 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
1206 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1207 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1208 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1209 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1210 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1211 LTTV_STATS
= g_quark_from_string("statistics");
1212 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1213 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1216 static void module_destroy()
1221 LTTV_MODULE("stats", "Compute processes statistics", \
1222 "Accumulate statistics for event types, processes and CPUs", \
1223 module_init
, module_destroy
, "state");
1225 /* Change the places where stats are called (create/read/write stats)
1227 Check for options in batchtest.c to reduce writing and see what tests are
1228 best candidates for performance analysis. Once OK, commit, move to main
1229 and run tests. Update the gui for statistics. */