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 tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
96 tcs
= (LttvTraceStats
*)tc
;
98 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
99 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
100 LTTV_STATS_TRACEFILES
);
101 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
105 if(*(v
.v_uint
) == 1) {
106 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
109 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
110 ltt_trace_per_cpu_tracefile_number(tc
->t
);
112 for(j
= 0 ; j
< nb_tracefile
; j
++) {
113 tfcs
= LTTV_TRACEFILE_STATS(tc
->tracefiles
[j
]);
114 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
115 tfcs
->parent
.cpu_name
);
116 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
117 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
118 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
119 &tfcs
->current_event_types_tree
);
126 fini(LttvTracesetStats
*self
)
128 guint i
, j
, nb_trace
, nb_tracefile
;
132 LttvTraceContext
*tc
;
136 LttvTracefileContext
*tfc
;
138 LttvTracefileStats
*tfcs
;
140 LttTime timestamp
= {0,0};
142 LttvAttributeValue v
;
144 LttvAttribute
*tracefiles_stats
;
146 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
150 if(*(v
.v_uint
) == 0) {
151 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
152 lttv_attribute_recursive_free(self
->stats
);
156 ts
= self
->parent
.parent
.ts
;
157 nb_trace
= lttv_traceset_number(ts
);
159 for(i
= 0 ; i
< nb_trace
; i
++) {
160 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
162 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
166 if(*(v
.v_uint
) == 0) {
167 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
168 lttv_attribute_recursive_free(tcs
->stats
);
169 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
170 LTTV_STATS_TRACEFILES
);
171 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
172 LTTV_STATS_TRACEFILES
);
173 lttv_attribute_recursive_free(tracefiles_stats
);
177 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
178 ltt_trace_per_cpu_tracefile_number(tc
->t
);
180 for(j
= 0 ; j
< nb_tracefile
; j
++) {
181 tfc
= tc
->tracefiles
[j
];
182 tfcs
= (LttvTracefileStats
*)tfc
;
184 tfcs
->current_events_tree
= NULL
;
185 tfcs
->current_event_types_tree
= NULL
;
188 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
189 fini((LttvTracesetContext
*)self
);
193 static LttvTracesetContext
*
194 new_traceset_context(LttvTracesetContext
*self
)
196 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
200 static LttvTraceContext
*
201 new_trace_context(LttvTracesetContext
*self
)
203 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
207 static LttvTracefileContext
*
208 new_tracefile_context(LttvTracesetContext
*self
)
210 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
215 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
221 traceset_stats_finalize (LttvTracesetStats
*self
)
223 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
224 finalize(G_OBJECT(self
));
229 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
231 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
233 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
234 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
235 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
236 klass
->new_traceset_context
= new_traceset_context
;
237 klass
->new_trace_context
= new_trace_context
;
238 klass
->new_tracefile_context
= new_tracefile_context
;
243 lttv_traceset_stats_get_type(void)
245 static GType type
= 0;
247 static const GTypeInfo info
= {
248 sizeof (LttvTracesetStatsClass
),
249 NULL
, /* base_init */
250 NULL
, /* base_finalize */
251 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
252 NULL
, /* class_finalize */
253 NULL
, /* class_data */
254 sizeof (LttvTracesetStats
),
256 (GInstanceInitFunc
) traceset_stats_instance_init
/* instance_init */
259 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
, "LttvTracesetStatsType",
267 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
273 trace_stats_finalize (LttvTraceStats
*self
)
275 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
276 finalize(G_OBJECT(self
));
281 trace_stats_class_init (LttvTraceContextClass
*klass
)
283 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
285 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
290 lttv_trace_stats_get_type(void)
292 static GType type
= 0;
294 static const GTypeInfo info
= {
295 sizeof (LttvTraceStatsClass
),
296 NULL
, /* base_init */
297 NULL
, /* base_finalize */
298 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
299 NULL
, /* class_finalize */
300 NULL
, /* class_data */
301 sizeof (LttvTraceStats
),
303 (GInstanceInitFunc
) trace_stats_instance_init
/* instance_init */
306 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
307 "LttvTraceStatsType", &info
, 0);
314 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
320 tracefile_stats_finalize (LttvTracefileStats
*self
)
322 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
323 finalize(G_OBJECT(self
));
328 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
330 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
332 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
337 lttv_tracefile_stats_get_type(void)
339 static GType type
= 0;
341 static const GTypeInfo info
= {
342 sizeof (LttvTracefileStatsClass
),
343 NULL
, /* base_init */
344 NULL
, /* base_finalize */
345 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
346 NULL
, /* class_finalize */
347 NULL
, /* class_data */
348 sizeof (LttvTracefileStats
),
350 (GInstanceInitFunc
) tracefile_stats_instance_init
/* instance_init */
353 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
354 "LttvTracefileStatsType", &info
, 0);
361 find_event_tree(LttvTracefileStats
*tfcs
, GQuark process
, GQuark cpu
,
362 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
363 LttvAttribute
**event_types_tree
)
367 LttvTraceStats
*tcs
= LTTV_TRACE_STATS(tfcs
->parent
.parent
.t_context
);
368 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
369 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->pid_time
);
370 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
371 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.cpu_name
);
372 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
373 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->t
);
374 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
375 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->n
);
377 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
378 *event_types_tree
= a
;
382 static void update_event_tree(LttvTracefileStats
*tfcs
)
384 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
386 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
, tfcs
->parent
.cpu_name
,
387 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
388 &(tfcs
->current_event_types_tree
));
392 static void mode_change(LttvTracefileStats
*tfcs
)
394 LttvAttributeValue cpu_time
;
398 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
399 LTTV_TIME
, &cpu_time
);
400 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
401 tfcs
->parent
.process
->state
->change
);
402 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
406 static void mode_end(LttvTracefileStats
*tfcs
)
408 LttvAttributeValue elapsed_time
, cpu_time
;
412 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
413 LTTV_TIME
, &elapsed_time
);
414 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
415 tfcs
->parent
.process
->state
->entry
);
416 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
418 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
419 LTTV_TIME
, &cpu_time
);
420 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
421 tfcs
->parent
.process
->state
->change
);
422 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
426 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
428 mode_change((LttvTracefileStats
*)call_data
);
433 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
435 update_event_tree((LttvTracefileStats
*)call_data
);
440 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
442 mode_end((LttvTracefileStats
*)call_data
);
447 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
449 update_event_tree((LttvTracefileStats
*)call_data
);
454 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
456 mode_change((LttvTracefileStats
*)call_data
);
461 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
463 update_event_tree((LttvTracefileStats
*)call_data
);
468 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
470 mode_end((LttvTracefileStats
*)call_data
);
475 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
477 update_event_tree((LttvTracefileStats
*)call_data
);
482 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
484 mode_change((LttvTracefileStats
*)call_data
);
489 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
491 update_event_tree((LttvTracefileStats
*)call_data
);
496 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
498 mode_end((LttvTracefileStats
*)call_data
);
503 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
505 update_event_tree((LttvTracefileStats
*)call_data
);
510 gboolean
before_schedchange(void *hook_data
, void *call_data
)
512 LttvTraceHook
*h
= (LttvTraceHook
*)hook_data
;
514 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
516 guint pid_in
, pid_out
, state_out
;
518 LttvProcessState
*process
;
520 pid_in
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f1
);
521 pid_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f2
);
522 state_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f3
);
524 /* compute the time for the process to schedule out */
528 /* get the information for the process scheduled in */
530 process
= lttv_state_find_process_or_create(&(tfcs
->parent
), pid_in
);
532 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
533 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
534 &(tfcs
->current_event_types_tree
));
536 /* compute the time waiting for the process to schedule in */
543 gboolean
process_fork(void *hook_data
, void *call_data
)
545 /* nothing to do for now */
550 gboolean
process_exit(void *hook_data
, void *call_data
)
552 /* We should probably exit all modes here or we could do that at
558 gboolean
every_event(void *hook_data
, void *call_data
)
560 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
562 LttvAttributeValue v
;
564 /* The current branch corresponds to the tracefile/process/interrupt state.
565 Statistics are added within it, to count the number of events of this
566 type occuring in this context. A quark has been pre-allocated for each
567 event type and is used as name. */
569 lttv_attribute_find(tfcs
->current_event_types_tree
,
570 ((LttvTraceState
*)(tfcs
->parent
.parent
.t_context
))->
571 eventtype_names
[ltt_event_eventtype_id(tfcs
->parent
.parent
.e
)],
579 lttv_stats_sum_trace(LttvTraceStats
*self
)
583 LttvAttributeType type
;
585 LttvAttributeValue value
;
587 LttvAttributeName name
;
591 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
594 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
595 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
596 *submode_tree
, *event_types_tree
, *mode_events_tree
,
597 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
600 main_tree
= self
->stats
;
602 lttv_attribute_find(self
->parent
.parent
.t_a
, LTTV_STATS_SUMMED
,
604 if(*(value
.v_uint
) != 0) return;
607 processes_tree
= lttv_attribute_find_subdir(main_tree
,
608 LTTV_STATS_PROCESSES
);
609 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
610 nb_process
= lttv_attribute_get_number(processes_tree
);
612 for(i
= 0 ; i
< nb_process
; i
++) {
613 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
614 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
616 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
617 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
619 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
621 for(j
= 0 ; j
< nb_cpu
; j
++) {
622 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
623 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
625 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
626 LTTV_STATS_MODE_TYPES
);
627 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
629 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
630 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
631 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
633 for(k
= 0 ; k
< nb_mode_type
; k
++) {
634 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
635 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
637 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
638 LTTV_STATS_SUBMODES
);
639 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
641 nb_submode
= lttv_attribute_get_number(submodes_tree
);
643 for(l
= 0 ; l
< nb_submode
; l
++) {
644 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
645 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
647 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
648 LTTV_STATS_EVENT_TYPES
);
649 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
652 for(m
= 0 ; m
< nb_event_type
; m
++) {
653 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
654 sum
+= *(value
.v_uint
);
656 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
658 *(value
.v_uint
) = sum
;
659 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
661 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
663 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
664 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
666 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
672 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
674 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
680 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
682 LttvAttributeValue value
;
684 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_SUMMED
,
686 if(*(value
.v_uint
) != 0) return;
689 traceset_modes_tree
= lttv_attribute_find_subdir(self
->stats
,
691 nb_trace
= lttv_traceset_number(traceset
);
693 for(i
= 0 ; i
< nb_trace
; i
++) {
694 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
695 lttv_stats_sum_trace(tcs
);
696 main_tree
= tcs
->stats
;
697 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
698 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
703 lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
705 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
707 guint i
, j
, k
, nb_trace
, nb_tracefile
;
715 LttvTracefileStats
*tfs
;
719 GArray
*hooks
, *before_hooks
, *after_hooks
;
723 LttvAttributeValue val
;
725 nb_trace
= lttv_traceset_number(traceset
);
726 for(i
= 0 ; i
< nb_trace
; i
++) {
727 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
729 /* Find the eventtype id for the following events and register the
730 associated by id hooks. */
732 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
733 g_array_set_size(hooks
, 7);
735 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
736 "syscall_id", NULL
, NULL
, before_syscall_entry
,
737 &g_array_index(hooks
, LttvTraceHook
, 0));
739 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
740 NULL
, NULL
, before_syscall_exit
,
741 &g_array_index(hooks
, LttvTraceHook
, 1));
743 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
744 NULL
, NULL
, before_trap_entry
,
745 &g_array_index(hooks
, LttvTraceHook
, 2));
747 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
748 NULL
, before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
750 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
751 NULL
, NULL
, before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
753 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
754 NULL
, before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
756 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "schedchange", "in",
757 "out", "out_state", before_schedchange
,
758 &g_array_index(hooks
, LttvTraceHook
, 6));
760 before_hooks
= hooks
;
762 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
763 g_array_set_size(hooks
, 8);
765 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
766 "syscall_id", NULL
, NULL
, after_syscall_entry
,
767 &g_array_index(hooks
, LttvTraceHook
, 0));
769 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
770 NULL
, NULL
, after_syscall_exit
,
771 &g_array_index(hooks
, LttvTraceHook
, 1));
773 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
774 NULL
, NULL
, after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
776 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
777 NULL
, after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
779 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
780 NULL
, NULL
, after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
782 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
783 NULL
, after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
785 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_fork",
786 "child_pid", NULL
, NULL
, process_fork
,
787 &g_array_index(hooks
, LttvTraceHook
, 6));
789 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_exit", NULL
,
790 NULL
, NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
794 /* Add these hooks to each event_by_id hooks list */
796 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
797 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
799 for(j
= 0 ; j
< nb_tracefile
; j
++) {
800 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
801 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
804 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
805 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
806 lttv_hooks_add(lttv_hooks_by_id_find(
807 tfs
->parent
.parent
.event_by_id
,
808 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
),
809 LTTV_PRIO_STATS_BEFORE_STATE
);
811 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
812 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
813 lttv_hooks_add(lttv_hooks_by_id_find(
814 tfs
->parent
.parent
.event_by_id
,
815 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
),
816 LTTV_PRIO_STATS_AFTER_STATE
);
819 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
821 *(val
.v_pointer
) = before_hooks
;
822 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
824 *(val
.v_pointer
) = after_hooks
;
829 lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
831 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
833 guint i
, j
, k
, nb_trace
, nb_tracefile
;
837 LttvTracefileStats
*tfs
;
841 GArray
*before_hooks
, *after_hooks
;
845 LttvAttributeValue val
;
847 nb_trace
= lttv_traceset_number(traceset
);
848 for(i
= 0 ; i
< nb_trace
; i
++) {
849 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
850 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
852 before_hooks
= *(val
.v_pointer
);
853 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
855 after_hooks
= *(val
.v_pointer
);
857 /* Remove these hooks from each event_by_id hooks list */
859 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
860 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
862 for(j
= 0 ; j
< nb_tracefile
; j
++) {
863 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
864 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
867 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
868 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
869 lttv_hooks_remove_data(
870 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
871 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
873 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
874 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
875 lttv_hooks_remove_data(
876 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
877 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
880 g_debug("lttv_stats_remove_event_hooks()");
881 g_array_free(before_hooks
, TRUE
);
882 g_array_free(after_hooks
, TRUE
);
887 static void module_init()
889 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
890 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
891 LTTV_STATS_CPU
= g_quark_from_string("cpu");
892 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
893 LTTV_STATS_MODES
= g_quark_from_string("modes");
894 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
895 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
896 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
897 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
898 LTTV_STATS_EVENTS
= g_quark_from_string("events");
899 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
900 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
901 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
902 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
903 LTTV_STATS
= g_quark_from_string("statistics");
904 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
905 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
908 static void module_destroy()
913 LTTV_MODULE("stats", "Compute processes statistics", \
914 "Accumulate statistics for event types, processes and CPUs", \
915 module_init
, module_destroy
, "state");
917 /* Change the places where stats are called (create/read/write stats)
919 Check for options in batchtest.c to reduce writing and see what tests are
920 best candidates for performance analysis. Once OK, commit, move to main
921 and run tests. Update the gui for statistics. */