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>
35 LTTV_STATS_PROCESS_UNKNOWN
,
38 LTTV_STATS_MODE_TYPES
,
41 LTTV_STATS_EVENT_TYPES
,
43 LTTV_STATS_ELAPSED_TIME
,
45 LTTV_STATS_EVENTS_COUNT
,
48 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 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
63 guint i
, j
, nb_trace
, nb_tracefile
;
69 LttvTracefileContext
*tfc
;
71 LttvTracefileStats
*tfcs
;
73 LttTime timestamp
= {0,0};
81 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
82 init((LttvTracesetContext
*)self
, 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
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
100 tcs
= (LttvTraceStats
*)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 tfcs
= LTTV_TRACEFILE_STATS(g_array_index(tc
->tracefiles
,
117 LttvTracefileContext
*, j
));
118 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
119 tfcs
->parent
.cpu_name
);
120 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
121 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
122 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
123 &tfcs
->current_event_types_tree
);
129 fini(LttvTracesetStats
*self
)
131 guint i
, j
, nb_trace
, nb_tracefile
;
135 LttvTraceContext
*tc
;
139 LttvTracefileContext
*tfc
;
141 LttvTracefileStats
*tfcs
;
143 LttTime timestamp
= {0,0};
145 LttvAttributeValue v
;
147 LttvAttribute
*tracefiles_stats
;
149 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
153 if(*(v
.v_uint
) == 0) {
154 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
158 ts
= self
->parent
.parent
.ts
;
159 nb_trace
= lttv_traceset_number(ts
);
161 for(i
= 0 ; i
< nb_trace
; i
++) {
162 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
164 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
168 if(*(v
.v_uint
) == 0) {
169 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
170 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
171 LTTV_STATS_TRACEFILES
);
172 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
173 LTTV_STATS_TRACEFILES
);
177 nb_tracefile
= tc
->tracefiles
->len
;
179 for(j
= 0 ; j
< nb_tracefile
; j
++) {
180 tfc
= g_array_index(tc
->tracefiles
,
181 LttvTracefileContext
*, j
);
182 tfcs
= (LttvTracefileStats
*)tfc
;
184 tfcs
->current_events_tree
= NULL
;
185 tfcs
->current_event_types_tree
= NULL
;
188 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
189 fini((LttvTracesetContext
*)self
);
193 static LttvTracesetContext
*
194 new_traceset_context(LttvTracesetContext
*self
)
196 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
200 static LttvTraceContext
*
201 new_trace_context(LttvTracesetContext
*self
)
203 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
207 static LttvTracefileContext
*
208 new_tracefile_context(LttvTracesetContext
*self
)
210 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
215 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
221 traceset_stats_finalize (LttvTracesetStats
*self
)
223 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
224 finalize(G_OBJECT(self
));
229 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
231 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
233 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
234 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
235 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
236 klass
->new_traceset_context
= new_traceset_context
;
237 klass
->new_trace_context
= new_trace_context
;
238 klass
->new_tracefile_context
= new_tracefile_context
;
243 lttv_traceset_stats_get_type(void)
245 static GType type
= 0;
247 static const GTypeInfo info
= {
248 sizeof (LttvTracesetStatsClass
),
249 NULL
, /* base_init */
250 NULL
, /* base_finalize */
251 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
252 NULL
, /* class_finalize */
253 NULL
, /* class_data */
254 sizeof (LttvTracesetStats
),
256 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
257 NULL
/* Value handling */
260 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
261 "LttvTracesetStatsType",
269 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
275 trace_stats_finalize (LttvTraceStats
*self
)
277 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
278 finalize(G_OBJECT(self
));
283 trace_stats_class_init (LttvTraceContextClass
*klass
)
285 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
287 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
292 lttv_trace_stats_get_type(void)
294 static GType type
= 0;
296 static const GTypeInfo info
= {
297 sizeof (LttvTraceStatsClass
),
298 NULL
, /* base_init */
299 NULL
, /* base_finalize */
300 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
301 NULL
, /* class_finalize */
302 NULL
, /* class_data */
303 sizeof (LttvTraceStats
),
305 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
306 NULL
/* Value handling */
309 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
310 "LttvTraceStatsType", &info
, 0);
317 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
323 tracefile_stats_finalize (LttvTracefileStats
*self
)
325 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
326 finalize(G_OBJECT(self
));
331 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
333 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
335 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
340 lttv_tracefile_stats_get_type(void)
342 static GType type
= 0;
344 static const GTypeInfo info
= {
345 sizeof (LttvTracefileStatsClass
),
346 NULL
, /* base_init */
347 NULL
, /* base_finalize */
348 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
349 NULL
, /* class_finalize */
350 NULL
, /* class_data */
351 sizeof (LttvTracefileStats
),
353 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
354 NULL
/* Value handling */
357 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
358 "LttvTracefileStatsType", &info
, 0);
365 find_event_tree(LttvTracefileStats
*tfcs
,
370 LttvAttribute
**events_tree
,
371 LttvAttribute
**event_types_tree
)
375 LttvTraceStats
*tcs
= LTTV_TRACE_STATS(tfcs
->parent
.parent
.t_context
);
376 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
377 a
= lttv_attribute_find_subdir(a
, pid_time
);
378 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
379 a
= lttv_attribute_find_subdir(a
, cpu
);
380 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
381 a
= lttv_attribute_find_subdir(a
, mode
);
382 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
383 a
= lttv_attribute_find_subdir(a
, sub_mode
);
385 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
386 *event_types_tree
= a
;
390 static void update_event_tree(LttvTracefileStats
*tfcs
)
392 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
394 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
,
395 tfcs
->parent
.cpu_name
,
396 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
397 &(tfcs
->current_event_types_tree
));
401 static void mode_change(LttvTracefileStats
*tfcs
)
403 LttvAttributeValue cpu_time
;
407 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
408 LTTV_TIME
, &cpu_time
);
409 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
410 tfcs
->parent
.process
->state
->change
);
411 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
415 static void mode_end(LttvTracefileStats
*tfcs
)
417 LttvAttributeValue elapsed_time
, cpu_time
;
421 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
422 LTTV_TIME
, &elapsed_time
);
423 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
424 tfcs
->parent
.process
->state
->entry
);
425 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
427 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
428 LTTV_TIME
, &cpu_time
);
429 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
430 tfcs
->parent
.process
->state
->change
);
431 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
435 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
437 mode_change((LttvTracefileStats
*)call_data
);
442 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
444 update_event_tree((LttvTracefileStats
*)call_data
);
449 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
451 mode_end((LttvTracefileStats
*)call_data
);
456 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
458 update_event_tree((LttvTracefileStats
*)call_data
);
463 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
465 mode_change((LttvTracefileStats
*)call_data
);
470 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
472 update_event_tree((LttvTracefileStats
*)call_data
);
477 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
479 mode_end((LttvTracefileStats
*)call_data
);
484 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
486 update_event_tree((LttvTracefileStats
*)call_data
);
491 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
493 mode_change((LttvTracefileStats
*)call_data
);
498 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
500 update_event_tree((LttvTracefileStats
*)call_data
);
505 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
507 mode_end((LttvTracefileStats
*)call_data
);
512 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
514 update_event_tree((LttvTracefileStats
*)call_data
);
519 gboolean
before_schedchange(void *hook_data
, void *call_data
)
521 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
523 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
525 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
527 guint pid_in
, pid_out
;
531 LttvProcessState
*process
;
533 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
534 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
535 state_out
= ltt_event_get_int(e
, thf
->f3
);
537 /* compute the time for the process to schedule out */
541 /* get the information for the process scheduled in */
543 process
= lttv_state_find_process_or_create(&(tfcs
->parent
), pid_in
);
545 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
546 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
547 &(tfcs
->current_event_types_tree
));
549 /* compute the time waiting for the process to schedule in */
556 gboolean
process_fork(void *hook_data
, void *call_data
)
558 /* nothing to do for now */
563 gboolean
process_exit(void *hook_data
, void *call_data
)
565 /* We should probably exit all modes here or we could do that at
570 gboolean
process_free(void *hook_data
, void *call_data
)
575 gboolean
every_event(void *hook_data
, void *call_data
)
577 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
579 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
581 LttvAttributeValue v
;
583 /* The current branch corresponds to the tracefile/process/interrupt state.
584 Statistics are added within it, to count the number of events of this
585 type occuring in this context. A quark has been pre-allocated for each
586 event type and is used as name. */
588 lttv_attribute_find(tfcs
->current_event_types_tree
,
589 ltt_eventtype_name(ltt_event_eventtype(e
)),
597 lttv_stats_sum_trace(LttvTraceStats
*self
)
599 LttvAttribute
*sum_container
= self
->stats
;
601 LttvAttributeType type
;
603 LttvAttributeValue value
;
605 LttvAttributeName name
;
609 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
612 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
613 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
614 *submode_tree
, *event_types_tree
, *mode_events_tree
,
615 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
618 main_tree
= sum_container
;
620 lttv_attribute_find(sum_container
,
623 if(*(value
.v_uint
) != 0) return;
626 processes_tree
= lttv_attribute_find_subdir(main_tree
,
627 LTTV_STATS_PROCESSES
);
628 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
,
630 nb_process
= lttv_attribute_get_number(processes_tree
);
632 for(i
= 0 ; i
< nb_process
; i
++) {
633 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
634 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
636 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
637 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
639 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
641 for(j
= 0 ; j
< nb_cpu
; j
++) {
642 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
643 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
645 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
646 LTTV_STATS_MODE_TYPES
);
647 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
649 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
650 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
651 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
653 for(k
= 0 ; k
< nb_mode_type
; k
++) {
654 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
655 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
657 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
658 LTTV_STATS_SUBMODES
);
659 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
661 nb_submode
= lttv_attribute_get_number(submodes_tree
);
663 for(l
= 0 ; l
< nb_submode
; l
++) {
664 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
665 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
667 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
668 LTTV_STATS_EVENT_TYPES
);
669 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
672 for(m
= 0 ; m
< nb_event_type
; m
++) {
673 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
674 sum
+= *(value
.v_uint
);
676 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
678 *(value
.v_uint
) = sum
;
679 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
681 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
683 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
684 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
686 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
691 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
693 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
698 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
700 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
701 LttvAttribute
*sum_container
= self
->stats
;
707 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
709 LttvAttributeValue value
;
711 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
713 if(*(value
.v_uint
) != 0) return;
716 traceset_modes_tree
= lttv_attribute_find_subdir(sum_container
,
718 nb_trace
= lttv_traceset_number(traceset
);
720 for(i
= 0 ; i
< nb_trace
; i
++) {
721 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
722 lttv_stats_sum_trace(tcs
);
723 main_tree
= tcs
->stats
;
724 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
725 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
730 // Hook wrapper. call_data is a traceset context.
731 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
733 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
735 lttv_stats_add_event_hooks(tss
);
740 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
742 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
744 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
752 LttvTracefileStats
*tfs
;
756 GArray
*hooks
, *before_hooks
, *after_hooks
;
760 LttvTraceHookByFacility
*thf
;
762 LttvAttributeValue val
;
766 nb_trace
= lttv_traceset_number(traceset
);
767 for(i
= 0 ; i
< nb_trace
; i
++) {
768 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
770 /* Find the eventtype id for the following events and register the
771 associated by id hooks. */
773 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 7);
774 g_array_set_size(hooks
, 7);
776 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
777 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
778 LTT_FIELD_SYSCALL_ID
, 0, 0,
779 before_syscall_entry
,
780 &g_array_index(hooks
, LttvTraceHook
, 0));
783 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
784 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
787 &g_array_index(hooks
, LttvTraceHook
, 1));
790 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
791 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
792 LTT_FIELD_TRAP_ID
, 0, 0,
794 &g_array_index(hooks
, LttvTraceHook
, 2));
797 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
798 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
800 before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
803 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
804 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
805 LTT_FIELD_IRQ_ID
, 0, 0,
806 before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
809 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
810 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
812 before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
815 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
816 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
817 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
819 &g_array_index(hooks
, LttvTraceHook
, 6));
822 before_hooks
= hooks
;
824 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 9);
825 g_array_set_size(hooks
, 9);
827 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
828 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
829 LTT_FIELD_SYSCALL_ID
, 0, 0,
831 &g_array_index(hooks
, LttvTraceHook
, 0));
834 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
835 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
838 &g_array_index(hooks
, LttvTraceHook
, 1));
841 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
842 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
843 LTT_FIELD_TRAP_ID
, 0, 0,
844 after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
847 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
848 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
850 after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
853 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
854 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
855 LTT_FIELD_IRQ_ID
, 0, 0,
856 after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
859 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
860 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
862 after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
866 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
867 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
868 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
870 &g_array_index(hooks
, LttvTraceHook
, 6));
873 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
874 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
876 process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
879 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
880 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
882 process_free
, &g_array_index(hooks
, LttvTraceHook
, 8));
888 /* Add these hooks to each event_by_id hooks list */
890 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
892 for(j
= 0 ; j
< nb_tracefile
; j
++) {
893 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
894 LttvTracefileContext
*, j
));
895 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
898 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
899 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
900 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
901 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
903 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
906 LTTV_PRIO_STATS_BEFORE_STATE
);
909 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
910 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
911 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
912 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
914 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
917 LTTV_PRIO_STATS_AFTER_STATE
);
921 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
923 *(val
.v_pointer
) = before_hooks
;
924 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
926 *(val
.v_pointer
) = after_hooks
;
930 // Hook wrapper. call_data is a traceset context.
931 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
933 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
935 lttv_stats_remove_event_hooks(tss
);
940 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
942 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
944 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
948 LttvTracefileStats
*tfs
;
952 GArray
*before_hooks
, *after_hooks
;
956 LttvTraceHookByFacility
*thf
;
958 LttvAttributeValue val
;
960 nb_trace
= lttv_traceset_number(traceset
);
961 for(i
= 0 ; i
< nb_trace
; i
++) {
962 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
963 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
965 before_hooks
= *(val
.v_pointer
);
966 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
968 after_hooks
= *(val
.v_pointer
);
970 /* Remove these hooks from each event_by_id hooks list */
972 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
974 for(j
= 0 ; j
< nb_tracefile
; j
++) {
975 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
976 LttvTracefileContext
*, j
));
977 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
980 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
981 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
982 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
983 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
984 lttv_hooks_remove_data(
985 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
990 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
991 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
992 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
993 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
994 lttv_hooks_remove_data(
995 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1001 g_debug("lttv_stats_remove_event_hooks()");
1002 g_array_free(before_hooks
, TRUE
);
1003 g_array_free(after_hooks
, TRUE
);
1008 static void module_init()
1010 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1011 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1012 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1013 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1014 LTTV_STATS_MODES
= g_quark_from_string("modes");
1015 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1016 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1017 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1018 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
1019 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1020 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1021 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1022 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1023 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1024 LTTV_STATS
= g_quark_from_string("statistics");
1025 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1026 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1029 static void module_destroy()
1034 LTTV_MODULE("stats", "Compute processes statistics", \
1035 "Accumulate statistics for event types, processes and CPUs", \
1036 module_init
, module_destroy
, "state");
1038 /* Change the places where stats are called (create/read/write stats)
1040 Check for options in batchtest.c to reduce writing and see what tests are
1041 best candidates for performance analysis. Once OK, commit, move to main
1042 and run tests. Update the gui for statistics. */