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(
84 lttv_traceset_attribute(self
->parent
.parent
.ts
),
86 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
91 if(*(v
.v_uint
) == 1) {
92 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
95 nb_trace
= lttv_traceset_number(ts
);
97 for(i
= 0 ; i
< nb_trace
; i
++) {
98 tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]);
99 tcs
= (LttvTraceStats
*)tc
;
101 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
102 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
103 LTTV_STATS_TRACEFILES
);
104 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
108 if(*(v
.v_uint
) == 1) {
109 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
112 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
113 ltt_trace_per_cpu_tracefile_number(tc
->t
);
115 for(j
= 0 ; j
< nb_tracefile
; j
++) {
116 tfcs
= LTTV_TRACEFILE_STATS(tc
->tracefiles
[j
]);
117 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
118 tfcs
->parent
.cpu_name
);
119 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
120 tfcs
->parent
.cpu_name
, LTTV_STATE_MODE_UNKNOWN
,
121 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
122 &tfcs
->current_event_types_tree
);
128 fini(LttvTracesetStats
*self
)
130 guint i
, j
, nb_trace
, nb_tracefile
;
134 LttvTraceContext
*tc
;
138 LttvTracefileContext
*tfc
;
140 LttvTracefileStats
*tfcs
;
142 LttTime timestamp
= {0,0};
144 LttvAttributeValue v
;
146 LttvAttribute
*tracefiles_stats
;
148 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
152 if(*(v
.v_uint
) == 0) {
153 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
157 ts
= self
->parent
.parent
.ts
;
158 nb_trace
= lttv_traceset_number(ts
);
160 for(i
= 0 ; i
< nb_trace
; i
++) {
161 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
163 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
167 if(*(v
.v_uint
) == 0) {
168 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_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
);
176 nb_tracefile
= ltt_trace_control_tracefile_number(tc
->t
) +
177 ltt_trace_per_cpu_tracefile_number(tc
->t
);
179 for(j
= 0 ; j
< nb_tracefile
; j
++) {
180 tfc
= tc
->tracefiles
[j
];
181 tfcs
= (LttvTracefileStats
*)tfc
;
183 tfcs
->current_events_tree
= NULL
;
184 tfcs
->current_event_types_tree
= NULL
;
187 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
188 fini((LttvTracesetContext
*)self
);
192 static LttvTracesetContext
*
193 new_traceset_context(LttvTracesetContext
*self
)
195 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
199 static LttvTraceContext
*
200 new_trace_context(LttvTracesetContext
*self
)
202 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
206 static LttvTracefileContext
*
207 new_tracefile_context(LttvTracesetContext
*self
)
209 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
214 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
220 traceset_stats_finalize (LttvTracesetStats
*self
)
222 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
223 finalize(G_OBJECT(self
));
228 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
230 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
232 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
233 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
234 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
235 klass
->new_traceset_context
= new_traceset_context
;
236 klass
->new_trace_context
= new_trace_context
;
237 klass
->new_tracefile_context
= new_tracefile_context
;
242 lttv_traceset_stats_get_type(void)
244 static GType type
= 0;
246 static const GTypeInfo info
= {
247 sizeof (LttvTracesetStatsClass
),
248 NULL
, /* base_init */
249 NULL
, /* base_finalize */
250 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
251 NULL
, /* class_finalize */
252 NULL
, /* class_data */
253 sizeof (LttvTracesetStats
),
255 (GInstanceInitFunc
) traceset_stats_instance_init
/* instance_init */
258 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
, "LttvTracesetStatsType",
266 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
272 trace_stats_finalize (LttvTraceStats
*self
)
274 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
275 finalize(G_OBJECT(self
));
280 trace_stats_class_init (LttvTraceContextClass
*klass
)
282 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
284 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
289 lttv_trace_stats_get_type(void)
291 static GType type
= 0;
293 static const GTypeInfo info
= {
294 sizeof (LttvTraceStatsClass
),
295 NULL
, /* base_init */
296 NULL
, /* base_finalize */
297 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
298 NULL
, /* class_finalize */
299 NULL
, /* class_data */
300 sizeof (LttvTraceStats
),
302 (GInstanceInitFunc
) trace_stats_instance_init
/* instance_init */
305 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
306 "LttvTraceStatsType", &info
, 0);
313 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
319 tracefile_stats_finalize (LttvTracefileStats
*self
)
321 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
322 finalize(G_OBJECT(self
));
327 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
329 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
331 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
336 lttv_tracefile_stats_get_type(void)
338 static GType type
= 0;
340 static const GTypeInfo info
= {
341 sizeof (LttvTracefileStatsClass
),
342 NULL
, /* base_init */
343 NULL
, /* base_finalize */
344 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
345 NULL
, /* class_finalize */
346 NULL
, /* class_data */
347 sizeof (LttvTracefileStats
),
349 (GInstanceInitFunc
) tracefile_stats_instance_init
/* instance_init */
352 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
353 "LttvTracefileStatsType", &info
, 0);
360 find_event_tree(LttvTracefileStats
*tfcs
, GQuark process
, GQuark cpu
,
361 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
362 LttvAttribute
**event_types_tree
)
366 LttvTraceStats
*tcs
= LTTV_TRACE_STATS(tfcs
->parent
.parent
.t_context
);
367 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
368 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->pid_time
);
369 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
370 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.cpu_name
);
371 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
372 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->t
);
373 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
374 a
= lttv_attribute_find_subdir(a
, tfcs
->parent
.process
->state
->n
);
376 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
377 *event_types_tree
= a
;
381 static void update_event_tree(LttvTracefileStats
*tfcs
)
383 LttvExecutionState
*es
= tfcs
->parent
.process
->state
;
385 find_event_tree(tfcs
, tfcs
->parent
.process
->pid_time
, tfcs
->parent
.cpu_name
,
386 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
387 &(tfcs
->current_event_types_tree
));
391 static void mode_change(LttvTracefileStats
*tfcs
)
393 LttvAttributeValue cpu_time
;
397 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
398 LTTV_TIME
, &cpu_time
);
399 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
400 tfcs
->parent
.process
->state
->change
);
401 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
405 static void mode_end(LttvTracefileStats
*tfcs
)
407 LttvAttributeValue elapsed_time
, cpu_time
;
411 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
412 LTTV_TIME
, &elapsed_time
);
413 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
414 tfcs
->parent
.process
->state
->entry
);
415 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
417 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
418 LTTV_TIME
, &cpu_time
);
419 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
420 tfcs
->parent
.process
->state
->change
);
421 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
425 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
427 mode_change((LttvTracefileStats
*)call_data
);
432 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
434 update_event_tree((LttvTracefileStats
*)call_data
);
439 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
441 mode_end((LttvTracefileStats
*)call_data
);
446 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
448 update_event_tree((LttvTracefileStats
*)call_data
);
453 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
455 mode_change((LttvTracefileStats
*)call_data
);
460 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
462 update_event_tree((LttvTracefileStats
*)call_data
);
467 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
469 mode_end((LttvTracefileStats
*)call_data
);
474 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
476 update_event_tree((LttvTracefileStats
*)call_data
);
481 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
483 mode_change((LttvTracefileStats
*)call_data
);
488 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
490 update_event_tree((LttvTracefileStats
*)call_data
);
495 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
497 mode_end((LttvTracefileStats
*)call_data
);
502 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
504 update_event_tree((LttvTracefileStats
*)call_data
);
509 gboolean
before_schedchange(void *hook_data
, void *call_data
)
511 LttvTraceHook
*h
= (LttvTraceHook
*)hook_data
;
513 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
515 guint pid_in
, pid_out
, state_out
;
517 LttvProcessState
*process
;
519 pid_in
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f1
);
520 pid_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f2
);
521 state_out
= ltt_event_get_unsigned(tfcs
->parent
.parent
.e
, h
->f3
);
523 /* compute the time for the process to schedule out */
527 /* get the information for the process scheduled in */
529 process
= lttv_state_find_process_or_create(&(tfcs
->parent
), pid_in
);
531 find_event_tree(tfcs
, process
->pid_time
, tfcs
->parent
.cpu_name
,
532 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
533 &(tfcs
->current_event_types_tree
));
535 /* compute the time waiting for the process to schedule in */
542 gboolean
process_fork(void *hook_data
, void *call_data
)
544 /* nothing to do for now */
549 gboolean
process_exit(void *hook_data
, void *call_data
)
551 /* We should probably exit all modes here or we could do that at
557 gboolean
every_event(void *hook_data
, void *call_data
)
559 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
561 LttvAttributeValue v
;
563 /* The current branch corresponds to the tracefile/process/interrupt state.
564 Statistics are added within it, to count the number of events of this
565 type occuring in this context. A quark has been pre-allocated for each
566 event type and is used as name. */
568 lttv_attribute_find(tfcs
->current_event_types_tree
,
569 ((LttvTraceState
*)(tfcs
->parent
.parent
.t_context
))->
570 eventtype_names
[ltt_event_eventtype_id(tfcs
->parent
.parent
.e
)],
578 lttv_stats_sum_trace(LttvTraceStats
*self
)
580 LttvAttribute
*sum_container
= self
->stats
;
582 LttvAttributeType type
;
584 LttvAttributeValue value
;
586 LttvAttributeName name
;
590 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
593 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
594 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
595 *submode_tree
, *event_types_tree
, *mode_events_tree
,
596 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
599 main_tree
= sum_container
;
601 lttv_attribute_find(sum_container
,
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
,
611 nb_process
= lttv_attribute_get_number(processes_tree
);
613 for(i
= 0 ; i
< nb_process
; i
++) {
614 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
615 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
617 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
618 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
620 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
622 for(j
= 0 ; j
< nb_cpu
; j
++) {
623 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
624 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
626 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
627 LTTV_STATS_MODE_TYPES
);
628 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
630 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
631 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
632 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
634 for(k
= 0 ; k
< nb_mode_type
; k
++) {
635 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
636 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
638 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
639 LTTV_STATS_SUBMODES
);
640 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
642 nb_submode
= lttv_attribute_get_number(submodes_tree
);
644 for(l
= 0 ; l
< nb_submode
; l
++) {
645 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
646 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
648 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
649 LTTV_STATS_EVENT_TYPES
);
650 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
653 for(m
= 0 ; m
< nb_event_type
; m
++) {
654 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
655 sum
+= *(value
.v_uint
);
657 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
659 *(value
.v_uint
) = sum
;
660 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
662 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
664 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
665 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
667 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
672 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
674 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
679 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
681 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
682 LttvAttribute
*sum_container
= self
->stats
;
688 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
690 LttvAttributeValue value
;
692 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
694 if(*(value
.v_uint
) != 0) return;
697 traceset_modes_tree
= lttv_attribute_find_subdir(sum_container
,
699 nb_trace
= lttv_traceset_number(traceset
);
701 for(i
= 0 ; i
< nb_trace
; i
++) {
702 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
703 lttv_stats_sum_trace(tcs
);
704 main_tree
= tcs
->stats
;
705 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
706 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
711 // Hook wrapper. call_data is a traceset context.
712 gint
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
714 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
716 lttv_stats_add_event_hooks(tss
);
721 lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
723 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
725 guint i
, j
, k
, nb_trace
, nb_tracefile
;
733 LttvTracefileStats
*tfs
;
737 GArray
*hooks
, *before_hooks
, *after_hooks
;
741 LttvAttributeValue val
;
743 lttv_state_add_event_hooks(&self
->parent
);
745 nb_trace
= lttv_traceset_number(traceset
);
746 for(i
= 0 ; i
< nb_trace
; i
++) {
747 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
749 /* Find the eventtype id for the following events and register the
750 associated by id hooks. */
752 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
753 g_array_set_size(hooks
, 7);
755 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
756 "syscall_id", NULL
, NULL
, before_syscall_entry
,
757 &g_array_index(hooks
, LttvTraceHook
, 0));
759 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
760 NULL
, NULL
, before_syscall_exit
,
761 &g_array_index(hooks
, LttvTraceHook
, 1));
763 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
764 NULL
, NULL
, before_trap_entry
,
765 &g_array_index(hooks
, LttvTraceHook
, 2));
767 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
768 NULL
, before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
770 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
771 NULL
, NULL
, before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
773 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
774 NULL
, before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
776 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "schedchange", "in",
777 "out", "out_state", before_schedchange
,
778 &g_array_index(hooks
, LttvTraceHook
, 6));
780 before_hooks
= hooks
;
782 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
783 g_array_set_size(hooks
, 8);
785 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
786 "syscall_id", NULL
, NULL
, after_syscall_entry
,
787 &g_array_index(hooks
, LttvTraceHook
, 0));
789 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
790 NULL
, NULL
, after_syscall_exit
,
791 &g_array_index(hooks
, LttvTraceHook
, 1));
793 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
794 NULL
, NULL
, after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
796 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
797 NULL
, after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
799 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
800 NULL
, NULL
, after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
802 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
803 NULL
, after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
805 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_fork",
806 "child_pid", NULL
, NULL
, process_fork
,
807 &g_array_index(hooks
, LttvTraceHook
, 6));
809 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_exit", NULL
,
810 NULL
, NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
814 /* Add these hooks to each event_by_id hooks list */
816 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
817 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
819 for(j
= 0 ; j
< nb_tracefile
; j
++) {
820 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
821 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
824 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
825 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
826 lttv_hooks_add(lttv_hooks_by_id_find(
827 tfs
->parent
.parent
.event_by_id
,
828 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
),
829 LTTV_PRIO_STATS_BEFORE_STATE
);
831 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
832 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
833 lttv_hooks_add(lttv_hooks_by_id_find(
834 tfs
->parent
.parent
.event_by_id
,
835 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
),
836 LTTV_PRIO_STATS_AFTER_STATE
);
839 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
841 *(val
.v_pointer
) = before_hooks
;
842 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
844 *(val
.v_pointer
) = after_hooks
;
848 // Hook wrapper. call_data is a traceset context.
849 gint
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
851 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
853 lttv_stats_remove_event_hooks(tss
);
858 lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
860 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
862 guint i
, j
, k
, nb_trace
, nb_tracefile
;
866 LttvTracefileStats
*tfs
;
870 GArray
*before_hooks
, *after_hooks
;
874 LttvAttributeValue val
;
876 nb_trace
= lttv_traceset_number(traceset
);
877 for(i
= 0 ; i
< nb_trace
; i
++) {
878 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
879 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
881 before_hooks
= *(val
.v_pointer
);
882 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
884 after_hooks
= *(val
.v_pointer
);
886 /* Remove these hooks from each event_by_id hooks list */
888 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
889 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
891 for(j
= 0 ; j
< nb_tracefile
; j
++) {
892 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
893 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
896 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
897 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
898 lttv_hooks_remove_data(
899 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
900 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
902 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
903 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
904 lttv_hooks_remove_data(
905 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
906 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
909 g_debug("lttv_stats_remove_event_hooks()");
910 g_array_free(before_hooks
, TRUE
);
911 g_array_free(after_hooks
, TRUE
);
913 lttv_state_remove_event_hooks(&self
->parent
);
917 static void module_init()
919 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
920 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
921 LTTV_STATS_CPU
= g_quark_from_string("cpu");
922 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
923 LTTV_STATS_MODES
= g_quark_from_string("modes");
924 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
925 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
926 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
927 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
928 LTTV_STATS_EVENTS
= g_quark_from_string("events");
929 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
930 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
931 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
932 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
933 LTTV_STATS
= g_quark_from_string("statistics");
934 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
935 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
938 static void module_destroy()
943 LTTV_MODULE("stats", "Compute processes statistics", \
944 "Accumulate statistics for event types, processes and CPUs", \
945 module_init
, module_destroy
, "state");
947 /* Change the places where stats are called (create/read/write stats)
949 Check for options in batchtest.c to reduce writing and see what tests are
950 best candidates for performance analysis. Once OK, commit, move to main
951 and run tests. Update the gui for statistics. */