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>
36 LTTV_STATS_PROCESS_UNKNOWN
,
39 LTTV_STATS_MODE_TYPES
,
42 LTTV_STATS_EVENT_TYPES
,
44 LTTV_STATS_ELAPSED_TIME
,
46 LTTV_STATS_EVENTS_COUNT
,
49 LTTV_STATS_TRACEFILES
,
53 LTTV_STATS_BEFORE_HOOKS
,
54 LTTV_STATS_AFTER_HOOKS
;
57 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, GQuark cpu
,
58 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
59 LttvAttribute
**event_types_tree
);
62 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
64 guint i
, j
, nb_trace
, nb_tracefile
;
70 LttvTracefileContext
*tfc
;
72 LttvTracefileContext
**tfs
;
73 LttvTracefileStats
*tfcs
;
75 LttTime timestamp
= {0,0};
83 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
84 init((LttvTracesetContext
*)self
, 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 tfcs
->parent
.cpu_name
);
123 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
124 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
125 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
126 &tfcs
->current_event_types_tree
);
132 fini(LttvTracesetStats
*self
)
134 guint i
, j
, nb_trace
, nb_tracefile
;
138 LttvTraceContext
*tc
;
142 LttvTracefileContext
*tfc
;
144 LttvTracefileStats
*tfcs
;
146 LttTime timestamp
= {0,0};
148 LttvAttributeValue v
;
150 LttvAttribute
*tracefiles_stats
;
152 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
156 if(*(v
.v_uint
) == 0) {
157 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
161 ts
= self
->parent
.parent
.ts
;
162 nb_trace
= lttv_traceset_number(ts
);
164 for(i
= 0 ; i
< nb_trace
; i
++) {
165 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
167 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
171 if(*(v
.v_uint
) == 0) {
172 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
173 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
174 LTTV_STATS_TRACEFILES
);
175 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
176 LTTV_STATS_TRACEFILES
);
180 nb_tracefile
= tc
->tracefiles
->len
;
182 for(j
= 0 ; j
< nb_tracefile
; j
++) {
183 tfc
= g_array_index(tc
->tracefiles
,
184 LttvTracefileContext
*, j
);
185 tfcs
= (LttvTracefileStats
*)tfc
;
187 tfcs
->current_events_tree
= NULL
;
188 tfcs
->current_event_types_tree
= NULL
;
191 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
192 fini((LttvTracesetContext
*)self
);
196 static LttvTracesetContext
*
197 new_traceset_context(LttvTracesetContext
*self
)
199 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
203 static LttvTraceContext
*
204 new_trace_context(LttvTracesetContext
*self
)
206 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
210 static LttvTracefileContext
*
211 new_tracefile_context(LttvTracesetContext
*self
)
213 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
218 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
224 traceset_stats_finalize (LttvTracesetStats
*self
)
226 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
227 finalize(G_OBJECT(self
));
232 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
234 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
236 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
237 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
238 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
239 klass
->new_traceset_context
= new_traceset_context
;
240 klass
->new_trace_context
= new_trace_context
;
241 klass
->new_tracefile_context
= new_tracefile_context
;
246 lttv_traceset_stats_get_type(void)
248 static GType type
= 0;
250 static const GTypeInfo info
= {
251 sizeof (LttvTracesetStatsClass
),
252 NULL
, /* base_init */
253 NULL
, /* base_finalize */
254 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
255 NULL
, /* class_finalize */
256 NULL
, /* class_data */
257 sizeof (LttvTracesetStats
),
259 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
260 NULL
/* Value handling */
263 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
264 "LttvTracesetStatsType",
272 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
278 trace_stats_finalize (LttvTraceStats
*self
)
280 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
281 finalize(G_OBJECT(self
));
286 trace_stats_class_init (LttvTraceContextClass
*klass
)
288 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
290 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
295 lttv_trace_stats_get_type(void)
297 static GType type
= 0;
299 static const GTypeInfo info
= {
300 sizeof (LttvTraceStatsClass
),
301 NULL
, /* base_init */
302 NULL
, /* base_finalize */
303 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
304 NULL
, /* class_finalize */
305 NULL
, /* class_data */
306 sizeof (LttvTraceStats
),
308 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
309 NULL
/* Value handling */
312 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
313 "LttvTraceStatsType", &info
, 0);
320 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
326 tracefile_stats_finalize (LttvTracefileStats
*self
)
328 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
329 finalize(G_OBJECT(self
));
334 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
336 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
338 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
343 lttv_tracefile_stats_get_type(void)
345 static GType type
= 0;
347 static const GTypeInfo info
= {
348 sizeof (LttvTracefileStatsClass
),
349 NULL
, /* base_init */
350 NULL
, /* base_finalize */
351 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
352 NULL
, /* class_finalize */
353 NULL
, /* class_data */
354 sizeof (LttvTracefileStats
),
356 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
357 NULL
/* Value handling */
360 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
361 "LttvTracefileStatsType", &info
, 0);
368 find_event_tree(LttvTracefileStats
*tfcs
,
373 LttvAttribute
**events_tree
,
374 LttvAttribute
**event_types_tree
)
378 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
379 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
380 a
= lttv_attribute_find_subdir(a
, pid_time
);
381 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
382 a
= lttv_attribute_find_subdir(a
, cpu
);
383 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
384 a
= lttv_attribute_find_subdir(a
, mode
);
385 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
386 a
= lttv_attribute_find_subdir(a
, sub_mode
);
388 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
389 *event_types_tree
= a
;
393 static void update_event_tree(LttvTracefileStats
*tfcs
)
395 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
397 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
,
398 tfcs
->parent
.cpu_name
,
399 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
400 &(tfcs
->current_event_types_tree
));
404 static void mode_change(LttvTracefileStats
*tfcs
)
406 LttvAttributeValue cpu_time
;
410 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
411 LTTV_TIME
, &cpu_time
);
412 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
413 tfcs
->parent
.process
->state
->change
);
414 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
418 static void mode_end(LttvTracefileStats
*tfcs
)
420 LttvAttributeValue elapsed_time
, cpu_time
;
424 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
425 LTTV_TIME
, &elapsed_time
);
426 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
427 tfcs
->parent
.process
->state
->entry
);
428 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
430 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
431 LTTV_TIME
, &cpu_time
);
432 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
433 tfcs
->parent
.process
->state
->change
);
434 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
438 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
440 mode_change((LttvTracefileStats
*)call_data
);
445 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
447 update_event_tree((LttvTracefileStats
*)call_data
);
452 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
454 mode_end((LttvTracefileStats
*)call_data
);
459 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
461 update_event_tree((LttvTracefileStats
*)call_data
);
466 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
468 mode_change((LttvTracefileStats
*)call_data
);
473 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
475 update_event_tree((LttvTracefileStats
*)call_data
);
480 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
482 mode_end((LttvTracefileStats
*)call_data
);
487 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
489 update_event_tree((LttvTracefileStats
*)call_data
);
494 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
496 mode_change((LttvTracefileStats
*)call_data
);
501 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
503 update_event_tree((LttvTracefileStats
*)call_data
);
508 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
510 mode_end((LttvTracefileStats
*)call_data
);
515 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
517 update_event_tree((LttvTracefileStats
*)call_data
);
522 gboolean
before_schedchange(void *hook_data
, void *call_data
)
524 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
526 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
528 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
530 guint pid_in
, pid_out
;
534 LttvProcessState
*process
;
536 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
537 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
538 state_out
= ltt_event_get_int(e
, thf
->f3
);
540 /* compute the time for the process to schedule out */
544 /* get the information for the process scheduled in */
546 process
= lttv_state_find_process_or_create(&(tfcs
->parent
), pid_in
);
548 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
549 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
550 &(tfcs
->current_event_types_tree
));
552 /* compute the time waiting for the process to schedule in */
559 gboolean
process_fork(void *hook_data
, void *call_data
)
561 /* nothing to do for now */
566 gboolean
process_exit(void *hook_data
, void *call_data
)
568 /* We should probably exit all modes here or we could do that at
573 gboolean
process_free(void *hook_data
, void *call_data
)
578 gboolean
every_event(void *hook_data
, void *call_data
)
580 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
582 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
584 LttvAttributeValue v
;
586 /* The current branch corresponds to the tracefile/process/interrupt state.
587 Statistics are added within it, to count the number of events of this
588 type occuring in this context. A quark has been pre-allocated for each
589 event type and is used as name. */
591 lttv_attribute_find(tfcs
->current_event_types_tree
,
592 ltt_eventtype_name(ltt_event_eventtype(e
)),
600 lttv_stats_sum_trace(LttvTraceStats
*self
)
602 LttvAttribute
*sum_container
= self
->stats
;
604 LttvAttributeType type
;
606 LttvAttributeValue value
;
608 LttvAttributeName name
;
612 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
615 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
616 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
617 *submode_tree
, *event_types_tree
, *mode_events_tree
,
618 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
621 main_tree
= sum_container
;
623 lttv_attribute_find(sum_container
,
626 if(*(value
.v_uint
) != 0) return;
629 processes_tree
= lttv_attribute_find_subdir(main_tree
,
630 LTTV_STATS_PROCESSES
);
631 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
,
633 nb_process
= lttv_attribute_get_number(processes_tree
);
635 for(i
= 0 ; i
< nb_process
; i
++) {
636 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
637 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
639 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
640 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
642 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
644 for(j
= 0 ; j
< nb_cpu
; j
++) {
645 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
646 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
648 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
649 LTTV_STATS_MODE_TYPES
);
650 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
652 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
653 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
654 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
656 for(k
= 0 ; k
< nb_mode_type
; k
++) {
657 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
658 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
660 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
661 LTTV_STATS_SUBMODES
);
662 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
664 nb_submode
= lttv_attribute_get_number(submodes_tree
);
666 for(l
= 0 ; l
< nb_submode
; l
++) {
667 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
668 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
670 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
671 LTTV_STATS_EVENT_TYPES
);
672 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
675 for(m
= 0 ; m
< nb_event_type
; m
++) {
676 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
677 sum
+= *(value
.v_uint
);
679 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
681 *(value
.v_uint
) = sum
;
682 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
684 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
686 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
687 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
689 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
694 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
696 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
701 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
703 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
704 LttvAttribute
*sum_container
= self
->stats
;
710 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
712 LttvAttributeValue value
;
714 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
716 if(*(value
.v_uint
) != 0) return;
719 traceset_modes_tree
= lttv_attribute_find_subdir(sum_container
,
721 nb_trace
= lttv_traceset_number(traceset
);
723 for(i
= 0 ; i
< nb_trace
; i
++) {
724 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
725 lttv_stats_sum_trace(tcs
);
726 main_tree
= tcs
->stats
;
727 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
728 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
733 // Hook wrapper. call_data is a traceset context.
734 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
736 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
738 lttv_stats_add_event_hooks(tss
);
743 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
745 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
747 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
751 LttvTracefileStats
*tfs
;
753 GArray
*hooks
, *before_hooks
, *after_hooks
;
757 LttvTraceHookByFacility
*thf
;
759 LttvAttributeValue val
;
763 nb_trace
= lttv_traceset_number(traceset
);
764 for(i
= 0 ; i
< nb_trace
; i
++) {
765 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
767 /* Find the eventtype id for the following events and register the
768 associated by id hooks. */
770 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 7);
771 g_array_set_size(hooks
, 7);
773 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
774 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
775 LTT_FIELD_SYSCALL_ID
, 0, 0,
776 before_syscall_entry
, NULL
,
777 &g_array_index(hooks
, LttvTraceHook
, 0));
780 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
781 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
783 before_syscall_exit
, NULL
,
784 &g_array_index(hooks
, LttvTraceHook
, 1));
787 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
788 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
789 LTT_FIELD_TRAP_ID
, 0, 0,
790 before_trap_entry
, NULL
,
791 &g_array_index(hooks
, LttvTraceHook
, 2));
794 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
795 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
797 before_trap_exit
, NULL
,
798 &g_array_index(hooks
, LttvTraceHook
, 3));
801 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
802 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
803 LTT_FIELD_IRQ_ID
, 0, 0,
804 before_irq_entry
, NULL
,
805 &g_array_index(hooks
, LttvTraceHook
, 4));
808 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
809 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
811 before_irq_exit
, NULL
,
812 &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
,
818 before_schedchange
, NULL
,
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,
830 after_syscall_entry
, NULL
,
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
,
837 after_syscall_exit
, NULL
,
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
, NULL
,
845 &g_array_index(hooks
, LttvTraceHook
, 2));
848 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
849 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
851 after_trap_exit
, NULL
,
852 &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
, NULL
,
859 &g_array_index(hooks
, LttvTraceHook
, 4));
862 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
863 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
865 after_irq_exit
, NULL
,
866 &g_array_index(hooks
, LttvTraceHook
, 5));
870 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
871 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
872 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
874 &g_array_index(hooks
, LttvTraceHook
, 6));
877 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
878 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
881 &g_array_index(hooks
, LttvTraceHook
, 7));
884 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
885 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
888 &g_array_index(hooks
, LttvTraceHook
, 8));
894 /* Add these hooks to each event_by_id hooks list */
896 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
898 for(j
= 0 ; j
< nb_tracefile
; j
++) {
899 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
900 LttvTracefileContext
*, j
));
901 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
904 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
905 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
906 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
907 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
909 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
912 LTTV_PRIO_STATS_BEFORE_STATE
);
915 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
916 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
917 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
918 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
920 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
923 LTTV_PRIO_STATS_AFTER_STATE
);
927 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
929 *(val
.v_pointer
) = before_hooks
;
930 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
932 *(val
.v_pointer
) = after_hooks
;
936 // Hook wrapper. call_data is a traceset context.
937 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
939 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
941 lttv_stats_remove_event_hooks(tss
);
946 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
948 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
950 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
954 LttvTracefileStats
*tfs
;
958 GArray
*before_hooks
, *after_hooks
;
962 LttvTraceHookByFacility
*thf
;
964 LttvAttributeValue val
;
966 nb_trace
= lttv_traceset_number(traceset
);
967 for(i
= 0 ; i
< nb_trace
; i
++) {
968 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
969 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
971 before_hooks
= *(val
.v_pointer
);
972 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
974 after_hooks
= *(val
.v_pointer
);
976 /* Remove these hooks from each event_by_id hooks list */
978 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
980 for(j
= 0 ; j
< nb_tracefile
; j
++) {
981 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
982 LttvTracefileContext
*, j
));
983 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
986 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
987 hook
= &g_array_index(before_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
),
996 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
997 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
998 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
999 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1000 lttv_hooks_remove_data(
1001 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1007 g_debug("lttv_stats_remove_event_hooks()");
1008 g_array_free(before_hooks
, TRUE
);
1009 g_array_free(after_hooks
, TRUE
);
1014 static void module_init()
1016 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1017 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1018 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1019 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1020 LTTV_STATS_MODES
= g_quark_from_string("modes");
1021 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1022 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1023 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1024 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
1025 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1026 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1027 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1028 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1029 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1030 LTTV_STATS
= g_quark_from_string("statistics");
1031 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1032 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1035 static void module_destroy()
1040 LTTV_MODULE("stats", "Compute processes statistics", \
1041 "Accumulate statistics for event types, processes and CPUs", \
1042 module_init
, module_destroy
, "state");
1044 /* Change the places where stats are called (create/read/write stats)
1046 Check for options in batchtest.c to reduce writing and see what tests are
1047 best candidates for performance analysis. Once OK, commit, move to main
1048 and run tests. Update the gui for statistics. */