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 nb_trace
= lttv_traceset_number(traceset
);
744 for(i
= 0 ; i
< nb_trace
; i
++) {
745 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
747 /* Find the eventtype id for the following events and register the
748 associated by id hooks. */
750 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
751 g_array_set_size(hooks
, 7);
753 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
754 "syscall_id", NULL
, NULL
, before_syscall_entry
,
755 &g_array_index(hooks
, LttvTraceHook
, 0));
757 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
758 NULL
, NULL
, before_syscall_exit
,
759 &g_array_index(hooks
, LttvTraceHook
, 1));
761 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
762 NULL
, NULL
, before_trap_entry
,
763 &g_array_index(hooks
, LttvTraceHook
, 2));
765 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
766 NULL
, before_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
768 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
769 NULL
, NULL
, before_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
771 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
772 NULL
, before_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
774 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "schedchange", "in",
775 "out", "out_state", before_schedchange
,
776 &g_array_index(hooks
, LttvTraceHook
, 6));
778 before_hooks
= hooks
;
780 hooks
= g_array_new(FALSE
, FALSE
, sizeof(LttvTraceHook
));
781 g_array_set_size(hooks
, 8);
783 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core","syscall_entry",
784 "syscall_id", NULL
, NULL
, after_syscall_entry
,
785 &g_array_index(hooks
, LttvTraceHook
, 0));
787 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "syscall_exit", NULL
,
788 NULL
, NULL
, after_syscall_exit
,
789 &g_array_index(hooks
, LttvTraceHook
, 1));
791 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_entry", "trap_id",
792 NULL
, NULL
, after_trap_entry
, &g_array_index(hooks
, LttvTraceHook
, 2));
794 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "trap_exit", NULL
, NULL
,
795 NULL
, after_trap_exit
, &g_array_index(hooks
, LttvTraceHook
, 3));
797 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_entry", "irq_id",
798 NULL
, NULL
, after_irq_entry
, &g_array_index(hooks
, LttvTraceHook
, 4));
800 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "irq_exit", NULL
, NULL
,
801 NULL
, after_irq_exit
, &g_array_index(hooks
, LttvTraceHook
, 5));
803 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_fork",
804 "child_pid", NULL
, NULL
, process_fork
,
805 &g_array_index(hooks
, LttvTraceHook
, 6));
807 lttv_trace_find_hook(ts
->parent
.parent
.t
, "core", "process_exit", NULL
,
808 NULL
, NULL
, process_exit
, &g_array_index(hooks
, LttvTraceHook
, 7));
812 /* Add these hooks to each event_by_id hooks list */
814 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
815 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
817 for(j
= 0 ; j
< nb_tracefile
; j
++) {
818 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
819 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
822 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
823 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
824 lttv_hooks_add(lttv_hooks_by_id_find(
825 tfs
->parent
.parent
.event_by_id
,
826 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
),
827 LTTV_PRIO_STATS_BEFORE_STATE
);
829 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
830 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
831 lttv_hooks_add(lttv_hooks_by_id_find(
832 tfs
->parent
.parent
.event_by_id
,
833 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
),
834 LTTV_PRIO_STATS_AFTER_STATE
);
837 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
839 *(val
.v_pointer
) = before_hooks
;
840 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
842 *(val
.v_pointer
) = after_hooks
;
846 // Hook wrapper. call_data is a traceset context.
847 gint
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
849 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
851 lttv_stats_remove_event_hooks(tss
);
856 lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
858 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
860 guint i
, j
, k
, nb_trace
, nb_tracefile
;
864 LttvTracefileStats
*tfs
;
868 GArray
*before_hooks
, *after_hooks
;
872 LttvAttributeValue val
;
874 nb_trace
= lttv_traceset_number(traceset
);
875 for(i
= 0 ; i
< nb_trace
; i
++) {
876 ts
= LTTV_TRACE_STATS(self
->parent
.parent
.traces
[i
]);
877 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
879 before_hooks
= *(val
.v_pointer
);
880 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
882 after_hooks
= *(val
.v_pointer
);
884 /* Remove these hooks from each event_by_id hooks list */
886 nb_tracefile
= ltt_trace_control_tracefile_number(ts
->parent
.parent
.t
) +
887 ltt_trace_per_cpu_tracefile_number(ts
->parent
.parent
.t
);
889 for(j
= 0 ; j
< nb_tracefile
; j
++) {
890 tfs
= LTTV_TRACEFILE_STATS(ts
->parent
.parent
.tracefiles
[j
]);
891 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
894 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
895 hook
= g_array_index(before_hooks
, LttvTraceHook
, k
);
896 lttv_hooks_remove_data(
897 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
898 hook
.id
), hook
.h
, &g_array_index(before_hooks
, LttvTraceHook
, k
));
900 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
901 hook
= g_array_index(after_hooks
, LttvTraceHook
, k
);
902 lttv_hooks_remove_data(
903 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
,
904 hook
.id
), hook
.h
, &g_array_index(after_hooks
, LttvTraceHook
, k
));
907 g_debug("lttv_stats_remove_event_hooks()");
908 g_array_free(before_hooks
, TRUE
);
909 g_array_free(after_hooks
, TRUE
);
914 static void module_init()
916 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
917 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
918 LTTV_STATS_CPU
= g_quark_from_string("cpu");
919 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
920 LTTV_STATS_MODES
= g_quark_from_string("modes");
921 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
922 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
923 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
924 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
925 LTTV_STATS_EVENTS
= g_quark_from_string("events");
926 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
927 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
928 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
929 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
930 LTTV_STATS
= g_quark_from_string("statistics");
931 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
932 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
935 static void module_destroy()
940 LTTV_MODULE("stats", "Compute processes statistics", \
941 "Accumulate statistics for event types, processes and CPUs", \
942 module_init
, module_destroy
, "state");
944 /* Change the places where stats are called (create/read/write stats)
946 Check for options in batchtest.c to reduce writing and see what tests are
947 best candidates for performance analysis. Once OK, commit, move to main
948 and run tests. Update the gui for statistics. */