3 #include <lttv/stats.h>
4 #include <ltt/facility.h>
11 LTTV_STATS_PROCESS_UNKNOWN
,
14 LTTV_STATS_MODE_TYPES
,
17 LTTV_STATS_EVENT_TYPES
,
19 LTTV_STATS_ELAPSED_TIME
,
21 LTTV_STATS_EVENTS_COUNT
;
24 LTTV_STATS_BEFORE_HOOKS
,
25 LTTV_STATS_AFTER_HOOKS
;
27 static void remove_all_processes(GHashTable
*processes
);
30 find_event_tree(LttvTracefileStats
*tfcs
, GQuark process
, GQuark cpu
,
31 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
32 LttvAttribute
**event_types_tree
);
35 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
37 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
43 LttvTracefileContext
*tfc
;
45 LttvTracefileStats
*tfcs
;
47 LttTime timestamp
= {0,0};
49 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
50 init((LttvTracesetContext
*)self
, ts
);
52 self
->stats
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
53 nb_trace
= lttv_traceset_number(ts
);
55 for(i
= 0 ; i
< nb_trace
; i
++) {
56 tcs
= (LttvTraceStats
*)tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
57 tcs
->stats
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
59 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
60 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
61 nb_tracefile
= nb_control
+ nb_per_cpu
;
62 for(j
= 0 ; j
< nb_tracefile
; j
++) {
64 tfcs
= LTTV_TRACEFILE_STATS(tc
->control_tracefiles
[j
]);
67 tfcs
= LTTV_TRACEFILE_STATS(tc
->per_cpu_tracefiles
[j
- nb_control
]);
70 tfcs
->stats
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
71 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
72 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
73 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
74 &tfcs
->current_event_types_tree
);
81 fini(LttvTracesetStats
*self
)
83 guint i
, j
, nb_trace
, nb_tracefile
;
91 LttvTracefileContext
*tfc
;
93 LttvTracefileStats
*tfcs
;
95 LttTime timestamp
= {0,0};
97 lttv_attribute_recursive_free(self
->stats
);
98 ts
= self
->parent
.parent
.ts
;
99 nb_trace
= lttv_traceset_number(ts
);
101 for(i
= 0 ; i
< nb_trace
; i
++) {
102 tcs
= (LttvTraceStats
*)tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
103 lttv_attribute_recursive_free(tcs
->stats
);
105 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
);
106 for(j
= 0 ; j
< nb_tracefile
; j
++) {
107 tfcs
= (LttvTracefileStats
*)tfc
= tc
->control_tracefiles
[j
];
108 lttv_attribute_recursive_free(tfcs
->stats
);
109 tfcs
->current_events_tree
= NULL
;
110 tfcs
->current_event_types_tree
= NULL
;
113 nb_tracefile
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
114 for(j
= 0 ; j
< nb_tracefile
; j
++) {
115 tfcs
= (LttvTracefileStats
*)tfc
= tc
->per_cpu_tracefiles
[j
];
116 lttv_attribute_recursive_free(tfcs
->stats
);
117 tfcs
->current_events_tree
= NULL
;
118 tfcs
->current_event_types_tree
= NULL
;
121 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
122 fini((LttvTracesetContext
*)self
);
126 static LttvTracesetContext
*
127 new_traceset_context(LttvTracesetContext
*self
)
129 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
133 static LttvTraceContext
*
134 new_trace_context(LttvTracesetContext
*self
)
136 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
140 static LttvTracefileContext
*
141 new_tracefile_context(LttvTracesetContext
*self
)
143 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
148 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
154 traceset_stats_finalize (LttvTracesetStats
*self
)
156 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
157 finalize(G_OBJECT(self
));
162 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
164 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
166 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
167 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
168 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
169 klass
->new_traceset_context
= new_traceset_context
;
170 klass
->new_trace_context
= new_trace_context
;
171 klass
->new_tracefile_context
= new_tracefile_context
;
176 lttv_traceset_stats_get_type(void)
178 static GType type
= 0;
180 static const GTypeInfo info
= {
181 sizeof (LttvTracesetStatsClass
),
182 NULL
, /* base_init */
183 NULL
, /* base_finalize */
184 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
185 NULL
, /* class_finalize */
186 NULL
, /* class_data */
187 sizeof (LttvTracesetContext
),
189 (GInstanceInitFunc
) traceset_stats_instance_init
/* instance_init */
192 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
, "LttvTracesetStatsType",
200 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
206 trace_stats_finalize (LttvTraceStats
*self
)
208 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
209 finalize(G_OBJECT(self
));
214 trace_stats_class_init (LttvTraceContextClass
*klass
)
216 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
218 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
223 lttv_trace_stats_get_type(void)
225 static GType type
= 0;
227 static const GTypeInfo info
= {
228 sizeof (LttvTraceStatsClass
),
229 NULL
, /* base_init */
230 NULL
, /* base_finalize */
231 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
232 NULL
, /* class_finalize */
233 NULL
, /* class_data */
234 sizeof (LttvTraceStats
),
236 (GInstanceInitFunc
) trace_stats_instance_init
/* instance_init */
239 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
240 "LttvTraceStatsType", &info
, 0);
247 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
253 tracefile_stats_finalize (LttvTracefileStats
*self
)
255 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
256 finalize(G_OBJECT(self
));
261 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
263 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
265 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
270 lttv_tracefile_stats_get_type(void)
272 static GType type
= 0;
274 static const GTypeInfo info
= {
275 sizeof (LttvTracefileStatsClass
),
276 NULL
, /* base_init */
277 NULL
, /* base_finalize */
278 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
279 NULL
, /* class_finalize */
280 NULL
, /* class_data */
281 sizeof (LttvTracefileStats
),
283 (GInstanceInitFunc
) tracefile_stats_instance_init
/* instance_init */
286 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
287 "LttvTracefileStatsType", &info
, 0);
294 find_event_tree(LttvTracefileStats
*tfcs
, GQuark process
, GQuark cpu
,
295 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
296 LttvAttribute
**event_types_tree
)
300 LttvTraceStats
*tcs
= LTTV_TRACE_STATS(tfcs
->parent
.parent
.t_context
);
301 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
302 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->pid_time
);
303 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
304 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.cpu_name
);
305 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
306 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->t
);
307 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
308 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->n
);
310 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
311 *event_types_tree
= a
;
315 static void update_event_tree(LttvTracefileStats
*tfcs
)
317 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
319 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
, tfcs
->parent
.cpu_name
,
320 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
321 &(tfcs
->current_event_types_tree
));
325 static void mode_change(LttvTracefileStats
*tfcs
)
327 LttvAttributeValue cpu_time
;
331 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
332 LTTV_TIME
, &cpu_time
);
333 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
334 tfcs
->parent
.process
->state
->change
);
335 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
339 static void mode_end(LttvTracefileStats
*tfcs
)
341 LttvAttributeValue elapsed_time
, cpu_time
;
345 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
346 LTTV_TIME
, &elapsed_time
);
347 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
348 tfcs
->parent
.process
->state
->entry
);
349 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
351 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
352 LTTV_TIME
, &cpu_time
);
353 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
354 tfcs
->parent
.process
->state
->change
);
355 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
359 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
361 mode_change((LttvTracefileStats
*)call_data
);
366 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
368 update_event_tree((LttvTracefileStats
*)call_data
);
373 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
375 mode_end((LttvTracefileStats
*)call_data
);
380 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
382 update_event_tree((LttvTracefileStats
*)call_data
);
387 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
389 mode_change((LttvTracefileStats
*)call_data
);
394 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
396 update_event_tree((LttvTracefileStats
*)call_data
);
401 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
403 mode_end((LttvTracefileStats
*)call_data
);
408 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
410 update_event_tree((LttvTracefileStats
*)call_data
);
415 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
417 mode_change((LttvTracefileStats
*)call_data
);
422 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
424 update_event_tree((LttvTracefileStats
*)call_data
);
429 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
431 mode_end((LttvTracefileStats
*)call_data
);
436 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
438 update_event_tree((LttvTracefileStats
*)call_data
);
443 gboolean
before_schedchange(void *hook_data
, void *call_data
)
445 LttvTraceHook
*h
= (LttvTraceHook
*)hook_data
;
447 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
449 guint pid_in
, pid_out
, state_out
;
451 LttvProcessState
*process
;
453 pid_in
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f1
);
454 pid_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f2
);
455 state_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f3
);
457 /* compute the time for the process to schedule out */
461 /* get the information for the process scheduled in */
463 process
= lttv_state_find_process(&(tfcs
->parent
), pid_in
);
465 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
466 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
467 &(tfcs
->current_event_types_tree
));
469 /* compute the time waiting for the process to schedule in */
476 gboolean
process_fork(void *hook_data
, void *call_data
)
478 /* nothing to do for now */
483 gboolean
process_exit(void *hook_data
, void *call_data
)
485 /* We should probably exit all modes here or we could do that at
491 gboolean
every_event(void *hook_data
, void *call_data
)
493 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
495 LttvAttributeValue v
;
497 /* The current branch corresponds to the tracefile/process/interrupt state.
498 Statistics are added within it, to count the number of events of this
499 type occuring in this context. A quark has been pre-allocated for each
500 event type and is used as name. */
502 lttv_attribute_find(tfcs
->current_event_types_tree
,
503 ((LttvTraceState
*)(tfcs
->parent
.parent
.t_context
))->
504 eventtype_names
[ltt_event_eventtype_id(tfcs
->parent
.parent
.e
)],
512 sum_stats(void *hook_data
, void *call_data
)
514 LttvTracesetStats
*tscs
= (LttvTracesetStats
*)call_data
;
518 LttvTraceset
*traceset
= tscs
->parent
.parent
.ts
;
520 LttvAttributeType type
;
522 LttvAttributeValue value
;
524 LttvAttributeName name
;
528 int i
, j
, k
, l
, m
, n
, nb_trace
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
531 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
532 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
533 *submode_tree
, *event_types_tree
, *mode_events_tree
,
534 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
535 *trace_modes_tree
, *traceset_modes_tree
;
537 traceset_modes_tree
= lttv_attribute_find_subdir(tscs
->stats
,
539 nb_trace
= lttv_traceset_number(traceset
);
541 for(i
= 0 ; i
< nb_trace
; i
++) {
542 tcs
= (LttvTraceStats
*)(tscs
->parent
.parent
.traces
[i
]);
543 main_tree
= tcs
->stats
;
544 processes_tree
= lttv_attribute_find_subdir(main_tree
,
545 LTTV_STATS_PROCESSES
);
546 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
547 nb_process
= lttv_attribute_get_number(processes_tree
);
549 for(j
= 0 ; j
< nb_process
; j
++) {
550 type
= lttv_attribute_get(processes_tree
, j
, &name
, &value
);
551 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
553 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
554 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
556 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
558 for(k
= 0 ; k
< nb_cpu
; k
++) {
559 type
= lttv_attribute_get(cpus_tree
, k
, &name
, &value
);
560 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
562 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
563 LTTV_STATS_MODE_TYPES
);
564 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
566 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
567 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
568 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
570 for(l
= 0 ; l
< nb_mode_type
; l
++) {
571 type
= lttv_attribute_get(mode_types_tree
, l
, &name
, &value
);
572 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
574 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
575 LTTV_STATS_SUBMODES
);
576 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
578 nb_submode
= lttv_attribute_get_number(submodes_tree
);
580 for(m
= 0 ; m
< nb_submode
; m
++) {
581 type
= lttv_attribute_get(submodes_tree
, m
, &name
, &value
);
582 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
584 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
585 LTTV_STATS_EVENT_TYPES
);
586 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
589 for(n
= 0 ; n
< nb_event_type
; n
++) {
590 type
= lttv_attribute_get(event_types_tree
, n
, &name
, &value
);
591 sum
+= *(value
.v_uint
);
593 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
595 *(value
.v_uint
) = sum
;
596 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
598 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
600 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
601 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
603 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
605 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
611 lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
613 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
615 guint i
, j
, k
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
623 LttvTracefileStats
*tfs
;
627 GArray
*hooks
, *before_hooks
, *after_hooks
;
631 LttvAttributeValue val
;
633 nb_trace
= lttv_traceset_number(traceset
);
634 for(i
= 0 ; i
< nb_trace
; i
++) {
635 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
637 /* Find the eventtype id for the following events and register the
638 associated by id hooks. */
640 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
641 g_array_set_size(hooks
, 7);
643 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
644 "syscall_id", NULL
, NULL
, before_syscall_entry
,
645 &g_array_index(hooks
, LttvTraceHook
, 0));
647 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
648 NULL
, NULL
, before_syscall_exit
,
649 &g_array_index(hooks
, LttvTraceHook
, 1));
651 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
652 NULL
, NULL
, before_trap_entry
,
653 &g_array_index(hooks
, LttvTraceHook
, 2));
655 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
656 NULL
, before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
658 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
659 NULL
, NULL
, before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
661 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
662 NULL
, before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
664 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "schedchange", "in",
665 "out", "out_state", before_schedchange
,
666 &g_array_index(hooks
, LttvTraceHook
, 6));
668 before_hooks
= hooks
;
670 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
671 g_array_set_size(hooks
, 8);
673 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
674 "syscall_id", NULL
, NULL
, after_syscall_entry
,
675 &g_array_index(hooks
, LttvTraceHook
, 0));
677 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
678 NULL
, NULL
, after_syscall_exit
,
679 &g_array_index(hooks
, LttvTraceHook
, 1));
681 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
682 NULL
, NULL
, after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
684 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
685 NULL
, after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
687 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
688 NULL
, NULL
, after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
690 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
691 NULL
, after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
693 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_fork",
694 "child_pid", NULL
, NULL
, process_fork
,
695 &g_array_index(hooks
, LttvTraceHook
, 6));
697 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_exit", NULL
,
698 NULL
, NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
702 /* Add these hooks to each before_event_by_id hooks list */
704 nb_control
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
);
705 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
706 nb_tracefile
= nb_control
+ nb_per_cpu
;
707 for(j
= 0 ; j
< nb_tracefile
; j
++) {
709 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.control_tracefiles
[j
]);
712 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.per_cpu_tracefiles
[
716 lttv_hooks_add(tfs
->parent
.parent
.after_event
, every_event
, NULL
);
718 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
719 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
720 lttv_hooks_add(lttv_hooks_by_id_find(
721 tfs
->parent
.parent
.before_event_by_id
,
722 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
724 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
725 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
726 lttv_hooks_add(lttv_hooks_by_id_find(
727 tfs
->parent
.parent
.after_event_by_id
,
728 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
731 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
733 *(val
.v_pointer
) = before_hooks
;
734 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
736 *(val
.v_pointer
) = after_hooks
;
738 lttv_hooks_add(self
->parent
.parent
.after
, sum_stats
, NULL
);
742 lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
744 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
746 guint i
, j
, k
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
750 LttvTracefileStats
*tfs
;
754 GArray
*before_hooks
, *after_hooks
;
758 LttvAttributeValue val
;
760 nb_trace
= lttv_traceset_number(traceset
);
761 for(i
= 0 ; i
< nb_trace
; i
++) {
762 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
763 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
765 before_hooks
= *(val
.v_pointer
);
766 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
768 after_hooks
= *(val
.v_pointer
);
770 /* Add these hooks to each before_event_by_id hooks list */
772 nb_control
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
);
773 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
774 nb_tracefile
= nb_control
+ nb_per_cpu
;
775 for(j
= 0 ; j
< nb_tracefile
; j
++) {
777 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.control_tracefiles
[j
]);
780 tfs
=LTTV_TRACEFILE_STATS(ts
->parent
.parent
.per_cpu_tracefiles
[
784 lttv_hooks_remove_data(tfs
->parent
.parent
.after_event
, every_event
,
787 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
788 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
789 lttv_hooks_remove_data(
790 lttv_hooks_by_id_find(tfs
->parent
.parent
.before_event_by_id
,
791 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
793 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
794 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
795 lttv_hooks_remove_data(
796 lttv_hooks_by_id_find(tfs
->parent
.parent
.after_event_by_id
,
797 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
800 g_critical("lttv_stats_remove_event_hooks()");
801 g_array_free(before_hooks
, TRUE
);
802 g_array_free(after_hooks
, TRUE
);
804 lttv_hooks_remove_data(self
->parent
.parent
.after
, sum_stats
, NULL
);
808 void lttv_stats_init(int argc
, char **argv
)
810 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
811 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
812 LTTV_STATS_CPU
= g_quark_from_string("cpu");
813 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
814 LTTV_STATS_MODES
= g_quark_from_string("modes");
815 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
816 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
817 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
818 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
819 LTTV_STATS_EVENTS
= g_quark_from_string("events");
820 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
821 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
822 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
825 void lttv_stats_destroy()
829 void lttv_stats_save_attribute(LttvAttribute
*attr
, char *indent
, FILE * fp
)
831 LttvAttributeType type
;
832 LttvAttributeValue value
;
833 LttvAttributeName name
;
834 char type_value
[BUF_SIZE
];
835 int i
, nb_attr
, flag
;
837 nb_attr
= lttv_attribute_get_number(attr
);
838 for(i
=0;i
<nb_attr
;i
++){
840 type
= lttv_attribute_get(attr
, i
, &name
, &value
);
843 sprintf(type_value
, "%d\0", *value
.v_int
);
846 sprintf(type_value
, "%u\0", *value
.v_uint
);
849 sprintf(type_value
, "%ld\0", *value
.v_long
);
852 sprintf(type_value
, "%lu\0", *value
.v_ulong
);
855 sprintf(type_value
, "%f\0", (double)*value
.v_float
);
858 sprintf(type_value
, "%f\0", *value
.v_double
);
861 sprintf(type_value
, "%10u.%09u\0", value
.v_time
->tv_sec
,
862 value
.v_time
->tv_nsec
);
865 sprintf(type_value
, "POINTER\0");
868 sprintf(type_value
, "%s\0", *value
.v_string
);
874 if(flag
== 0) continue;
875 fprintf(fp
,"%s<VALUE type=\"%d\" name=\"%s\">",indent
,type
,g_quark_to_string(name
));
876 fprintf(fp
,"%s",type_value
);
877 fprintf(fp
,"</VALUE> \n");
882 void lttv_stats_save_statistics(LttvTracesetStats
*self
)
884 LttvTracesetStats
*tscs
= self
;
886 LttvTraceset
*traceset
= tscs
->parent
.parent
.ts
;
887 LttvAttributeType type
;
888 LttvAttributeValue value
;
889 LttvAttributeName name
;
891 char filename
[BUF_SIZE
];
893 char indent
[10][24]= {" ",
906 int i
, j
, k
, l
, m
, n
, nb_trace
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
;
908 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
909 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
910 *submode_tree
, *event_types_tree
;
912 nb_trace
= lttv_traceset_number(traceset
);
914 for(i
= 0 ; i
< nb_trace
; i
++) {
915 tcs
= (LttvTraceStats
*)(tscs
->parent
.parent
.traces
[i
]);
918 strcat(filename
,ltt_trace_name(tcs
->parent
.parent
.t
));
919 strcat(filename
,"/statistics.xml");
920 fp
= fopen(filename
,"w");
922 g_warning("can not open the file %s for saving statistics\n", filename
);
926 main_tree
= tcs
->stats
;
927 processes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_PROCESSES
);
928 nb_process
= lttv_attribute_get_number(processes_tree
);
930 fprintf(fp
, "<NODE name=\"%s\"> \n",g_quark_to_string(LTTV_STATS_PROCESSES
)); //root NODE
932 for(j
= 0 ; j
< nb_process
; j
++) {
933 type
= lttv_attribute_get(processes_tree
, j
, &name
, &value
);
934 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
936 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[0],g_quark_to_string(name
)); //process NODE
937 lttv_stats_save_attribute(process_tree
,indent
[1], fp
);
938 fprintf(fp
,"%s<NODE name=\"%s\"> \n", indent
[1],g_quark_to_string(LTTV_STATS_CPU
)); //cpus NODE
940 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
941 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
943 for(k
= 0 ; k
< nb_cpu
; k
++) {
944 type
= lttv_attribute_get(cpus_tree
, k
, &name
, &value
);
945 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
947 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[2],g_quark_to_string(name
)); //cpu NODE
948 lttv_stats_save_attribute(cpu_tree
,indent
[3], fp
);
949 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[3],g_quark_to_string(LTTV_STATS_MODE_TYPES
)); //mode_types NODE
951 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,LTTV_STATS_MODE_TYPES
);
952 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
954 for(l
= 0 ; l
< nb_mode_type
; l
++) {
955 type
= lttv_attribute_get(mode_types_tree
, l
, &name
, &value
);
956 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
958 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[4],g_quark_to_string(name
)); //mode NODE
959 lttv_stats_save_attribute(mode_tree
,indent
[5], fp
);
960 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[5],g_quark_to_string(LTTV_STATS_SUBMODES
)); //sub_modes NODE
962 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,LTTV_STATS_SUBMODES
);
963 nb_submode
= lttv_attribute_get_number(submodes_tree
);
965 for(m
= 0 ; m
< nb_submode
; m
++) {
966 type
= lttv_attribute_get(submodes_tree
, m
, &name
, &value
);
967 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
968 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[6],g_quark_to_string(name
)); //sub_mode NODE
969 lttv_stats_save_attribute(submode_tree
,indent
[7], fp
);
970 fprintf(fp
,"%s<NODE name=\"%s\"> \n",indent
[7],g_quark_to_string(LTTV_STATS_EVENT_TYPES
)); //event_types NODE
972 event_types_tree
= lttv_attribute_find_subdir(submode_tree
, LTTV_STATS_EVENT_TYPES
);
973 lttv_stats_save_attribute(event_types_tree
,indent
[8], fp
);
975 fprintf(fp
,"%s</NODE> \n",indent
[7]); //event_types NODE
976 fprintf(fp
,"%s</NODE> \n",indent
[6]); //sub_mode NODE
978 fprintf(fp
,"%s</NODE> \n",indent
[5]); //sub_modes NODE
979 fprintf(fp
,"%s</NODE> \n",indent
[4]); //mode NODE
981 fprintf(fp
,"%s</NODE> \n",indent
[3]); //mode_type NODE
982 fprintf(fp
,"%s</NODE> \n",indent
[2]); //cpu NODE
984 fprintf(fp
,"%s</NODE> \n",indent
[1]); //cpus NODE
985 fprintf(fp
,"%s</NODE> \n", indent
[0]); //process NODE
987 fprintf(fp
, "</NODE>\n"); //root NODE
993 /* Functions to parse statistic.xml file (using glib xml parser) */
995 typedef struct _ParserStruct
{
996 GPtrArray
* attribute
;
997 LttvAttributeType type
;
998 LttvAttributeName name
;
1001 static void stats_parser_start_element (GMarkupParseContext
*context
,
1002 const gchar
*element_name
,
1003 const gchar
**attribute_names
,
1004 const gchar
**attribute_values
,
1008 ParserStruct
* parser
= (ParserStruct
*)user_data
;
1010 LttvAttributeType type
;
1011 LttvAttributeName name
;
1012 LttvAttribute
* parent_att
, *new_att
;
1014 len
= parser
->attribute
->len
;
1015 parent_att
= (LttvAttribute
*)g_ptr_array_index (parser
->attribute
, len
-1);
1017 if(strcmp("NODE", element_name
) == 0){
1018 type
= LTTV_GOBJECT
;
1019 name
= g_quark_from_string(attribute_values
[0]);
1020 new_att
= lttv_attribute_find_subdir(parent_att
,name
);
1021 g_ptr_array_add(parser
->attribute
, (gpointer
)new_att
);
1022 }else if(strcmp("VALUE", element_name
) == 0){
1023 parser
->type
= (LttvAttributeType
) atoi(attribute_values
[0]);
1024 parser
->name
= g_quark_from_string(attribute_values
[1]);
1026 g_warning("This is not statistics.xml file\n");
1031 static void stats_parser_end_element (GMarkupParseContext
*context
,
1032 const gchar
*element_name
,
1036 ParserStruct
* parser
= (ParserStruct
*)user_data
;
1038 LttvAttribute
* parent_att
;
1040 len
= parser
->attribute
->len
;
1041 parent_att
= (LttvAttribute
*)g_ptr_array_index (parser
->attribute
, len
-1);
1043 if(strcmp("NODE", element_name
) == 0){
1044 g_ptr_array_remove_index(parser
->attribute
, len
-1);
1045 }else if(strcmp("VALUE", element_name
) == 0){
1047 g_warning("This is not statistics.xml file\n");
1053 static void stats_parser_characters (GMarkupParseContext
*context
,
1059 ParserStruct
* parser
= (ParserStruct
*)user_data
;
1060 LttvAttributeValue value
;
1062 LttvAttribute
* parent_att
;
1066 for(len
=0;len
<text_len
;len
++){
1073 if(strlen(pos
) == 0)return;
1075 len
= parser
->attribute
->len
;
1076 parent_att
= (LttvAttribute
*)g_ptr_array_index (parser
->attribute
, len
-1);
1077 if(!lttv_attribute_find(parent_att
,parser
->name
, parser
->type
, &value
)){
1078 g_warning("can not find value\n");
1082 switch(parser
->type
) {
1084 *value
.v_int
= atoi(text
);
1087 *value
.v_uint
= (unsigned)atoi(text
);
1090 *value
.v_long
= atol(text
);
1093 *value
.v_ulong
= (unsigned long)atol(text
);
1096 *value
.v_float
= atof(text
);
1099 *value
.v_float
= atof(text
);
1102 pos
= strrchr(text
,'.');
1106 value
.v_time
->tv_sec
= atol(text
);
1107 value
.v_time
->tv_nsec
= atol(pos
);
1109 g_warning("The time value format is wrong\n");
1116 *value
.v_string
= g_strdup(text
);
1124 gboolean
lttv_stats_load_statistics(LttvTracesetStats
*self
)
1128 LttvTracesetStats
*tscs
= self
;
1129 LttvTraceStats
*tcs
;
1130 LttvTraceset
*traceset
= tscs
->parent
.parent
.ts
;
1131 char filename
[BUF_SIZE
];
1133 GMarkupParseContext
* context
;
1135 GMarkupParser markup_parser
=
1137 stats_parser_start_element
,
1138 stats_parser_end_element
,
1139 stats_parser_characters
,
1140 NULL
, /* passthrough */
1145 LttvAttribute
*main_tree
;
1146 ParserStruct a_parser_struct
;
1147 a_parser_struct
.attribute
= g_ptr_array_new();
1149 nb_trace
= lttv_traceset_number(traceset
);
1151 for(i
= 0 ; i
< nb_trace
; i
++) {
1152 tcs
= (LttvTraceStats
*)(tscs
->parent
.parent
.traces
[i
]);
1155 strcat(filename
,ltt_trace_name(tcs
->parent
.parent
.t
));
1156 strcat(filename
,"/statistics.xml");
1157 fp
= fopen(filename
,"r");
1159 g_warning("can not open the file %s for reading statistics\n", filename
);
1163 main_tree
= tcs
->stats
;
1164 g_ptr_array_add(a_parser_struct
.attribute
,(gpointer
)main_tree
);
1166 context
= g_markup_parse_context_new(&markup_parser
, 0, (gpointer
)&a_parser_struct
, NULL
);
1168 while(fgets(buf
,BUF_SIZE
, fp
) != NULL
){
1169 if(!g_markup_parse_context_parse(context
, buf
, BUF_SIZE
, &error
)){
1170 g_warning("Can not parse xml file: \n%s\n", error
->message
);
1177 sum_stats(NULL
, (void *)self
);