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 LttvTracefileContext
**tfs
;
72 LttvTracefileStats
*tfcs
;
74 LttTime timestamp
= {0,0};
82 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
83 init((LttvTracesetContext
*)self
, ts
);
85 self
->stats
= lttv_attribute_find_subdir(
86 lttv_traceset_attribute(self
->parent
.parent
.ts
),
88 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
93 if(*(v
.v_uint
) == 1) {
94 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
97 nb_trace
= lttv_traceset_number(ts
);
99 for(i
= 0 ; i
< nb_trace
; i
++) {
100 tc
= self
->parent
.parent
.traces
[i
];
101 tcs
= LTTV_TRACE_STATS(tc
);
103 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
104 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
105 LTTV_STATS_TRACEFILES
);
106 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
110 if(*(v
.v_uint
) == 1) {
111 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
114 nb_tracefile
= tc
->tracefiles
->len
;
116 for(j
= 0 ; j
< nb_tracefile
; j
++) {
117 tfs
= &g_array_index(tc
->tracefiles
,
118 LttvTracefileContext
*, j
);
119 tfcs
= LTTV_TRACEFILE_STATS(*tfs
);
120 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
121 tfcs
->parent
.cpu_name
);
122 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
123 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
124 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
125 &tfcs
->current_event_types_tree
);
131 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
;
190 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
191 fini((LttvTracesetContext
*)self
);
195 static LttvTracesetContext
*
196 new_traceset_context(LttvTracesetContext
*self
)
198 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
202 static LttvTraceContext
*
203 new_trace_context(LttvTracesetContext
*self
)
205 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
209 static LttvTracefileContext
*
210 new_tracefile_context(LttvTracesetContext
*self
)
212 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
217 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
223 traceset_stats_finalize (LttvTracesetStats
*self
)
225 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
226 finalize(G_OBJECT(self
));
231 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
233 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
235 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
236 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
237 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
238 klass
->new_traceset_context
= new_traceset_context
;
239 klass
->new_trace_context
= new_trace_context
;
240 klass
->new_tracefile_context
= new_tracefile_context
;
245 lttv_traceset_stats_get_type(void)
247 static GType type
= 0;
249 static const GTypeInfo info
= {
250 sizeof (LttvTracesetStatsClass
),
251 NULL
, /* base_init */
252 NULL
, /* base_finalize */
253 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
254 NULL
, /* class_finalize */
255 NULL
, /* class_data */
256 sizeof (LttvTracesetStats
),
258 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
259 NULL
/* Value handling */
262 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
263 "LttvTracesetStatsType",
271 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
277 trace_stats_finalize (LttvTraceStats
*self
)
279 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
280 finalize(G_OBJECT(self
));
285 trace_stats_class_init (LttvTraceContextClass
*klass
)
287 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
289 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
294 lttv_trace_stats_get_type(void)
296 static GType type
= 0;
298 static const GTypeInfo info
= {
299 sizeof (LttvTraceStatsClass
),
300 NULL
, /* base_init */
301 NULL
, /* base_finalize */
302 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
303 NULL
, /* class_finalize */
304 NULL
, /* class_data */
305 sizeof (LttvTraceStats
),
307 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
308 NULL
/* Value handling */
311 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
312 "LttvTraceStatsType", &info
, 0);
319 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
325 tracefile_stats_finalize (LttvTracefileStats
*self
)
327 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
328 finalize(G_OBJECT(self
));
333 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
335 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
337 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
342 lttv_tracefile_stats_get_type(void)
344 static GType type
= 0;
346 static const GTypeInfo info
= {
347 sizeof (LttvTracefileStatsClass
),
348 NULL
, /* base_init */
349 NULL
, /* base_finalize */
350 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
351 NULL
, /* class_finalize */
352 NULL
, /* class_data */
353 sizeof (LttvTracefileStats
),
355 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
356 NULL
/* Value handling */
359 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
360 "LttvTracefileStatsType", &info
, 0);
367 find_event_tree(LttvTracefileStats
*tfcs
,
372 LttvAttribute
**events_tree
,
373 LttvAttribute
**event_types_tree
)
377 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
378 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
379 a
= lttv_attribute_find_subdir(a
, pid_time
);
380 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
381 a
= lttv_attribute_find_subdir(a
, cpu
);
382 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
383 a
= lttv_attribute_find_subdir(a
, mode
);
384 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
385 a
= lttv_attribute_find_subdir(a
, sub_mode
);
387 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
388 *event_types_tree
= a
;
392 static void update_event_tree(LttvTracefileStats
*tfcs
)
394 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
396 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
,
397 tfcs
->parent
.cpu_name
,
398 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
399 &(tfcs
->current_event_types_tree
));
403 static void mode_change(LttvTracefileStats
*tfcs
)
405 LttvAttributeValue cpu_time
;
409 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
410 LTTV_TIME
, &cpu_time
);
411 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
412 tfcs
->parent
.process
->state
->change
);
413 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
417 static void mode_end(LttvTracefileStats
*tfcs
)
419 LttvAttributeValue elapsed_time
, cpu_time
;
423 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
424 LTTV_TIME
, &elapsed_time
);
425 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
426 tfcs
->parent
.process
->state
->entry
);
427 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
429 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
430 LTTV_TIME
, &cpu_time
);
431 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
432 tfcs
->parent
.process
->state
->change
);
433 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
437 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
439 mode_change((LttvTracefileStats
*)call_data
);
444 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
446 update_event_tree((LttvTracefileStats
*)call_data
);
451 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
453 mode_end((LttvTracefileStats
*)call_data
);
458 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
460 update_event_tree((LttvTracefileStats
*)call_data
);
465 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
467 mode_change((LttvTracefileStats
*)call_data
);
472 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
474 update_event_tree((LttvTracefileStats
*)call_data
);
479 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
481 mode_end((LttvTracefileStats
*)call_data
);
486 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
488 update_event_tree((LttvTracefileStats
*)call_data
);
493 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
495 mode_change((LttvTracefileStats
*)call_data
);
500 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
502 update_event_tree((LttvTracefileStats
*)call_data
);
507 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
509 mode_end((LttvTracefileStats
*)call_data
);
514 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
516 update_event_tree((LttvTracefileStats
*)call_data
);
521 gboolean
before_schedchange(void *hook_data
, void *call_data
)
523 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
525 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
527 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
529 guint pid_in
, pid_out
;
533 LttvProcessState
*process
;
535 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
536 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
537 state_out
= ltt_event_get_int(e
, thf
->f3
);
539 /* compute the time for the process to schedule out */
543 /* get the information for the process scheduled in */
545 process
= lttv_state_find_process_or_create(&(tfcs
->parent
), pid_in
);
547 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
548 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
549 &(tfcs
->current_event_types_tree
));
551 /* compute the time waiting for the process to schedule in */
558 gboolean
process_fork(void *hook_data
, void *call_data
)
560 /* nothing to do for now */
565 gboolean
process_exit(void *hook_data
, void *call_data
)
567 /* We should probably exit all modes here or we could do that at
572 gboolean
process_free(void *hook_data
, void *call_data
)
577 gboolean
every_event(void *hook_data
, void *call_data
)
579 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
581 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
583 LttvAttributeValue v
;
585 /* The current branch corresponds to the tracefile/process/interrupt state.
586 Statistics are added within it, to count the number of events of this
587 type occuring in this context. A quark has been pre-allocated for each
588 event type and is used as name. */
590 lttv_attribute_find(tfcs
->current_event_types_tree
,
591 ltt_eventtype_name(ltt_event_eventtype(e
)),
599 lttv_stats_sum_trace(LttvTraceStats
*self
)
601 LttvAttribute
*sum_container
= self
->stats
;
603 LttvAttributeType type
;
605 LttvAttributeValue value
;
607 LttvAttributeName name
;
611 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
614 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
615 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
616 *submode_tree
, *event_types_tree
, *mode_events_tree
,
617 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
620 main_tree
= sum_container
;
622 lttv_attribute_find(sum_container
,
625 if(*(value
.v_uint
) != 0) return;
628 processes_tree
= lttv_attribute_find_subdir(main_tree
,
629 LTTV_STATS_PROCESSES
);
630 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
,
632 nb_process
= lttv_attribute_get_number(processes_tree
);
634 for(i
= 0 ; i
< nb_process
; i
++) {
635 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
636 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
638 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
639 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
641 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
643 for(j
= 0 ; j
< nb_cpu
; j
++) {
644 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
645 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
647 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
648 LTTV_STATS_MODE_TYPES
);
649 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
651 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
652 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
653 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
655 for(k
= 0 ; k
< nb_mode_type
; k
++) {
656 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
657 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
659 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
660 LTTV_STATS_SUBMODES
);
661 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
663 nb_submode
= lttv_attribute_get_number(submodes_tree
);
665 for(l
= 0 ; l
< nb_submode
; l
++) {
666 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
667 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
669 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
670 LTTV_STATS_EVENT_TYPES
);
671 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
674 for(m
= 0 ; m
< nb_event_type
; m
++) {
675 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
676 sum
+= *(value
.v_uint
);
678 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
680 *(value
.v_uint
) = sum
;
681 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
683 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
685 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
686 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
688 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
693 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
695 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
700 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
702 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
703 LttvAttribute
*sum_container
= self
->stats
;
709 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
711 LttvAttributeValue value
;
713 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
715 if(*(value
.v_uint
) != 0) return;
718 traceset_modes_tree
= lttv_attribute_find_subdir(sum_container
,
720 nb_trace
= lttv_traceset_number(traceset
);
722 for(i
= 0 ; i
< nb_trace
; i
++) {
723 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
724 lttv_stats_sum_trace(tcs
);
725 main_tree
= tcs
->stats
;
726 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
727 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
732 // Hook wrapper. call_data is a traceset context.
733 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
735 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
737 lttv_stats_add_event_hooks(tss
);
742 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
744 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
746 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
750 LttvTracefileStats
*tfs
;
752 GArray
*hooks
, *before_hooks
, *after_hooks
;
756 LttvTraceHookByFacility
*thf
;
758 LttvAttributeValue val
;
762 nb_trace
= lttv_traceset_number(traceset
);
763 for(i
= 0 ; i
< nb_trace
; i
++) {
764 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
766 /* Find the eventtype id for the following events and register the
767 associated by id hooks. */
769 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 7);
770 g_array_set_size(hooks
, 7);
772 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
773 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
774 LTT_FIELD_SYSCALL_ID
, 0, 0,
775 before_syscall_entry
,
776 &g_array_index(hooks
, LttvTraceHook
, 0));
779 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
780 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
783 &g_array_index(hooks
, LttvTraceHook
, 1));
786 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
787 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
788 LTT_FIELD_TRAP_ID
, 0, 0,
790 &g_array_index(hooks
, LttvTraceHook
, 2));
793 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
794 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
796 before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
799 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
800 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
801 LTT_FIELD_IRQ_ID
, 0, 0,
802 before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
805 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
806 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
808 before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
811 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
812 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
813 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
815 &g_array_index(hooks
, LttvTraceHook
, 6));
818 before_hooks
= hooks
;
820 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 9);
821 g_array_set_size(hooks
, 9);
823 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
824 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
825 LTT_FIELD_SYSCALL_ID
, 0, 0,
827 &g_array_index(hooks
, LttvTraceHook
, 0));
830 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
831 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
834 &g_array_index(hooks
, LttvTraceHook
, 1));
837 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
838 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
839 LTT_FIELD_TRAP_ID
, 0, 0,
840 after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
843 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
844 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
846 after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
849 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
850 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
851 LTT_FIELD_IRQ_ID
, 0, 0,
852 after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
855 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
856 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
858 after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
862 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
863 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
864 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
866 &g_array_index(hooks
, LttvTraceHook
, 6));
869 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
870 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
872 process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
875 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
876 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
878 process_free
, &g_array_index(hooks
, LttvTraceHook
, 8));
884 /* Add these hooks to each event_by_id hooks list */
886 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
888 for(j
= 0 ; j
< nb_tracefile
; j
++) {
889 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
890 LttvTracefileContext
*, j
));
891 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
894 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
895 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
896 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
897 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
899 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
902 LTTV_PRIO_STATS_BEFORE_STATE
);
905 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
906 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
907 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
908 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
910 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
913 LTTV_PRIO_STATS_AFTER_STATE
);
917 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
919 *(val
.v_pointer
) = before_hooks
;
920 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
922 *(val
.v_pointer
) = after_hooks
;
926 // Hook wrapper. call_data is a traceset context.
927 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
929 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
931 lttv_stats_remove_event_hooks(tss
);
936 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
938 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
940 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
944 LttvTracefileStats
*tfs
;
948 GArray
*before_hooks
, *after_hooks
;
952 LttvTraceHookByFacility
*thf
;
954 LttvAttributeValue val
;
956 nb_trace
= lttv_traceset_number(traceset
);
957 for(i
= 0 ; i
< nb_trace
; i
++) {
958 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
959 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
961 before_hooks
= *(val
.v_pointer
);
962 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
964 after_hooks
= *(val
.v_pointer
);
966 /* Remove these hooks from each event_by_id hooks list */
968 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
970 for(j
= 0 ; j
< nb_tracefile
; j
++) {
971 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
972 LttvTracefileContext
*, j
));
973 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
976 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
977 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
978 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
979 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
980 lttv_hooks_remove_data(
981 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
986 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
987 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
988 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
989 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
990 lttv_hooks_remove_data(
991 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
997 g_debug("lttv_stats_remove_event_hooks()");
998 g_array_free(before_hooks
, TRUE
);
999 g_array_free(after_hooks
, TRUE
);
1004 static void module_init()
1006 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1007 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1008 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1009 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1010 LTTV_STATS_MODES
= g_quark_from_string("modes");
1011 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1012 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1013 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1014 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
1015 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1016 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1017 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1018 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1019 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1020 LTTV_STATS
= g_quark_from_string("statistics");
1021 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1022 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1025 static void module_destroy()
1030 LTTV_MODULE("stats", "Compute processes statistics", \
1031 "Accumulate statistics for event types, processes and CPUs", \
1032 module_init
, module_destroy
, "state");
1034 /* Change the places where stats are called (create/read/write stats)
1036 Check for options in batchtest.c to reduce writing and see what tests are
1037 best candidates for performance analysis. Once OK, commit, move to main
1038 and run tests. Update the gui for statistics. */