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,
21 #include <lttv/module.h>
22 #include <lttv/stats.h>
23 #include <lttv/lttv.h>
24 #include <lttv/attribute.h>
25 #include <ltt/facility.h>
26 #include <ltt/trace.h>
27 #include <ltt/event.h>
32 LTTV_STATS_PROCESS_UNKNOWN
,
35 LTTV_STATS_MODE_TYPES
,
38 LTTV_STATS_EVENT_TYPES
,
40 LTTV_STATS_ELAPSED_TIME
,
42 LTTV_STATS_EVENTS_COUNT
,
45 LTTV_STATS_TRACEFILES
,
49 LTTV_STATS_BEFORE_HOOKS
,
50 LTTV_STATS_AFTER_HOOKS
;
52 static void remove_all_processes(GHashTable
*processes
);
55 find_event_tree(LttvTracefileStats
*tfcs
, GQuark process
, GQuark cpu
,
56 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
57 LttvAttribute
**event_types_tree
);
60 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
62 guint i
, j
, nb_trace
, nb_tracefile
;
68 LttvTracefileContext
*tfc
;
70 LttvTracefileStats
*tfcs
;
72 LttTime timestamp
= {0,0};
80 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
81 init((LttvTracesetContext
*)self
, ts
);
83 self
->stats
=lttv_attribute_find_subdir(self
->parent
.parent
.ts_a
,LTTV_STATS
);
84 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
88 if(*(v
.v_uint
) == 1) {
89 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
92 nb_trace
= lttv_traceset_number(ts
);
94 for(i
= 0 ; i
< nb_trace
; i
++) {
95 tcs
= (LttvTraceStats
*)tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
97 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
98 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
99 LTTV_STATS_TRACEFILES
);
100 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
104 if(*(v
.v_uint
) == 1) {
105 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
108 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
109 ltt_trace_per_cpu_tracefile_number(tc
->t
);
111 for(j
= 0 ; j
< nb_tracefile
; j
++) {
112 tfcs
= LTTV_TRACEFILE_STATS(tc
->tracefiles
[j
]);
113 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
114 tfcs
->parent
.cpu_name
);
115 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
116 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
117 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
118 &tfcs
->current_event_types_tree
);
125 fini(LttvTracesetStats
*self
)
127 guint i
, j
, nb_trace
, nb_tracefile
;
131 LttvTraceContext
*tc
;
135 LttvTracefileContext
*tfc
;
137 LttvTracefileStats
*tfcs
;
139 LttTime timestamp
= {0,0};
141 LttvAttributeValue v
;
143 LttvAttribute
*tracefiles_stats
;
145 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
149 if(*(v
.v_uint
) == 0) {
150 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
151 lttv_attribute_recursive_free(self
->stats
);
155 ts
= self
->parent
.parent
.ts
;
156 nb_trace
= lttv_traceset_number(ts
);
158 for(i
= 0 ; i
< nb_trace
; i
++) {
159 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
161 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
165 if(*(v
.v_uint
) == 0) {
166 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
167 lttv_attribute_recursive_free(tcs
->stats
);
168 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
169 LTTV_STATS_TRACEFILES
);
170 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
171 LTTV_STATS_TRACEFILES
);
172 lttv_attribute_recursive_free(tracefiles_stats
);
176 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
177 ltt_trace_per_cpu_tracefile_number(tc
->t
);
179 for(j
= 0 ; j
< nb_tracefile
; j
++) {
180 tfcs
= ((LttvTracefileStats
*)tfc
= tc
->tracefiles
[j
]);
182 tfcs
->current_events_tree
= NULL
;
183 tfcs
->current_event_types_tree
= NULL
;
186 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
187 fini((LttvTracesetContext
*)self
);
191 static LttvTracesetContext
*
192 new_traceset_context(LttvTracesetContext
*self
)
194 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
198 static LttvTraceContext
*
199 new_trace_context(LttvTracesetContext
*self
)
201 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
205 static LttvTracefileContext
*
206 new_tracefile_context(LttvTracesetContext
*self
)
208 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
213 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
219 traceset_stats_finalize (LttvTracesetStats
*self
)
221 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
222 finalize(G_OBJECT(self
));
227 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
229 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
231 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
232 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
233 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
234 klass
->new_traceset_context
= new_traceset_context
;
235 klass
->new_trace_context
= new_trace_context
;
236 klass
->new_tracefile_context
= new_tracefile_context
;
241 lttv_traceset_stats_get_type(void)
243 static GType type
= 0;
245 static const GTypeInfo info
= {
246 sizeof (LttvTracesetStatsClass
),
247 NULL
, /* base_init */
248 NULL
, /* base_finalize */
249 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
250 NULL
, /* class_finalize */
251 NULL
, /* class_data */
252 sizeof (LttvTracesetStats
),
254 (GInstanceInitFunc
) traceset_stats_instance_init
/* instance_init */
257 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
, "LttvTracesetStatsType",
265 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
271 trace_stats_finalize (LttvTraceStats
*self
)
273 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
274 finalize(G_OBJECT(self
));
279 trace_stats_class_init (LttvTraceContextClass
*klass
)
281 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
283 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
288 lttv_trace_stats_get_type(void)
290 static GType type
= 0;
292 static const GTypeInfo info
= {
293 sizeof (LttvTraceStatsClass
),
294 NULL
, /* base_init */
295 NULL
, /* base_finalize */
296 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
297 NULL
, /* class_finalize */
298 NULL
, /* class_data */
299 sizeof (LttvTraceStats
),
301 (GInstanceInitFunc
) trace_stats_instance_init
/* instance_init */
304 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
305 "LttvTraceStatsType", &info
, 0);
312 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
318 tracefile_stats_finalize (LttvTracefileStats
*self
)
320 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
321 finalize(G_OBJECT(self
));
326 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
328 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
330 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
335 lttv_tracefile_stats_get_type(void)
337 static GType type
= 0;
339 static const GTypeInfo info
= {
340 sizeof (LttvTracefileStatsClass
),
341 NULL
, /* base_init */
342 NULL
, /* base_finalize */
343 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
344 NULL
, /* class_finalize */
345 NULL
, /* class_data */
346 sizeof (LttvTracefileStats
),
348 (GInstanceInitFunc
) tracefile_stats_instance_init
/* instance_init */
351 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
352 "LttvTracefileStatsType", &info
, 0);
359 find_event_tree(LttvTracefileStats
*tfcs
, GQuark process
, GQuark cpu
,
360 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
361 LttvAttribute
**event_types_tree
)
365 LttvTraceStats
*tcs
= LTTV_TRACE_STATS(tfcs
->parent
.parent
.t_context
);
366 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
367 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->pid_time
);
368 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
369 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.cpu_name
);
370 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
371 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->t
);
372 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
373 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->n
);
375 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
376 *event_types_tree
= a
;
380 static void update_event_tree(LttvTracefileStats
*tfcs
)
382 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
384 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
, tfcs
->parent
.cpu_name
,
385 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
386 &(tfcs
->current_event_types_tree
));
390 static void mode_change(LttvTracefileStats
*tfcs
)
392 LttvAttributeValue cpu_time
;
396 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
397 LTTV_TIME
, &cpu_time
);
398 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
399 tfcs
->parent
.process
->state
->change
);
400 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
404 static void mode_end(LttvTracefileStats
*tfcs
)
406 LttvAttributeValue elapsed_time
, cpu_time
;
410 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
411 LTTV_TIME
, &elapsed_time
);
412 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
413 tfcs
->parent
.process
->state
->entry
);
414 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
416 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
417 LTTV_TIME
, &cpu_time
);
418 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
419 tfcs
->parent
.process
->state
->change
);
420 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
424 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
426 mode_change((LttvTracefileStats
*)call_data
);
431 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
433 update_event_tree((LttvTracefileStats
*)call_data
);
438 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
440 mode_end((LttvTracefileStats
*)call_data
);
445 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
447 update_event_tree((LttvTracefileStats
*)call_data
);
452 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
454 mode_change((LttvTracefileStats
*)call_data
);
459 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
461 update_event_tree((LttvTracefileStats
*)call_data
);
466 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
468 mode_end((LttvTracefileStats
*)call_data
);
473 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
475 update_event_tree((LttvTracefileStats
*)call_data
);
480 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
482 mode_change((LttvTracefileStats
*)call_data
);
487 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
489 update_event_tree((LttvTracefileStats
*)call_data
);
494 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
496 mode_end((LttvTracefileStats
*)call_data
);
501 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
503 update_event_tree((LttvTracefileStats
*)call_data
);
508 gboolean
before_schedchange(void *hook_data
, void *call_data
)
510 LttvTraceHook
*h
= (LttvTraceHook
*)hook_data
;
512 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
514 guint pid_in
, pid_out
, state_out
;
516 LttvProcessState
*process
;
518 pid_in
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f1
);
519 pid_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f2
);
520 state_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f3
);
522 /* compute the time for the process to schedule out */
526 /* get the information for the process scheduled in */
528 process
= lttv_state_find_process_or_create(&(tfcs
->parent
), pid_in
);
530 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
531 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
532 &(tfcs
->current_event_types_tree
));
534 /* compute the time waiting for the process to schedule in */
541 gboolean
process_fork(void *hook_data
, void *call_data
)
543 /* nothing to do for now */
548 gboolean
process_exit(void *hook_data
, void *call_data
)
550 /* We should probably exit all modes here or we could do that at
556 gboolean
every_event(void *hook_data
, void *call_data
)
558 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
560 LttvAttributeValue v
;
562 /* The current branch corresponds to the tracefile/process/interrupt state.
563 Statistics are added within it, to count the number of events of this
564 type occuring in this context. A quark has been pre-allocated for each
565 event type and is used as name. */
567 lttv_attribute_find(tfcs
->current_event_types_tree
,
568 ((LttvTraceState
*)(tfcs
->parent
.parent
.t_context
))->
569 eventtype_names
[ltt_event_eventtype_id(tfcs
->parent
.parent
.e
)],
577 lttv_stats_sum_trace(LttvTraceStats
*self
)
581 LttvAttributeType type
;
583 LttvAttributeValue value
;
585 LttvAttributeName name
;
589 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
592 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
593 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
594 *submode_tree
, *event_types_tree
, *mode_events_tree
,
595 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
598 main_tree
= self
->stats
;
600 lttv_attribute_find(self
->parent
.parent
.t_a
, LTTV_STATS_SUMMED
,
602 if(*(value
.v_uint
) != 0) return;
605 processes_tree
= lttv_attribute_find_subdir(main_tree
,
606 LTTV_STATS_PROCESSES
);
607 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
608 nb_process
= lttv_attribute_get_number(processes_tree
);
610 for(i
= 0 ; i
< nb_process
; i
++) {
611 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
612 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
614 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
615 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
617 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
619 for(j
= 0 ; j
< nb_cpu
; j
++) {
620 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
621 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
623 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
624 LTTV_STATS_MODE_TYPES
);
625 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
627 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
628 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
629 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
631 for(k
= 0 ; k
< nb_mode_type
; k
++) {
632 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
633 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
635 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
636 LTTV_STATS_SUBMODES
);
637 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
639 nb_submode
= lttv_attribute_get_number(submodes_tree
);
641 for(l
= 0 ; l
< nb_submode
; l
++) {
642 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
643 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
645 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
646 LTTV_STATS_EVENT_TYPES
);
647 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
650 for(m
= 0 ; m
< nb_event_type
; m
++) {
651 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
652 sum
+= *(value
.v_uint
);
654 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
656 *(value
.v_uint
) = sum
;
657 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
659 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
661 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
662 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
664 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
670 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
672 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
678 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
680 LttvAttributeValue value
;
682 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_SUMMED
,
684 if(*(value
.v_uint
) != 0) return;
687 traceset_modes_tree
= lttv_attribute_find_subdir(self
->stats
,
689 nb_trace
= lttv_traceset_number(traceset
);
691 for(i
= 0 ; i
< nb_trace
; i
++) {
692 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
693 lttv_stats_sum_trace(tcs
);
694 main_tree
= tcs
->stats
;
695 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
696 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
701 lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
703 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
705 guint i
, j
, k
, nb_trace
, nb_tracefile
;
713 LttvTracefileStats
*tfs
;
717 GArray
*hooks
, *before_hooks
, *after_hooks
;
721 LttvAttributeValue val
;
723 nb_trace
= lttv_traceset_number(traceset
);
724 for(i
= 0 ; i
< nb_trace
; i
++) {
725 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
727 /* Find the eventtype id for the following events and register the
728 associated by id hooks. */
730 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
731 g_array_set_size(hooks
, 7);
733 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
734 "syscall_id", NULL
, NULL
, before_syscall_entry
,
735 &g_array_index(hooks
, LttvTraceHook
, 0));
737 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
738 NULL
, NULL
, before_syscall_exit
,
739 &g_array_index(hooks
, LttvTraceHook
, 1));
741 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
742 NULL
, NULL
, before_trap_entry
,
743 &g_array_index(hooks
, LttvTraceHook
, 2));
745 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
746 NULL
, before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
748 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
749 NULL
, NULL
, before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
751 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
752 NULL
, before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
754 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "schedchange", "in",
755 "out", "out_state", before_schedchange
,
756 &g_array_index(hooks
, LttvTraceHook
, 6));
758 before_hooks
= hooks
;
760 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
761 g_array_set_size(hooks
, 8);
763 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
764 "syscall_id", NULL
, NULL
, after_syscall_entry
,
765 &g_array_index(hooks
, LttvTraceHook
, 0));
767 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
768 NULL
, NULL
, after_syscall_exit
,
769 &g_array_index(hooks
, LttvTraceHook
, 1));
771 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
772 NULL
, NULL
, after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
774 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
775 NULL
, after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
777 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
778 NULL
, NULL
, after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
780 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
781 NULL
, after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
783 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_fork",
784 "child_pid", NULL
, NULL
, process_fork
,
785 &g_array_index(hooks
, LttvTraceHook
, 6));
787 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_exit", NULL
,
788 NULL
, NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
792 /* Add these hooks to each before_event_by_id hooks list */
794 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
795 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
797 for(j
= 0 ; j
< nb_tracefile
; j
++) {
798 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
799 lttv_hooks_add(tfs
->parent
.parent
.after_event
, every_event
, NULL
);
801 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
802 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
803 lttv_hooks_add(lttv_hooks_by_id_find(
804 tfs
->parent
.parent
.before_event_by_id
,
805 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
807 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
808 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
809 lttv_hooks_add(lttv_hooks_by_id_find(
810 tfs
->parent
.parent
.after_event_by_id
,
811 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
814 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
816 *(val
.v_pointer
) = before_hooks
;
817 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
819 *(val
.v_pointer
) = after_hooks
;
824 lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
826 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
828 guint i
, j
, k
, nb_trace
, nb_tracefile
;
832 LttvTracefileStats
*tfs
;
836 GArray
*before_hooks
, *after_hooks
;
840 LttvAttributeValue val
;
842 nb_trace
= lttv_traceset_number(traceset
);
843 for(i
= 0 ; i
< nb_trace
; i
++) {
844 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
845 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
847 before_hooks
= *(val
.v_pointer
);
848 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
850 after_hooks
= *(val
.v_pointer
);
852 /* Add these hooks to each before_event_by_id hooks list */
854 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
855 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
857 for(j
= 0 ; j
< nb_tracefile
; j
++) {
858 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
859 lttv_hooks_remove_data(tfs
->parent
.parent
.after_event
, every_event
,
862 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
863 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
864 lttv_hooks_remove_data(
865 lttv_hooks_by_id_find(tfs
->parent
.parent
.before_event_by_id
,
866 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
868 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
869 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
870 lttv_hooks_remove_data(
871 lttv_hooks_by_id_find(tfs
->parent
.parent
.after_event_by_id
,
872 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
875 g_debug("lttv_stats_remove_event_hooks()");
876 g_array_free(before_hooks
, TRUE
);
877 g_array_free(after_hooks
, TRUE
);
882 static void module_init()
884 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
885 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
886 LTTV_STATS_CPU
= g_quark_from_string("cpu");
887 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
888 LTTV_STATS_MODES
= g_quark_from_string("modes");
889 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
890 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
891 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
892 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
893 LTTV_STATS_EVENTS
= g_quark_from_string("events");
894 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
895 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
896 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
897 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
898 LTTV_STATS
= g_quark_from_string("statistics");
899 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
900 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
903 static void module_destroy()
908 LTTV_MODULE("stats", "Compute processes statistics", \
909 "Accumulate statistics for event types, processes and CPUs", \
910 module_init
, module_destroy
, "state");
912 /* Change the places where stats are called (create/read/write stats)
914 Check for options in batchtest.c to reduce writing and see what tests are
915 best candidates for performance analysis. Once OK, commit, move to main
916 and run tests. Update the gui for statistics. */