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>
36 LTTV_STATS_PROCESS_UNKNOWN
,
39 LTTV_STATS_MODE_TYPES
,
42 LTTV_STATS_EVENT_TYPES
,
44 LTTV_STATS_ELAPSED_TIME
,
46 LTTV_STATS_EVENTS_COUNT
,
49 LTTV_STATS_TRACEFILES
,
53 LTTV_STATS_BEFORE_HOOKS
,
54 LTTV_STATS_AFTER_HOOKS
;
57 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, GQuark cpu
,
58 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
59 LttvAttribute
**event_types_tree
);
62 static void lttv_stats_init(LttvTracesetStats
*self
)
64 guint i
, j
, nb_trace
, nb_tracefile
;
70 LttvTracefileContext
*tfc
;
72 LttvTracefileContext
**tfs
;
73 LttvTracefileStats
*tfcs
;
75 LttTime timestamp
= {0,0};
83 LttvTraceset
*ts
= self
->parent
.parent
.ts
;
85 self
->stats
= lttv_attribute_find_subdir(
86 lttv_traceset_attribute(self
->parent
.parent
.ts
),
88 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
93 if(*(v
.v_uint
) == 1) {
94 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
97 nb_trace
= lttv_traceset_number(ts
);
99 for(i
= 0 ; i
< nb_trace
; i
++) {
100 tc
= self
->parent
.parent
.traces
[i
];
101 tcs
= LTTV_TRACE_STATS(tc
);
103 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
104 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
105 LTTV_STATS_TRACEFILES
);
106 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
110 if(*(v
.v_uint
) == 1) {
111 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
114 nb_tracefile
= tc
->tracefiles
->len
;
116 for(j
= 0 ; j
< nb_tracefile
; j
++) {
117 tfs
= &g_array_index(tc
->tracefiles
,
118 LttvTracefileContext
*, j
);
119 tfcs
= LTTV_TRACEFILE_STATS(*tfs
);
120 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
121 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
));
122 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
123 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
124 LTTV_STATE_MODE_UNKNOWN
,
125 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
126 &tfcs
->current_event_types_tree
);
132 static void lttv_stats_fini(LttvTracesetStats
*self
)
134 guint i
, j
, nb_trace
, nb_tracefile
;
138 LttvTraceContext
*tc
;
142 LttvTracefileContext
*tfc
;
144 LttvTracefileStats
*tfcs
;
146 LttTime timestamp
= {0,0};
148 LttvAttributeValue v
;
150 LttvAttribute
*tracefiles_stats
;
152 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
156 if(*(v
.v_uint
) == 0) {
157 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
161 ts
= self
->parent
.parent
.ts
;
162 nb_trace
= lttv_traceset_number(ts
);
164 for(i
= 0 ; i
< nb_trace
; i
++) {
165 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
167 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
171 if(*(v
.v_uint
) == 0) {
172 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
173 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
174 LTTV_STATS_TRACEFILES
);
175 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
176 LTTV_STATS_TRACEFILES
);
180 nb_tracefile
= tc
->tracefiles
->len
;
182 for(j
= 0 ; j
< nb_tracefile
; j
++) {
183 tfc
= g_array_index(tc
->tracefiles
,
184 LttvTracefileContext
*, j
);
185 tfcs
= (LttvTracefileStats
*)tfc
;
187 tfcs
->current_events_tree
= NULL
;
188 tfcs
->current_event_types_tree
= NULL
;
194 void lttv_stats_reset(LttvTracesetStats
*self
)
196 lttv_stats_fini(self
);
197 lttv_stats_init(self
);
203 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
205 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
206 init((LttvTracesetContext
*)self
, ts
);
208 lttv_stats_init(self
);
213 fini(LttvTracesetStats
*self
)
215 lttv_stats_fini(self
);
217 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
218 fini((LttvTracesetContext
*)self
);
222 static LttvTracesetContext
*
223 new_traceset_context(LttvTracesetContext
*self
)
225 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
229 static LttvTraceContext
*
230 new_trace_context(LttvTracesetContext
*self
)
232 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
236 static LttvTracefileContext
*
237 new_tracefile_context(LttvTracesetContext
*self
)
239 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
244 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
250 traceset_stats_finalize (LttvTracesetStats
*self
)
252 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
253 finalize(G_OBJECT(self
));
258 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
260 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
262 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
263 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
264 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
265 klass
->new_traceset_context
= new_traceset_context
;
266 klass
->new_trace_context
= new_trace_context
;
267 klass
->new_tracefile_context
= new_tracefile_context
;
272 lttv_traceset_stats_get_type(void)
274 static GType type
= 0;
276 static const GTypeInfo info
= {
277 sizeof (LttvTracesetStatsClass
),
278 NULL
, /* base_init */
279 NULL
, /* base_finalize */
280 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
281 NULL
, /* class_finalize */
282 NULL
, /* class_data */
283 sizeof (LttvTracesetStats
),
285 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
286 NULL
/* Value handling */
289 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
290 "LttvTracesetStatsType",
298 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
304 trace_stats_finalize (LttvTraceStats
*self
)
306 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
307 finalize(G_OBJECT(self
));
312 trace_stats_class_init (LttvTraceContextClass
*klass
)
314 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
316 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
321 lttv_trace_stats_get_type(void)
323 static GType type
= 0;
325 static const GTypeInfo info
= {
326 sizeof (LttvTraceStatsClass
),
327 NULL
, /* base_init */
328 NULL
, /* base_finalize */
329 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
330 NULL
, /* class_finalize */
331 NULL
, /* class_data */
332 sizeof (LttvTraceStats
),
334 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
335 NULL
/* Value handling */
338 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
339 "LttvTraceStatsType", &info
, 0);
346 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
352 tracefile_stats_finalize (LttvTracefileStats
*self
)
354 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
355 finalize(G_OBJECT(self
));
360 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
362 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
364 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
369 lttv_tracefile_stats_get_type(void)
371 static GType type
= 0;
373 static const GTypeInfo info
= {
374 sizeof (LttvTracefileStatsClass
),
375 NULL
, /* base_init */
376 NULL
, /* base_finalize */
377 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
378 NULL
, /* class_finalize */
379 NULL
, /* class_data */
380 sizeof (LttvTracefileStats
),
382 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
383 NULL
/* Value handling */
386 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
387 "LttvTracefileStatsType", &info
, 0);
394 find_event_tree(LttvTracefileStats
*tfcs
,
399 LttvAttribute
**events_tree
,
400 LttvAttribute
**event_types_tree
)
404 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
405 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
406 a
= lttv_attribute_find_subdir(a
, pid_time
);
407 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
408 a
= lttv_attribute_find_subdir(a
, cpu
);
409 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
410 a
= lttv_attribute_find_subdir(a
, mode
);
411 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
412 a
= lttv_attribute_find_subdir(a
, sub_mode
);
414 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
415 *event_types_tree
= a
;
419 static void update_event_tree(LttvTracefileStats
*tfcs
)
421 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
422 guint cpu
= ltt_tracefile_num(tfcs
->parent
.parent
.tf
);
423 LttvProcessState
*process
= ts
->running_process
[cpu
];
424 LttvExecutionState
*es
= process
->state
;
426 find_event_tree(tfcs
, process
->pid_time
,
427 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
428 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
429 &(tfcs
->current_event_types_tree
));
433 static void mode_change(LttvTracefileStats
*tfcs
)
435 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
436 guint cpu
= ltt_tracefile_num(tfcs
->parent
.parent
.tf
);
437 LttvProcessState
*process
= ts
->running_process
[cpu
];
438 LttvAttributeValue cpu_time
;
442 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
443 LTTV_TIME
, &cpu_time
);
444 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
445 process
->state
->change
);
446 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
450 static void mode_end(LttvTracefileStats
*tfcs
)
452 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
453 guint cpu
= ltt_tracefile_num(tfcs
->parent
.parent
.tf
);
454 LttvProcessState
*process
= ts
->running_process
[cpu
];
455 LttvAttributeValue elapsed_time
, cpu_time
;
459 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
460 LTTV_TIME
, &elapsed_time
);
461 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
462 process
->state
->entry
);
463 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
465 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
466 LTTV_TIME
, &cpu_time
);
467 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
468 process
->state
->change
);
469 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
473 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
475 mode_change((LttvTracefileStats
*)call_data
);
480 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
482 update_event_tree((LttvTracefileStats
*)call_data
);
487 gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
489 mode_end((LttvTracefileStats
*)call_data
);
494 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
496 update_event_tree((LttvTracefileStats
*)call_data
);
501 gboolean
before_trap_entry(void *hook_data
, void *call_data
)
503 mode_change((LttvTracefileStats
*)call_data
);
508 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
510 update_event_tree((LttvTracefileStats
*)call_data
);
515 gboolean
before_trap_exit(void *hook_data
, void *call_data
)
517 mode_end((LttvTracefileStats
*)call_data
);
522 gboolean
after_trap_exit(void *hook_data
, void *call_data
)
524 update_event_tree((LttvTracefileStats
*)call_data
);
529 gboolean
before_irq_entry(void *hook_data
, void *call_data
)
531 mode_change((LttvTracefileStats
*)call_data
);
536 gboolean
after_irq_entry(void *hook_data
, void *call_data
)
538 update_event_tree((LttvTracefileStats
*)call_data
);
543 gboolean
before_irq_exit(void *hook_data
, void *call_data
)
545 mode_end((LttvTracefileStats
*)call_data
);
550 gboolean
after_irq_exit(void *hook_data
, void *call_data
)
552 update_event_tree((LttvTracefileStats
*)call_data
);
557 gboolean
before_schedchange(void *hook_data
, void *call_data
)
559 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
561 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
563 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
565 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
567 guint pid_in
, pid_out
;
571 LttvProcessState
*process
;
573 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
574 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
575 state_out
= ltt_event_get_int(e
, thf
->f3
);
577 /* compute the time for the process to schedule out */
581 /* get the information for the process scheduled in */
583 process
= lttv_state_find_process_or_create(ts
,
584 ANY_CPU
, pid_in
, &tfcs
->parent
.parent
.timestamp
);
586 find_event_tree(tfcs
, process
->pid_time
,
587 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
),
588 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
589 &(tfcs
->current_event_types_tree
));
591 /* compute the time waiting for the process to schedule in */
598 gboolean
process_fork(void *hook_data
, void *call_data
)
600 /* nothing to do for now */
605 gboolean
process_exit(void *hook_data
, void *call_data
)
607 /* We should probably exit all modes here or we could do that at
612 gboolean
process_free(void *hook_data
, void *call_data
)
617 gboolean
every_event(void *hook_data
, void *call_data
)
619 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
621 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
623 LttvAttributeValue v
;
625 /* The current branch corresponds to the tracefile/process/interrupt state.
626 Statistics are added within it, to count the number of events of this
627 type occuring in this context. A quark has been pre-allocated for each
628 event type and is used as name. */
630 lttv_attribute_find(tfcs
->current_event_types_tree
,
631 ltt_eventtype_name(ltt_event_eventtype(e
)),
639 lttv_stats_sum_trace(LttvTraceStats
*self
)
641 LttvAttribute
*sum_container
= self
->stats
;
643 LttvAttributeType type
;
645 LttvAttributeValue value
;
647 LttvAttributeName name
;
651 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
654 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
655 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
656 *submode_tree
, *event_types_tree
, *mode_events_tree
,
657 *cpu_events_tree
, *process_modes_tree
, *trace_cpu_tree
,
660 main_tree
= sum_container
;
662 lttv_attribute_find(sum_container
,
665 if(*(value
.v_uint
) != 0) return;
668 processes_tree
= lttv_attribute_find_subdir(main_tree
,
669 LTTV_STATS_PROCESSES
);
670 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
,
672 nb_process
= lttv_attribute_get_number(processes_tree
);
674 for(i
= 0 ; i
< nb_process
; i
++) {
675 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
);
676 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
678 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
679 process_modes_tree
= lttv_attribute_find_subdir(process_tree
,
681 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
683 for(j
= 0 ; j
< nb_cpu
; j
++) {
684 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
);
685 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
687 mode_types_tree
= lttv_attribute_find_subdir(cpu_tree
,
688 LTTV_STATS_MODE_TYPES
);
689 cpu_events_tree
= lttv_attribute_find_subdir(cpu_tree
,
691 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
692 trace_cpu_tree
= lttv_attribute_find_subdir(trace_cpu_tree
, name
);
693 nb_mode_type
= lttv_attribute_get_number(mode_types_tree
);
695 for(k
= 0 ; k
< nb_mode_type
; k
++) {
696 type
= lttv_attribute_get(mode_types_tree
, k
, &name
, &value
);
697 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
699 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
700 LTTV_STATS_SUBMODES
);
701 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
703 nb_submode
= lttv_attribute_get_number(submodes_tree
);
705 for(l
= 0 ; l
< nb_submode
; l
++) {
706 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
);
707 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
709 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
710 LTTV_STATS_EVENT_TYPES
);
711 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
714 for(m
= 0 ; m
< nb_event_type
; m
++) {
715 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
);
716 sum
+= *(value
.v_uint
);
718 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
720 *(value
.v_uint
) = sum
;
721 lttv_attribute_recursive_add(mode_events_tree
, submode_tree
);
723 lttv_attribute_recursive_add(cpu_events_tree
, mode_events_tree
);
725 lttv_attribute_recursive_add(process_modes_tree
, cpu_tree
);
726 lttv_attribute_recursive_add(trace_cpu_tree
, cpu_tree
);
728 lttv_attribute_recursive_add(trace_modes_tree
, process_modes_tree
);
733 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
735 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
740 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
742 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
743 LttvAttribute
*sum_container
= self
->stats
;
749 LttvAttribute
*main_tree
, *trace_modes_tree
, *traceset_modes_tree
;
751 LttvAttributeValue value
;
753 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
755 if(*(value
.v_uint
) != 0) return;
758 traceset_modes_tree
= lttv_attribute_find_subdir(sum_container
,
760 nb_trace
= lttv_traceset_number(traceset
);
762 for(i
= 0 ; i
< nb_trace
; i
++) {
763 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
764 lttv_stats_sum_trace(tcs
);
765 main_tree
= tcs
->stats
;
766 trace_modes_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_MODES
);
767 lttv_attribute_recursive_add(traceset_modes_tree
, trace_modes_tree
);
772 // Hook wrapper. call_data is a traceset context.
773 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
775 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
777 lttv_stats_add_event_hooks(tss
);
782 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
784 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
786 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
790 LttvTracefileStats
*tfs
;
792 GArray
*hooks
, *before_hooks
, *after_hooks
;
796 LttvTraceHookByFacility
*thf
;
798 LttvAttributeValue val
;
802 nb_trace
= lttv_traceset_number(traceset
);
803 for(i
= 0 ; i
< nb_trace
; i
++) {
804 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
806 /* Find the eventtype id for the following events and register the
807 associated by id hooks. */
809 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 7);
810 g_array_set_size(hooks
, 7);
812 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
813 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
814 LTT_FIELD_SYSCALL_ID
, 0, 0,
815 before_syscall_entry
, NULL
,
816 &g_array_index(hooks
, LttvTraceHook
, 0));
819 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
820 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
822 before_syscall_exit
, NULL
,
823 &g_array_index(hooks
, LttvTraceHook
, 1));
826 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
827 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
828 LTT_FIELD_TRAP_ID
, 0, 0,
829 before_trap_entry
, NULL
,
830 &g_array_index(hooks
, LttvTraceHook
, 2));
833 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
834 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
836 before_trap_exit
, NULL
,
837 &g_array_index(hooks
, LttvTraceHook
, 3));
840 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
841 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
842 LTT_FIELD_IRQ_ID
, 0, 0,
843 before_irq_entry
, NULL
,
844 &g_array_index(hooks
, LttvTraceHook
, 4));
847 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
848 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
850 before_irq_exit
, NULL
,
851 &g_array_index(hooks
, LttvTraceHook
, 5));
854 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
855 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
856 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
857 before_schedchange
, NULL
,
858 &g_array_index(hooks
, LttvTraceHook
, 6));
861 before_hooks
= hooks
;
863 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 9);
864 g_array_set_size(hooks
, 9);
866 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
867 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_ENTRY
,
868 LTT_FIELD_SYSCALL_ID
, 0, 0,
869 after_syscall_entry
, NULL
,
870 &g_array_index(hooks
, LttvTraceHook
, 0));
873 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
874 LTT_FACILITY_KERNEL
, LTT_EVENT_SYSCALL_EXIT
,
876 after_syscall_exit
, NULL
,
877 &g_array_index(hooks
, LttvTraceHook
, 1));
880 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
881 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
882 LTT_FIELD_TRAP_ID
, 0, 0,
883 after_trap_entry
, NULL
,
884 &g_array_index(hooks
, LttvTraceHook
, 2));
887 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
888 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
890 after_trap_exit
, NULL
,
891 &g_array_index(hooks
, LttvTraceHook
, 3));
894 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
895 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
896 LTT_FIELD_IRQ_ID
, 0, 0,
897 after_irq_entry
, NULL
,
898 &g_array_index(hooks
, LttvTraceHook
, 4));
901 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
902 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
904 after_irq_exit
, NULL
,
905 &g_array_index(hooks
, LttvTraceHook
, 5));
909 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
910 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
911 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
913 &g_array_index(hooks
, LttvTraceHook
, 6));
916 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
917 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
920 &g_array_index(hooks
, LttvTraceHook
, 7));
923 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
924 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
927 &g_array_index(hooks
, LttvTraceHook
, 8));
933 /* Add these hooks to each event_by_id hooks list */
935 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
937 for(j
= 0 ; j
< nb_tracefile
; j
++) {
938 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
939 LttvTracefileContext
*, j
));
940 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
943 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
944 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
945 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
946 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
948 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
951 LTTV_PRIO_STATS_BEFORE_STATE
);
954 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
955 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
956 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
957 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
959 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
962 LTTV_PRIO_STATS_AFTER_STATE
);
966 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
968 *(val
.v_pointer
) = before_hooks
;
969 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
971 *(val
.v_pointer
) = after_hooks
;
975 // Hook wrapper. call_data is a traceset context.
976 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
978 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
980 lttv_stats_remove_event_hooks(tss
);
985 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
987 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
989 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
993 LttvTracefileStats
*tfs
;
997 GArray
*before_hooks
, *after_hooks
;
1001 LttvTraceHookByFacility
*thf
;
1003 LttvAttributeValue val
;
1005 nb_trace
= lttv_traceset_number(traceset
);
1006 for(i
= 0 ; i
< nb_trace
; i
++) {
1007 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1008 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1009 LTTV_POINTER
, &val
);
1010 before_hooks
= *(val
.v_pointer
);
1011 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1012 LTTV_POINTER
, &val
);
1013 after_hooks
= *(val
.v_pointer
);
1015 /* Remove these hooks from each event_by_id hooks list */
1017 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1019 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1020 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1021 LttvTracefileContext
*, j
));
1022 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1025 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1026 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1027 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1028 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1029 lttv_hooks_remove_data(
1030 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1035 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1036 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1037 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1038 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1039 lttv_hooks_remove_data(
1040 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1046 g_debug("lttv_stats_remove_event_hooks()");
1047 g_array_free(before_hooks
, TRUE
);
1048 g_array_free(after_hooks
, TRUE
);
1053 static void module_init()
1055 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1056 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1057 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1058 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1059 LTTV_STATS_MODES
= g_quark_from_string("modes");
1060 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1061 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1062 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1063 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time");
1064 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1065 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1066 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1067 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1068 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1069 LTTV_STATS
= g_quark_from_string("statistics");
1070 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1071 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1074 static void module_destroy()
1079 LTTV_MODULE("stats", "Compute processes statistics", \
1080 "Accumulate statistics for event types, processes and CPUs", \
1081 module_init
, module_destroy
, "state");
1083 /* Change the places where stats are called (create/read/write stats)
1085 Check for options in batchtest.c to reduce writing and see what tests are
1086 best candidates for performance analysis. Once OK, commit, move to main
1087 and run tests. Update the gui for statistics. */