1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24 #include <lttv/module.h>
25 #include <lttv/stats.h>
26 #include <lttv/lttv.h>
27 #include <lttv/attribute.h>
28 #include <ltt/facility.h>
29 #include <ltt/trace.h>
30 #include <ltt/event.h>
35 LTTV_STATS_PROCESS_UNKNOWN
,
38 LTTV_STATS_MODE_TYPES
,
41 LTTV_STATS_EVENT_TYPES
,
43 LTTV_STATS_ELAPSED_TIME
,
45 LTTV_STATS_EVENTS_COUNT
,
48 LTTV_STATS_TRACEFILES
,
52 LTTV_STATS_BEFORE_HOOKS
,
53 LTTV_STATS_AFTER_HOOKS
;
56 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, GQuark cpu
,
57 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
58 LttvAttribute
**event_types_tree
);
61 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
63 guint i
, j
, nb_trace
, nb_tracefile
;
69 LttvTracefileContext
*tfc
;
71 LttvTracefileStats
*tfcs
;
73 LttTime timestamp
= {0,0};
81 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
82 init((LttvTracesetContext
*)self
, ts
);
84 self
->stats
= lttv_attribute_find_subdir(
85 lttv_traceset_attribute(self
->parent
.parent
.ts
),
87 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
92 if(*(v
.v_uint
) == 1) {
93 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
96 nb_trace
= lttv_traceset_number(ts
);
98 for(i
= 0 ; i
< nb_trace
; i
++) {
99 tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
100 tcs
= (LttvTraceStats
*)tc
;
102 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
103 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
104 LTTV_STATS_TRACEFILES
);
105 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
109 if(*(v
.v_uint
) == 1) {
110 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
113 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
114 ltt_trace_per_cpu_tracefile_number(tc
->t
);
116 for(j
= 0 ; j
< nb_tracefile
; j
++) {
117 tfcs
= LTTV_TRACEFILE_STATS(tc
->tracefiles
[j
]);
118 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
119 tfcs
->parent
.cpu_name
);
120 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
121 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
122 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
123 &tfcs
->current_event_types_tree
);
129 fini(LttvTracesetStats
*self
)
131 guint i
, j
, nb_trace
, nb_tracefile
;
135 LttvTraceContext
*tc
;
139 LttvTracefileContext
*tfc
;
141 LttvTracefileStats
*tfcs
;
143 LttTime timestamp
= {0,0};
145 LttvAttributeValue v
;
147 LttvAttribute
*tracefiles_stats
;
149 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
153 if(*(v
.v_uint
) == 0) {
154 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
158 ts
= self
->parent
.parent
.ts
;
159 nb_trace
= lttv_traceset_number(ts
);
161 for(i
= 0 ; i
< nb_trace
; i
++) {
162 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
164 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
168 if(*(v
.v_uint
) == 0) {
169 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
170 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
171 LTTV_STATS_TRACEFILES
);
172 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
173 LTTV_STATS_TRACEFILES
);
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 */
257 NULL
/* Value handling */
260 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
261 "LttvTracesetStatsType",
269 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
275 trace_stats_finalize (LttvTraceStats
*self
)
277 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
278 finalize(G_OBJECT(self
));
283 trace_stats_class_init (LttvTraceContextClass
*klass
)
285 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
287 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
292 lttv_trace_stats_get_type(void)
294 static GType type
= 0;
296 static const GTypeInfo info
= {
297 sizeof (LttvTraceStatsClass
),
298 NULL
, /* base_init */
299 NULL
, /* base_finalize */
300 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
301 NULL
, /* class_finalize */
302 NULL
, /* class_data */
303 sizeof (LttvTraceStats
),
305 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
306 NULL
/* Value handling */
309 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
310 "LttvTraceStatsType", &info
, 0);
317 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
323 tracefile_stats_finalize (LttvTracefileStats
*self
)
325 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
326 finalize(G_OBJECT(self
));
331 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
333 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
335 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
340 lttv_tracefile_stats_get_type(void)
342 static GType type
= 0;
344 static const GTypeInfo info
= {
345 sizeof (LttvTracefileStatsClass
),
346 NULL
, /* base_init */
347 NULL
, /* base_finalize */
348 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
349 NULL
, /* class_finalize */
350 NULL
, /* class_data */
351 sizeof (LttvTracefileStats
),
353 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
354 NULL
/* Value handling */
357 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
358 "LttvTracefileStatsType", &info
, 0);
365 find_event_tree(LttvTracefileStats
*tfcs
,
370 LttvAttribute
**events_tree
,
371 LttvAttribute
**event_types_tree
)
375 LttvTraceStats
*tcs
= LTTV_TRACE_STATS(tfcs
->parent
.parent
.t_context
);
376 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
377 a
= lttv_attribute_find_subdir(a
, pid_time
);
378 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
379 a
= lttv_attribute_find_subdir(a
, cpu
);
380 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
381 a
= lttv_attribute_find_subdir(a
, mode
);
382 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
383 a
= lttv_attribute_find_subdir(a
, sub_mode
);
385 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
386 *event_types_tree
= a
;
390 static void update_event_tree(LttvTracefileStats
*tfcs
)
392 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
394 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
,
395 tfcs
->parent
.cpu_name
,
396 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
397 &(tfcs
->current_event_types_tree
));
401 static void mode_change(LttvTracefileStats
*tfcs
)
403 LttvAttributeValue cpu_time
;
407 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
408 LTTV_TIME
, &cpu_time
);
409 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
410 tfcs
->parent
.process
->state
->change
);
411 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
415 static void mode_end(LttvTracefileStats
*tfcs
)
417 LttvAttributeValue elapsed_time
, cpu_time
;
421 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
422 LTTV_TIME
, &elapsed_time
);
423 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
424 tfcs
->parent
.process
->state
->entry
);
425 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
427 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
428 LTTV_TIME
, &cpu_time
);
429 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
430 tfcs
->parent
.process
->state
->change
);
431 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
435 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
437 mode_change((LttvTracefileStats
*)call_data
);
442 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
444 update_event_tree((LttvTracefileStats
*)call_data
);
449 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
451 mode_end((LttvTracefileStats
*)call_data
);
456 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
458 update_event_tree((LttvTracefileStats
*)call_data
);
463 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
465 mode_change((LttvTracefileStats
*)call_data
);
470 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
472 update_event_tree((LttvTracefileStats
*)call_data
);
477 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
479 mode_end((LttvTracefileStats
*)call_data
);
484 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
486 update_event_tree((LttvTracefileStats
*)call_data
);
491 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
493 mode_change((LttvTracefileStats
*)call_data
);
498 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
500 update_event_tree((LttvTracefileStats
*)call_data
);
505 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
507 mode_end((LttvTracefileStats
*)call_data
);
512 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
514 update_event_tree((LttvTracefileStats
*)call_data
);
519 gboolean
before_schedchange(void *hook_data
, void *call_data
)
521 LttvTraceHook
*h
= (LttvTraceHook
*)hook_data
;
523 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
525 guint pid_in
, pid_out
, state_out
;
527 LttvProcessState
*process
;
529 pid_in
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f1
);
530 pid_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f2
);
531 state_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f3
);
533 /* compute the time for the process to schedule out */
537 /* get the information for the process scheduled in */
539 process
= lttv_state_find_process_or_create(&(tfcs
->parent
), pid_in
);
541 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
542 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
543 &(tfcs
->current_event_types_tree
));
545 /* compute the time waiting for the process to schedule in */
552 gboolean
process_fork(void *hook_data
, void *call_data
)
554 /* nothing to do for now */
559 gboolean
process_exit(void *hook_data
, void *call_data
)
561 /* We should probably exit all modes here or we could do that at
567 gboolean
every_event(void *hook_data
, void *call_data
)
569 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
571 LttvAttributeValue v
;
573 /* The current branch corresponds to the tracefile/process/interrupt state.
574 Statistics are added within it, to count the number of events of this
575 type occuring in this context. A quark has been pre-allocated for each
576 event type and is used as name. */
578 lttv_attribute_find(tfcs
->current_event_types_tree
,
579 ((LttvTraceState
*)(tfcs
->parent
.parent
.t_context
))->
580 eventtype_names
[ltt_event_eventtype_id(tfcs
->parent
.parent
.e
)],
588 lttv_stats_sum_trace(LttvTraceStats
*self
)
590 LttvAttribute
*sum_container
= self
->stats
;
592 LttvAttributeType type
;
594 LttvAttributeValue value
;
596 LttvAttributeName name
;
600 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
603 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
604 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
605 *submode_tree
, *event_types_tree
, *mode_events_tree
,
606 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
609 main_tree
= sum_container
;
611 lttv_attribute_find(sum_container
,
614 if(*(value
.v_uint
) != 0) return;
617 processes_tree
= lttv_attribute_find_subdir(main_tree
,
618 LTTV_STATS_PROCESSES
);
619 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
,
621 nb_process
= lttv_attribute_get_number(processes_tree
);
623 for(i
= 0 ; i
< nb_process
; i
++) {
624 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
625 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
627 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
628 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
630 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
632 for(j
= 0 ; j
< nb_cpu
; j
++) {
633 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
634 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
636 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
637 LTTV_STATS_MODE_TYPES
);
638 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
640 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
641 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
642 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
644 for(k
= 0 ; k
< nb_mode_type
; k
++) {
645 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
646 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
648 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
649 LTTV_STATS_SUBMODES
);
650 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
652 nb_submode
= lttv_attribute_get_number(submodes_tree
);
654 for(l
= 0 ; l
< nb_submode
; l
++) {
655 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
656 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
658 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
659 LTTV_STATS_EVENT_TYPES
);
660 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
663 for(m
= 0 ; m
< nb_event_type
; m
++) {
664 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
665 sum
+= *(value
.v_uint
);
667 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
669 *(value
.v_uint
) = sum
;
670 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
672 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
674 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
675 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
677 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
682 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
684 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
689 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
691 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
692 LttvAttribute
*sum_container
= self
->stats
;
698 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
700 LttvAttributeValue value
;
702 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
704 if(*(value
.v_uint
) != 0) return;
707 traceset_modes_tree
= lttv_attribute_find_subdir(sum_container
,
709 nb_trace
= lttv_traceset_number(traceset
);
711 for(i
= 0 ; i
< nb_trace
; i
++) {
712 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
713 lttv_stats_sum_trace(tcs
);
714 main_tree
= tcs
->stats
;
715 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
716 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
721 // Hook wrapper. call_data is a traceset context.
722 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
724 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
726 lttv_stats_add_event_hooks(tss
);
731 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
733 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
735 guint i
, j
, k
, nb_trace
, nb_tracefile
;
743 LttvTracefileStats
*tfs
;
747 GArray
*hooks
, *before_hooks
, *after_hooks
;
751 LttvAttributeValue val
;
753 nb_trace
= lttv_traceset_number(traceset
);
754 for(i
= 0 ; i
< nb_trace
; i
++) {
755 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
757 /* Find the eventtype id for the following events and register the
758 associated by id hooks. */
760 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
761 g_array_set_size(hooks
, 7);
763 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
764 "syscall_id", NULL
, NULL
, before_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
, before_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
, before_trap_entry
,
773 &g_array_index(hooks
, LttvTraceHook
, 2));
775 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
776 NULL
, before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
778 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
779 NULL
, NULL
, before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
781 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
782 NULL
, before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
784 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "schedchange", "in",
785 "out", "out_state", before_schedchange
,
786 &g_array_index(hooks
, LttvTraceHook
, 6));
788 before_hooks
= hooks
;
790 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
791 g_array_set_size(hooks
, 8);
793 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
794 "syscall_id", NULL
, NULL
, after_syscall_entry
,
795 &g_array_index(hooks
, LttvTraceHook
, 0));
797 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
798 NULL
, NULL
, after_syscall_exit
,
799 &g_array_index(hooks
, LttvTraceHook
, 1));
801 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
802 NULL
, NULL
, after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
804 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
805 NULL
, after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
807 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
808 NULL
, NULL
, after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
810 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
811 NULL
, after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
813 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_fork",
814 "child_pid", NULL
, NULL
, process_fork
,
815 &g_array_index(hooks
, LttvTraceHook
, 6));
817 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_exit", NULL
,
818 NULL
, NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
822 /* Add these hooks to each event_by_id hooks list */
824 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
825 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
827 for(j
= 0 ; j
< nb_tracefile
; j
++) {
828 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
829 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
832 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
833 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
834 lttv_hooks_add(lttv_hooks_by_id_find(
835 tfs
->parent
.parent
.event_by_id
,
836 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
),
837 LTTV_PRIO_STATS_BEFORE_STATE
);
839 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
840 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
841 lttv_hooks_add(lttv_hooks_by_id_find(
842 tfs
->parent
.parent
.event_by_id
,
843 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
),
844 LTTV_PRIO_STATS_AFTER_STATE
);
847 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
849 *(val
.v_pointer
) = before_hooks
;
850 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
852 *(val
.v_pointer
) = after_hooks
;
856 // Hook wrapper. call_data is a traceset context.
857 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
859 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
861 lttv_stats_remove_event_hooks(tss
);
866 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
868 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
870 guint i
, j
, k
, nb_trace
, nb_tracefile
;
874 LttvTracefileStats
*tfs
;
878 GArray
*before_hooks
, *after_hooks
;
882 LttvAttributeValue val
;
884 nb_trace
= lttv_traceset_number(traceset
);
885 for(i
= 0 ; i
< nb_trace
; i
++) {
886 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
887 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
889 before_hooks
= *(val
.v_pointer
);
890 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
892 after_hooks
= *(val
.v_pointer
);
894 /* Remove these hooks from each event_by_id hooks list */
896 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
897 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
899 for(j
= 0 ; j
< nb_tracefile
; j
++) {
900 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
901 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
904 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
905 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
906 lttv_hooks_remove_data(
907 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
908 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
910 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
911 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
912 lttv_hooks_remove_data(
913 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
914 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
917 g_debug("lttv_stats_remove_event_hooks()");
918 g_array_free(before_hooks
, TRUE
);
919 g_array_free(after_hooks
, TRUE
);
924 static void module_init()
926 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
927 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
928 LTTV_STATS_CPU
= g_quark_from_string("cpu");
929 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
930 LTTV_STATS_MODES
= g_quark_from_string("modes");
931 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
932 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
933 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
934 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
935 LTTV_STATS_EVENTS
= g_quark_from_string("events");
936 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
937 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
938 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
939 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
940 LTTV_STATS
= g_quark_from_string("statistics");
941 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
942 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
945 static void module_destroy()
950 LTTV_MODULE("stats", "Compute processes statistics", \
951 "Accumulate statistics for event types, processes and CPUs", \
952 module_init
, module_destroy
, "state");
954 /* Change the places where stats are called (create/read/write stats)
956 Check for options in batchtest.c to reduce writing and see what tests are
957 best candidates for performance analysis. Once OK, commit, move to main
958 and run tests. Update the gui for statistics. */