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
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
101 tcs
= (LttvTraceStats
*)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
;
754 LttvTracefileStats
*tfs
;
758 GArray
*hooks
, *before_hooks
, *after_hooks
;
762 LttvTraceHookByFacility
*thf
;
764 LttvAttributeValue val
;
768 nb_trace
= lttv_traceset_number(traceset
);
769 for(i
= 0 ; i
< nb_trace
; i
++) {
770 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
772 /* Find the eventtype id for the following events and register the
773 associated by id hooks. */
775 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 7);
776 g_array_set_size(hooks
, 7);
778 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
779 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
780 LTT_FIELD_SYSCALL_ID
, 0, 0,
781 before_syscall_entry
,
782 &g_array_index(hooks
, LttvTraceHook
, 0));
785 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
786 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
789 &g_array_index(hooks
, LttvTraceHook
, 1));
792 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
793 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
794 LTT_FIELD_TRAP_ID
, 0, 0,
796 &g_array_index(hooks
, LttvTraceHook
, 2));
799 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
800 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
802 before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
805 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
806 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
807 LTT_FIELD_IRQ_ID
, 0, 0,
808 before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
811 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
812 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
814 before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
817 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
818 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
819 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
821 &g_array_index(hooks
, LttvTraceHook
, 6));
824 before_hooks
= hooks
;
826 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 9);
827 g_array_set_size(hooks
, 9);
829 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
830 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
831 LTT_FIELD_SYSCALL_ID
, 0, 0,
833 &g_array_index(hooks
, LttvTraceHook
, 0));
836 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
837 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
840 &g_array_index(hooks
, LttvTraceHook
, 1));
843 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
844 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
845 LTT_FIELD_TRAP_ID
, 0, 0,
846 after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
849 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
850 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
852 after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
855 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
856 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
857 LTT_FIELD_IRQ_ID
, 0, 0,
858 after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
861 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
862 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
864 after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
868 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
869 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
870 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
872 &g_array_index(hooks
, LttvTraceHook
, 6));
875 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
876 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
878 process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
881 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
882 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
884 process_free
, &g_array_index(hooks
, LttvTraceHook
, 8));
890 /* Add these hooks to each event_by_id hooks list */
892 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
894 for(j
= 0 ; j
< nb_tracefile
; j
++) {
895 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
896 LttvTracefileContext
*, j
));
897 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
900 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
901 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
902 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
903 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
905 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
908 LTTV_PRIO_STATS_BEFORE_STATE
);
911 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
912 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
913 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
914 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
916 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
919 LTTV_PRIO_STATS_AFTER_STATE
);
923 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
925 *(val
.v_pointer
) = before_hooks
;
926 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
928 *(val
.v_pointer
) = after_hooks
;
932 // Hook wrapper. call_data is a traceset context.
933 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
935 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
937 lttv_stats_remove_event_hooks(tss
);
942 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
944 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
946 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
950 LttvTracefileStats
*tfs
;
954 GArray
*before_hooks
, *after_hooks
;
958 LttvTraceHookByFacility
*thf
;
960 LttvAttributeValue val
;
962 nb_trace
= lttv_traceset_number(traceset
);
963 for(i
= 0 ; i
< nb_trace
; i
++) {
964 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
965 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
967 before_hooks
= *(val
.v_pointer
);
968 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
970 after_hooks
= *(val
.v_pointer
);
972 /* Remove these hooks from each event_by_id hooks list */
974 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
976 for(j
= 0 ; j
< nb_tracefile
; j
++) {
977 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
978 LttvTracefileContext
*, j
));
979 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
982 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
983 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
984 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
985 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
986 lttv_hooks_remove_data(
987 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
992 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
993 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
994 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
995 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
996 lttv_hooks_remove_data(
997 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1003 g_debug("lttv_stats_remove_event_hooks()");
1004 g_array_free(before_hooks
, TRUE
);
1005 g_array_free(after_hooks
, TRUE
);
1010 static void module_init()
1012 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1013 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1014 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1015 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1016 LTTV_STATS_MODES
= g_quark_from_string("modes");
1017 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1018 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1019 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1020 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
1021 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1022 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1023 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1024 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1025 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1026 LTTV_STATS
= g_quark_from_string("statistics");
1027 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1028 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1031 static void module_destroy()
1036 LTTV_MODULE("stats", "Compute processes statistics", \
1037 "Accumulate statistics for event types, processes and CPUs", \
1038 module_init
, module_destroy
, "state");
1040 /* Change the places where stats are called (create/read/write stats)
1042 Check for options in batchtest.c to reduce writing and see what tests are
1043 best candidates for performance analysis. Once OK, commit, move to main
1044 and run tests. Update the gui for statistics. */