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/stats.h>
22 #include <ltt/facility.h>
23 #include <ltt/trace.h>
24 #include <ltt/event.h>
29 LTTV_STATS_PROCESS_UNKNOWN
,
32 LTTV_STATS_MODE_TYPES
,
35 LTTV_STATS_EVENT_TYPES
,
37 LTTV_STATS_ELAPSED_TIME
,
39 LTTV_STATS_EVENTS_COUNT
;
42 LTTV_STATS_BEFORE_HOOKS
,
43 LTTV_STATS_AFTER_HOOKS
;
45 static void remove_all_processes(GHashTable
*processes
);
48 find_event_tree(LttvTracefileStats
*tfcs
, GQuark process
, GQuark cpu
,
49 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
50 LttvAttribute
**event_types_tree
);
53 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
55 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
61 LttvTracefileContext
*tfc
;
63 LttvTracefileStats
*tfcs
;
65 LttTime timestamp
= {0,0};
67 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
68 init((LttvTracesetContext
*)self
, ts
);
70 self
->stats
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
71 nb_trace
= lttv_traceset_number(ts
);
73 for(i
= 0 ; i
< nb_trace
; i
++) {
74 tcs
= (LttvTraceStats
*)tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
75 tcs
->stats
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
77 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
78 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
79 nb_tracefile
= nb_control
+ nb_per_cpu
;
80 for(j
= 0 ; j
< nb_tracefile
; j
++) {
82 tfcs
= LTTV_TRACEFILE_STATS(tc
->control_tracefiles
[j
]);
85 tfcs
= LTTV_TRACEFILE_STATS(tc
->per_cpu_tracefiles
[j
- nb_control
]);
88 tfcs
->stats
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
89 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
90 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
91 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
92 &tfcs
->current_event_types_tree
);
99 fini(LttvTracesetStats
*self
)
101 guint i
, j
, nb_trace
, nb_tracefile
;
105 LttvTraceContext
*tc
;
109 LttvTracefileContext
*tfc
;
111 LttvTracefileStats
*tfcs
;
113 LttTime timestamp
= {0,0};
115 lttv_attribute_recursive_free(self
->stats
);
116 ts
= self
->parent
.parent
.ts
;
117 nb_trace
= lttv_traceset_number(ts
);
119 for(i
= 0 ; i
< nb_trace
; i
++) {
120 tcs
= (LttvTraceStats
*)tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
121 lttv_attribute_recursive_free(tcs
->stats
);
123 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
);
124 for(j
= 0 ; j
< nb_tracefile
; j
++) {
125 tfcs
= (LttvTracefileStats
*)tfc
= tc
->control_tracefiles
[j
];
126 lttv_attribute_recursive_free(tfcs
->stats
);
127 tfcs
->current_events_tree
= NULL
;
128 tfcs
->current_event_types_tree
= NULL
;
131 nb_tracefile
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
132 for(j
= 0 ; j
< nb_tracefile
; j
++) {
133 tfcs
= (LttvTracefileStats
*)tfc
= tc
->per_cpu_tracefiles
[j
];
134 lttv_attribute_recursive_free(tfcs
->stats
);
135 tfcs
->current_events_tree
= NULL
;
136 tfcs
->current_event_types_tree
= NULL
;
139 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
140 fini((LttvTracesetContext
*)self
);
144 static LttvTracesetContext
*
145 new_traceset_context(LttvTracesetContext
*self
)
147 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
151 static LttvTraceContext
*
152 new_trace_context(LttvTracesetContext
*self
)
154 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
158 static LttvTracefileContext
*
159 new_tracefile_context(LttvTracesetContext
*self
)
161 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
166 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
172 traceset_stats_finalize (LttvTracesetStats
*self
)
174 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
175 finalize(G_OBJECT(self
));
180 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
182 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
184 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
185 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
186 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
187 klass
->new_traceset_context
= new_traceset_context
;
188 klass
->new_trace_context
= new_trace_context
;
189 klass
->new_tracefile_context
= new_tracefile_context
;
194 lttv_traceset_stats_get_type(void)
196 static GType type
= 0;
198 static const GTypeInfo info
= {
199 sizeof (LttvTracesetStatsClass
),
200 NULL
, /* base_init */
201 NULL
, /* base_finalize */
202 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
203 NULL
, /* class_finalize */
204 NULL
, /* class_data */
205 sizeof (LttvTracesetContext
),
207 (GInstanceInitFunc
) traceset_stats_instance_init
/* instance_init */
210 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
, "LttvTracesetStatsType",
218 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
224 trace_stats_finalize (LttvTraceStats
*self
)
226 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
227 finalize(G_OBJECT(self
));
232 trace_stats_class_init (LttvTraceContextClass
*klass
)
234 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
236 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
241 lttv_trace_stats_get_type(void)
243 static GType type
= 0;
245 static const GTypeInfo info
= {
246 sizeof (LttvTraceStatsClass
),
247 NULL
, /* base_init */
248 NULL
, /* base_finalize */
249 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
250 NULL
, /* class_finalize */
251 NULL
, /* class_data */
252 sizeof (LttvTraceStats
),
254 (GInstanceInitFunc
) trace_stats_instance_init
/* instance_init */
257 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
258 "LttvTraceStatsType", &info
, 0);
265 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
271 tracefile_stats_finalize (LttvTracefileStats
*self
)
273 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
274 finalize(G_OBJECT(self
));
279 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
281 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
283 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
288 lttv_tracefile_stats_get_type(void)
290 static GType type
= 0;
292 static const GTypeInfo info
= {
293 sizeof (LttvTracefileStatsClass
),
294 NULL
, /* base_init */
295 NULL
, /* base_finalize */
296 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
297 NULL
, /* class_finalize */
298 NULL
, /* class_data */
299 sizeof (LttvTracefileStats
),
301 (GInstanceInitFunc
) tracefile_stats_instance_init
/* instance_init */
304 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
305 "LttvTracefileStatsType", &info
, 0);
312 find_event_tree(LttvTracefileStats
*tfcs
, GQuark process
, GQuark cpu
,
313 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
314 LttvAttribute
**event_types_tree
)
318 LttvTraceStats
*tcs
= LTTV_TRACE_STATS(tfcs
->parent
.parent
.t_context
);
319 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
320 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->pid_time
);
321 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
322 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.cpu_name
);
323 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
324 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->t
);
325 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
326 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->n
);
328 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
329 *event_types_tree
= a
;
333 static void update_event_tree(LttvTracefileStats
*tfcs
)
335 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
337 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
, tfcs
->parent
.cpu_name
,
338 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
339 &(tfcs
->current_event_types_tree
));
343 static void mode_change(LttvTracefileStats
*tfcs
)
345 LttvAttributeValue cpu_time
;
349 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
350 LTTV_TIME
, &cpu_time
);
351 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
352 tfcs
->parent
.process
->state
->change
);
353 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
357 static void mode_end(LttvTracefileStats
*tfcs
)
359 LttvAttributeValue elapsed_time
, cpu_time
;
363 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
364 LTTV_TIME
, &elapsed_time
);
365 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
366 tfcs
->parent
.process
->state
->entry
);
367 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
369 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
370 LTTV_TIME
, &cpu_time
);
371 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
372 tfcs
->parent
.process
->state
->change
);
373 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
377 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
379 mode_change((LttvTracefileStats
*)call_data
);
384 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
386 update_event_tree((LttvTracefileStats
*)call_data
);
391 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
393 mode_end((LttvTracefileStats
*)call_data
);
398 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
400 update_event_tree((LttvTracefileStats
*)call_data
);
405 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
407 mode_change((LttvTracefileStats
*)call_data
);
412 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
414 update_event_tree((LttvTracefileStats
*)call_data
);
419 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
421 mode_end((LttvTracefileStats
*)call_data
);
426 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
428 update_event_tree((LttvTracefileStats
*)call_data
);
433 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
435 mode_change((LttvTracefileStats
*)call_data
);
440 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
442 update_event_tree((LttvTracefileStats
*)call_data
);
447 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
449 mode_end((LttvTracefileStats
*)call_data
);
454 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
456 update_event_tree((LttvTracefileStats
*)call_data
);
461 gboolean
before_schedchange(void *hook_data
, void *call_data
)
463 LttvTraceHook
*h
= (LttvTraceHook
*)hook_data
;
465 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
467 guint pid_in
, pid_out
, state_out
;
469 LttvProcessState
*process
;
471 pid_in
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f1
);
472 pid_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f2
);
473 state_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f3
);
475 /* compute the time for the process to schedule out */
479 /* get the information for the process scheduled in */
481 process
= lttv_state_find_process(&(tfcs
->parent
), pid_in
);
483 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
484 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
485 &(tfcs
->current_event_types_tree
));
487 /* compute the time waiting for the process to schedule in */
494 gboolean
process_fork(void *hook_data
, void *call_data
)
496 /* nothing to do for now */
501 gboolean
process_exit(void *hook_data
, void *call_data
)
503 /* We should probably exit all modes here or we could do that at
509 gboolean
every_event(void *hook_data
, void *call_data
)
511 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
513 LttvAttributeValue v
;
515 /* The current branch corresponds to the tracefile/process/interrupt state.
516 Statistics are added within it, to count the number of events of this
517 type occuring in this context. A quark has been pre-allocated for each
518 event type and is used as name. */
520 lttv_attribute_find(tfcs
->current_event_types_tree
,
521 ((LttvTraceState
*)(tfcs
->parent
.parent
.t_context
))->
522 eventtype_names
[ltt_event_eventtype_id(tfcs
->parent
.parent
.e
)],
530 sum_stats(void *hook_data
, void *call_data
)
532 LttvTracesetStats
*tscs
= (LttvTracesetStats
*)call_data
;
536 LttvTraceset
*traceset
= tscs
->parent
.parent
.ts
;
538 LttvAttributeType type
;
540 LttvAttributeValue value
;
542 LttvAttributeName name
;
546 int i
, j
, k
, l
, m
, n
, nb_trace
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
549 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
550 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
551 *submode_tree
, *event_types_tree
, *mode_events_tree
,
552 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
553 *trace_modes_tree
, *traceset_modes_tree
;
555 traceset_modes_tree
= lttv_attribute_find_subdir(tscs
->stats
,
557 nb_trace
= lttv_traceset_number(traceset
);
559 for(i
= 0 ; i
< nb_trace
; i
++) {
560 tcs
= (LttvTraceStats
*)(tscs
->parent
.parent
.traces
[i
]);
561 main_tree
= tcs
->stats
;
562 processes_tree
= lttv_attribute_find_subdir(main_tree
,
563 LTTV_STATS_PROCESSES
);
564 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
565 nb_process
= lttv_attribute_get_number(processes_tree
);
567 for(j
= 0 ; j
< nb_process
; j
++) {
568 type
= lttv_attribute_get(processes_tree
, j
, &name
, &value
);
569 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
571 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
572 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
574 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
576 for(k
= 0 ; k
< nb_cpu
; k
++) {
577 type
= lttv_attribute_get(cpus_tree
, k
, &name
, &value
);
578 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
580 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
581 LTTV_STATS_MODE_TYPES
);
582 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
584 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
585 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
586 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
588 for(l
= 0 ; l
< nb_mode_type
; l
++) {
589 type
= lttv_attribute_get(mode_types_tree
, l
, &name
, &value
);
590 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
592 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
593 LTTV_STATS_SUBMODES
);
594 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
596 nb_submode
= lttv_attribute_get_number(submodes_tree
);
598 for(m
= 0 ; m
< nb_submode
; m
++) {
599 type
= lttv_attribute_get(submodes_tree
, m
, &name
, &value
);
600 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
602 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
603 LTTV_STATS_EVENT_TYPES
);
604 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
607 for(n
= 0 ; n
< nb_event_type
; n
++) {
608 type
= lttv_attribute_get(event_types_tree
, n
, &name
, &value
);
609 sum
+= *(value
.v_uint
);
611 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
613 *(value
.v_uint
) = sum
;
614 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
616 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
618 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
619 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
621 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
623 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
629 lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
631 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
633 guint i
, j
, k
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
641 LttvTracefileStats
*tfs
;
645 GArray
*hooks
, *before_hooks
, *after_hooks
;
649 LttvAttributeValue val
;
651 nb_trace
= lttv_traceset_number(traceset
);
652 for(i
= 0 ; i
< nb_trace
; i
++) {
653 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
655 /* Find the eventtype id for the following events and register the
656 associated by id hooks. */
658 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
659 g_array_set_size(hooks
, 7);
661 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
662 "syscall_id", NULL
, NULL
, before_syscall_entry
,
663 &g_array_index(hooks
, LttvTraceHook
, 0));
665 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
666 NULL
, NULL
, before_syscall_exit
,
667 &g_array_index(hooks
, LttvTraceHook
, 1));
669 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
670 NULL
, NULL
, before_trap_entry
,
671 &g_array_index(hooks
, LttvTraceHook
, 2));
673 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
674 NULL
, before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
676 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
677 NULL
, NULL
, before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
679 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
680 NULL
, before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
682 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "schedchange", "in",
683 "out", "out_state", before_schedchange
,
684 &g_array_index(hooks
, LttvTraceHook
, 6));
686 before_hooks
= hooks
;
688 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
689 g_array_set_size(hooks
, 8);
691 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
692 "syscall_id", NULL
, NULL
, after_syscall_entry
,
693 &g_array_index(hooks
, LttvTraceHook
, 0));
695 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
696 NULL
, NULL
, after_syscall_exit
,
697 &g_array_index(hooks
, LttvTraceHook
, 1));
699 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
700 NULL
, NULL
, after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
702 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
703 NULL
, after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
705 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
706 NULL
, NULL
, after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
708 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
709 NULL
, after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
711 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_fork",
712 "child_pid", NULL
, NULL
, process_fork
,
713 &g_array_index(hooks
, LttvTraceHook
, 6));
715 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_exit", NULL
,
716 NULL
, NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
720 /* Add these hooks to each before_event_by_id hooks list */
722 nb_control
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
);
723 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
724 nb_tracefile
= nb_control
+ nb_per_cpu
;
725 for(j
= 0 ; j
< nb_tracefile
; j
++) {
727 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.control_tracefiles
[j
]);
730 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.per_cpu_tracefiles
[
734 lttv_hooks_add(tfs
->parent
.parent
.after_event
, every_event
, NULL
);
736 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
737 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
738 lttv_hooks_add(lttv_hooks_by_id_find(
739 tfs
->parent
.parent
.before_event_by_id
,
740 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
742 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
743 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
744 lttv_hooks_add(lttv_hooks_by_id_find(
745 tfs
->parent
.parent
.after_event_by_id
,
746 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
749 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
751 *(val
.v_pointer
) = before_hooks
;
752 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
754 *(val
.v_pointer
) = after_hooks
;
756 lttv_hooks_add(self
->parent
.parent
.after
, sum_stats
, NULL
);
760 lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
762 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
764 guint i
, j
, k
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
768 LttvTracefileStats
*tfs
;
772 GArray
*before_hooks
, *after_hooks
;
776 LttvAttributeValue val
;
778 nb_trace
= lttv_traceset_number(traceset
);
779 for(i
= 0 ; i
< nb_trace
; i
++) {
780 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
781 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
783 before_hooks
= *(val
.v_pointer
);
784 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
786 after_hooks
= *(val
.v_pointer
);
788 /* Add these hooks to each before_event_by_id hooks list */
790 nb_control
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
);
791 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
792 nb_tracefile
= nb_control
+ nb_per_cpu
;
793 for(j
= 0 ; j
< nb_tracefile
; j
++) {
795 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.control_tracefiles
[j
]);
798 tfs
=LTTV_TRACEFILE_STATS(ts
->parent
.parent
.per_cpu_tracefiles
[
802 lttv_hooks_remove_data(tfs
->parent
.parent
.after_event
, every_event
,
805 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
806 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
807 lttv_hooks_remove_data(
808 lttv_hooks_by_id_find(tfs
->parent
.parent
.before_event_by_id
,
809 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
811 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
812 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
813 lttv_hooks_remove_data(
814 lttv_hooks_by_id_find(tfs
->parent
.parent
.after_event_by_id
,
815 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
818 g_critical("lttv_stats_remove_event_hooks()");
819 g_array_free(before_hooks
, TRUE
);
820 g_array_free(after_hooks
, TRUE
);
822 lttv_hooks_remove_data(self
->parent
.parent
.after
, sum_stats
, NULL
);
826 void lttv_stats_init(int argc
, char **argv
)
828 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
829 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
830 LTTV_STATS_CPU
= g_quark_from_string("cpu");
831 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
832 LTTV_STATS_MODES
= g_quark_from_string("modes");
833 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
834 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
835 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
836 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
837 LTTV_STATS_EVENTS
= g_quark_from_string("events");
838 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
839 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
840 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
843 void lttv_stats_destroy()
847 void lttv_stats_save_attribute(LttvAttribute
*attr
, char *indent
, FILE * fp
)
849 LttvAttributeType type
;
850 LttvAttributeValue value
;
851 LttvAttributeName name
;
852 char type_value
[BUF_SIZE
];
853 int i
, nb_attr
, flag
;
855 nb_attr
= lttv_attribute_get_number(attr
);
856 for(i
=0;i
<nb_attr
;i
++){
858 type
= lttv_attribute_get(attr
, i
, &name
, &value
);
861 sprintf(type_value
, "%d\0", *value
.v_int
);
864 sprintf(type_value
, "%u\0", *value
.v_uint
);
867 sprintf(type_value
, "%ld\0", *value
.v_long
);
870 sprintf(type_value
, "%lu\0", *value
.v_ulong
);
873 sprintf(type_value
, "%f\0", (double)*value
.v_float
);
876 sprintf(type_value
, "%f\0", *value
.v_double
);
879 sprintf(type_value
, "%10u.%09u\0", value
.v_time
->tv_sec
,
880 value
.v_time
->tv_nsec
);
883 sprintf(type_value
, "POINTER\0");
886 sprintf(type_value
, "%s\0", *value
.v_string
);
892 if(flag
== 0) continue;
893 fprintf(fp
,"%s<VALUE type=\"%d\" name=\"%s\">",indent
,type
,g_quark_to_string(name
));
894 fprintf(fp
,"%s",type_value
);
895 fprintf(fp
,"</VALUE> \n");
900 void lttv_stats_save_statistics(LttvTracesetStats
*self
)
902 LttvTracesetStats
*tscs
= self
;
904 LttvTraceset
*traceset
= tscs
->parent
.parent
.ts
;
905 LttvAttributeType type
;
906 LttvAttributeValue value
;
907 LttvAttributeName name
;
909 char filename
[BUF_SIZE
];
911 char indent
[10][24]= {" ",
924 int i
, j
, k
, l
, m
, n
, nb_trace
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
;
926 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
927 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
928 *submode_tree
, *event_types_tree
;
930 nb_trace
= lttv_traceset_number(traceset
);
932 for(i
= 0 ; i
< nb_trace
; i
++) {
933 tcs
= (LttvTraceStats
*)(tscs
->parent
.parent
.traces
[i
]);
936 strcat(filename
,ltt_trace_name(tcs
->parent
.parent
.t
));
937 strcat(filename
,"/statistics.xml");
938 fp
= fopen(filename
,"w");
940 g_warning("can not open the file %s for saving statistics\n", filename
);
944 main_tree
= tcs
->stats
;
945 processes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_PROCESSES
);
946 nb_process
= lttv_attribute_get_number(processes_tree
);
948 fprintf(fp
, "<NODE name=\"%s\"> \n",g_quark_to_string(LTTV_STATS_PROCESSES
)); //root NODE
950 for(j
= 0 ; j
< nb_process
; j
++) {
951 type
= lttv_attribute_get(processes_tree
, j
, &name
, &value
);
952 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
954 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[0],g_quark_to_string(name
)); //process NODE
955 lttv_stats_save_attribute(process_tree
,indent
[1], fp
);
956 fprintf(fp
,"%s<NODE name=\"%s\"> \n", indent
[1],g_quark_to_string(LTTV_STATS_CPU
)); //cpus NODE
958 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
959 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
961 for(k
= 0 ; k
< nb_cpu
; k
++) {
962 type
= lttv_attribute_get(cpus_tree
, k
, &name
, &value
);
963 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
965 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[2],g_quark_to_string(name
)); //cpu NODE
966 lttv_stats_save_attribute(cpu_tree
,indent
[3], fp
);
967 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[3],g_quark_to_string(LTTV_STATS_MODE_TYPES
)); //mode_types NODE
969 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,LTTV_STATS_MODE_TYPES
);
970 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
972 for(l
= 0 ; l
< nb_mode_type
; l
++) {
973 type
= lttv_attribute_get(mode_types_tree
, l
, &name
, &value
);
974 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
976 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[4],g_quark_to_string(name
)); //mode NODE
977 lttv_stats_save_attribute(mode_tree
,indent
[5], fp
);
978 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[5],g_quark_to_string(LTTV_STATS_SUBMODES
)); //sub_modes NODE
980 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,LTTV_STATS_SUBMODES
);
981 nb_submode
= lttv_attribute_get_number(submodes_tree
);
983 for(m
= 0 ; m
< nb_submode
; m
++) {
984 type
= lttv_attribute_get(submodes_tree
, m
, &name
, &value
);
985 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
986 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[6],g_quark_to_string(name
)); //sub_mode NODE
987 lttv_stats_save_attribute(submode_tree
,indent
[7], fp
);
988 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[7],g_quark_to_string(LTTV_STATS_EVENT_TYPES
)); //event_types NODE
990 event_types_tree
= lttv_attribute_find_subdir(submode_tree
, LTTV_STATS_EVENT_TYPES
);
991 lttv_stats_save_attribute(event_types_tree
,indent
[8], fp
);
993 fprintf(fp
,"%s</NODE> \n",indent
[7]); //event_types NODE
994 fprintf(fp
,"%s</NODE> \n",indent
[6]); //sub_mode NODE
996 fprintf(fp
,"%s</NODE> \n",indent
[5]); //sub_modes NODE
997 fprintf(fp
,"%s</NODE> \n",indent
[4]); //mode NODE
999 fprintf(fp
,"%s</NODE> \n",indent
[3]); //mode_type NODE
1000 fprintf(fp
,"%s</NODE> \n",indent
[2]); //cpu NODE
1002 fprintf(fp
,"%s</NODE> \n",indent
[1]); //cpus NODE
1003 fprintf(fp
,"%s</NODE> \n", indent
[0]); //process NODE
1005 fprintf(fp
, "</NODE>\n"); //root NODE
1011 /* Functions to parse statistic.xml file (using glib xml parser) */
1013 typedef struct _ParserStruct
{
1014 GPtrArray
* attribute
;
1015 LttvAttributeType type
;
1016 LttvAttributeName name
;
1019 static void stats_parser_start_element (GMarkupParseContext
*context
,
1020 const gchar
*element_name
,
1021 const gchar
**attribute_names
,
1022 const gchar
**attribute_values
,
1026 ParserStruct
* parser
= (ParserStruct
*)user_data
;
1028 LttvAttributeType type
;
1029 LttvAttributeName name
;
1030 LttvAttribute
* parent_att
, *new_att
;
1032 len
= parser
->attribute
->len
;
1033 parent_att
= (LttvAttribute
*)g_ptr_array_index (parser
->attribute
, len
-1);
1035 if(strcmp("NODE", element_name
) == 0){
1036 type
= LTTV_GOBJECT
;
1037 name
= g_quark_from_string(attribute_values
[0]);
1038 new_att
= lttv_attribute_find_subdir(parent_att
,name
);
1039 g_ptr_array_add(parser
->attribute
, (gpointer
)new_att
);
1040 }else if(strcmp("VALUE", element_name
) == 0){
1041 parser
->type
= (LttvAttributeType
) atoi(attribute_values
[0]);
1042 parser
->name
= g_quark_from_string(attribute_values
[1]);
1044 g_warning("This is not statistics.xml file\n");
1049 static void stats_parser_end_element (GMarkupParseContext
*context
,
1050 const gchar
*element_name
,
1054 ParserStruct
* parser
= (ParserStruct
*)user_data
;
1056 LttvAttribute
* parent_att
;
1058 len
= parser
->attribute
->len
;
1059 parent_att
= (LttvAttribute
*)g_ptr_array_index (parser
->attribute
, len
-1);
1061 if(strcmp("NODE", element_name
) == 0){
1062 g_ptr_array_remove_index(parser
->attribute
, len
-1);
1063 }else if(strcmp("VALUE", element_name
) == 0){
1065 g_warning("This is not statistics.xml file\n");
1071 static void stats_parser_characters (GMarkupParseContext
*context
,
1077 ParserStruct
* parser
= (ParserStruct
*)user_data
;
1078 LttvAttributeValue value
;
1080 LttvAttribute
* parent_att
;
1084 for(len
=0;len
<text_len
;len
++){
1091 if(strlen(pos
) == 0)return;
1093 len
= parser
->attribute
->len
;
1094 parent_att
= (LttvAttribute
*)g_ptr_array_index (parser
->attribute
, len
-1);
1095 if(!lttv_attribute_find(parent_att
,parser
->name
, parser
->type
, &value
)){
1096 g_warning("can not find value\n");
1100 switch(parser
->type
) {
1102 *value
.v_int
= atoi(text
);
1105 *value
.v_uint
= (unsigned)atoi(text
);
1108 *value
.v_long
= atol(text
);
1111 *value
.v_ulong
= (unsigned long)atol(text
);
1114 *value
.v_float
= atof(text
);
1117 *value
.v_float
= atof(text
);
1120 pos
= strrchr(text
,'.');
1124 value
.v_time
->tv_sec
= atol(text
);
1125 value
.v_time
->tv_nsec
= atol(pos
);
1127 g_warning("The time value format is wrong\n");
1134 *value
.v_string
= g_strdup(text
);
1142 gboolean
lttv_stats_load_statistics(LttvTracesetStats
*self
)
1146 LttvTracesetStats
*tscs
= self
;
1147 LttvTraceStats
*tcs
;
1148 LttvTraceset
*traceset
= tscs
->parent
.parent
.ts
;
1149 char filename
[BUF_SIZE
];
1151 GMarkupParseContext
* context
;
1153 GMarkupParser markup_parser
=
1155 stats_parser_start_element
,
1156 stats_parser_end_element
,
1157 stats_parser_characters
,
1158 NULL
, /* passthrough */
1163 LttvAttribute
*main_tree
;
1164 ParserStruct a_parser_struct
;
1165 a_parser_struct
.attribute
= g_ptr_array_new();
1167 nb_trace
= lttv_traceset_number(traceset
);
1169 for(i
= 0 ; i
< nb_trace
; i
++) {
1170 tcs
= (LttvTraceStats
*)(tscs
->parent
.parent
.traces
[i
]);
1173 strcat(filename
,ltt_trace_name(tcs
->parent
.parent
.t
));
1174 strcat(filename
,"/statistics.xml");
1175 fp
= fopen(filename
,"r");
1177 g_warning("can not open the file %s for reading statistics\n", filename
);
1181 main_tree
= tcs
->stats
;
1182 g_ptr_array_add(a_parser_struct
.attribute
,(gpointer
)main_tree
);
1184 context
= g_markup_parse_context_new(&markup_parser
, 0, (gpointer
)&a_parser_struct
, NULL
);
1186 while(fgets(buf
,BUF_SIZE
, fp
) != NULL
){
1187 if(!g_markup_parse_context_parse(context
, buf
, BUF_SIZE
, &error
)){
1188 g_warning("Can not parse xml file: \n%s\n", error
->message
);
1195 sum_stats(NULL
, (void *)self
);