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>
34 #define MAX_64_HEX_STRING_LEN 19
37 LTTV_STATS_PROCESS_UNKNOWN
,
40 LTTV_STATS_MODE_TYPES
,
44 LTTV_STATS_EVENT_TYPES
,
46 LTTV_STATS_CUMULATIVE_CPU_TIME
,
47 LTTV_STATS_ELAPSED_TIME
,
49 LTTV_STATS_EVENTS_COUNT
,
52 LTTV_STATS_TRACEFILES
,
54 LTTV_STATS_BEFORE_HOOKS
,
55 LTTV_STATS_AFTER_HOOKS
;
58 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, guint cpu
,
60 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
61 LttvAttribute
**event_types_tree
);
64 static void lttv_stats_init(LttvTracesetStats
*self
)
66 guint i
, j
, nb_trace
, nb_tracefile
;
72 LttvTracefileContext
*tfc
;
74 LttvTracefileContext
**tfs
;
75 LttvTracefileStats
*tfcs
;
77 LttTime timestamp
= {0,0};
85 LttvTraceset
*ts
= self
->parent
.parent
.ts
;
87 self
->stats
= lttv_attribute_find_subdir(
88 lttv_traceset_attribute(self
->parent
.parent
.ts
),
90 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
95 if(*(v
.v_uint
) == 1) {
96 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
99 nb_trace
= lttv_traceset_number(ts
);
101 for(i
= 0 ; i
< nb_trace
; i
++) {
102 tc
= self
->parent
.parent
.traces
[i
];
103 tcs
= LTTV_TRACE_STATS(tc
);
105 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
106 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
107 LTTV_STATS_TRACEFILES
);
108 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
112 if(*(v
.v_uint
) == 1) {
113 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
116 nb_tracefile
= tc
->tracefiles
->len
;
118 for(j
= 0 ; j
< nb_tracefile
; j
++) {
119 tfs
= &g_array_index(tc
->tracefiles
,
120 LttvTracefileContext
*, j
);
121 tfcs
= LTTV_TRACEFILE_STATS(*tfs
);
122 tfcs
->stats
= lttv_attribute_find_subdir(tracefiles_stats
,
123 ltt_tracefile_long_name(tfcs
->parent
.parent
.tf
));
124 guint cpu
= tfcs
->parent
.cpu
;
125 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
128 LTTV_STATE_MODE_UNKNOWN
,
129 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
130 &tfcs
->current_event_types_tree
);
136 static void lttv_stats_fini(LttvTracesetStats
*self
)
138 guint i
, j
, nb_trace
, nb_tracefile
;
142 LttvTraceContext
*tc
;
146 LttvTracefileContext
*tfc
;
148 LttvTracefileStats
*tfcs
;
150 LttTime timestamp
= {0,0};
152 LttvAttributeValue v
;
154 LttvAttribute
*tracefiles_stats
;
156 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
160 if(*(v
.v_uint
) == 0) {
161 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
165 ts
= self
->parent
.parent
.ts
;
166 nb_trace
= lttv_traceset_number(ts
);
168 for(i
= 0 ; i
< nb_trace
; i
++) {
169 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
171 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
175 if(*(v
.v_uint
) == 0) {
176 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
177 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
178 LTTV_STATS_TRACEFILES
);
179 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
180 LTTV_STATS_TRACEFILES
);
184 nb_tracefile
= tc
->tracefiles
->len
;
186 for(j
= 0 ; j
< nb_tracefile
; j
++) {
187 tfc
= g_array_index(tc
->tracefiles
,
188 LttvTracefileContext
*, j
);
189 tfcs
= (LttvTracefileStats
*)tfc
;
191 tfcs
->current_events_tree
= NULL
;
192 tfcs
->current_event_types_tree
= NULL
;
198 void lttv_stats_reset(LttvTracesetStats
*self
)
200 lttv_stats_fini(self
);
201 lttv_stats_init(self
);
207 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
209 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
210 init((LttvTracesetContext
*)self
, ts
);
212 lttv_stats_init(self
);
217 fini(LttvTracesetStats
*self
)
219 lttv_stats_fini(self
);
221 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
222 fini((LttvTracesetContext
*)self
);
226 static LttvTracesetContext
*
227 new_traceset_context(LttvTracesetContext
*self
)
229 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
233 static LttvTraceContext
*
234 new_trace_context(LttvTracesetContext
*self
)
236 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
240 static LttvTracefileContext
*
241 new_tracefile_context(LttvTracesetContext
*self
)
243 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
248 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
254 traceset_stats_finalize (LttvTracesetStats
*self
)
256 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
257 finalize(G_OBJECT(self
));
262 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
264 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
266 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
267 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
268 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
269 klass
->new_traceset_context
= new_traceset_context
;
270 klass
->new_trace_context
= new_trace_context
;
271 klass
->new_tracefile_context
= new_tracefile_context
;
276 lttv_traceset_stats_get_type(void)
278 static GType type
= 0;
280 static const GTypeInfo info
= {
281 sizeof (LttvTracesetStatsClass
),
282 NULL
, /* base_init */
283 NULL
, /* base_finalize */
284 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
285 NULL
, /* class_finalize */
286 NULL
, /* class_data */
287 sizeof (LttvTracesetStats
),
289 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
290 NULL
/* Value handling */
293 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
294 "LttvTracesetStatsType",
302 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
308 trace_stats_finalize (LttvTraceStats
*self
)
310 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
311 finalize(G_OBJECT(self
));
316 trace_stats_class_init (LttvTraceContextClass
*klass
)
318 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
320 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
325 lttv_trace_stats_get_type(void)
327 static GType type
= 0;
329 static const GTypeInfo info
= {
330 sizeof (LttvTraceStatsClass
),
331 NULL
, /* base_init */
332 NULL
, /* base_finalize */
333 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
334 NULL
, /* class_finalize */
335 NULL
, /* class_data */
336 sizeof (LttvTraceStats
),
338 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
339 NULL
/* Value handling */
342 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
343 "LttvTraceStatsType", &info
, 0);
350 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
356 tracefile_stats_finalize (LttvTracefileStats
*self
)
358 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
359 finalize(G_OBJECT(self
));
364 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
366 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
368 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
373 lttv_tracefile_stats_get_type(void)
375 static GType type
= 0;
377 static const GTypeInfo info
= {
378 sizeof (LttvTracefileStatsClass
),
379 NULL
, /* base_init */
380 NULL
, /* base_finalize */
381 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
382 NULL
, /* class_finalize */
383 NULL
, /* class_data */
384 sizeof (LttvTracefileStats
),
386 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
387 NULL
/* Value handling */
390 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
391 "LttvTracefileStatsType", &info
, 0);
397 find_event_tree(LttvTracefileStats
*tfcs
,
403 LttvAttribute
**events_tree
,
404 LttvAttribute
**event_types_tree
)
406 LttvAttribute
*a
, *prev_a
;
407 gchar fstring
[MAX_64_HEX_STRING_LEN
];
410 ret
= snprintf(fstring
, MAX_64_HEX_STRING_LEN
-1,
411 "0x%llX", function
) > 0;
413 fstring
[MAX_64_HEX_STRING_LEN
-1] = '\0';
415 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
416 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
417 a
= lttv_attribute_find_subdir(a
, pid_time
);
418 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
419 a
= lttv_attribute_find_subdir_unnamed(a
, cpu
);
420 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_FUNCTIONS
);
421 a
= lttv_attribute_find_subdir(a
, g_quark_from_string(fstring
));
422 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
423 a
= lttv_attribute_find_subdir(a
, mode
);
424 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
425 a
= lttv_attribute_find_subdir(a
, sub_mode
);
427 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
428 *event_types_tree
= a
;
431 static void update_event_tree(LttvTracefileStats
*tfcs
)
433 guint cpu
= tfcs
->parent
.cpu
;
434 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
435 LttvProcessState
*process
= ts
->running_process
[cpu
];
436 LttvExecutionState
*es
= process
->state
;
438 find_event_tree(tfcs
, process
->pid_time
,
440 process
->current_function
,
441 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
442 &(tfcs
->current_event_types_tree
));
446 /* Update the trace event tree for the specified cpu */
447 static void update_trace_event_tree(LttvTraceStats
*tcs
)
449 LttvTracefileStats
*tfcs
;
450 LttvTraceContext
*tc
= (LttvTraceContext
*)tcs
;
451 guint j
, nb_tracefile
;
453 /* For each tracefile, update the event tree */
454 nb_tracefile
= tc
->tracefiles
->len
;
455 for(j
= 0; j
< nb_tracefile
; j
++) {
456 tfcs
= LTTV_TRACEFILE_STATS(g_array_index(tc
->tracefiles
,
457 LttvTracefileContext
*, j
));
458 update_event_tree(tfcs
);
462 static void mode_change(LttvTracefileStats
*tfcs
)
464 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
465 guint cpu
= tfcs
->parent
.cpu
;
466 LttvProcessState
*process
= ts
->running_process
[cpu
];
467 LttvAttributeValue cpu_time
, cum_cpu_time
;
471 if(process
->state
->s
== LTTV_STATE_RUN
&&
472 process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
)
473 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
474 process
->state
->change
);
476 delta
= ltt_time_zero
;
478 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
479 LTTV_TIME
, &cpu_time
);
480 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
482 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
486 /* Note : every mode_end must come with a cumulative cpu time update in the
488 static void mode_end(LttvTracefileStats
*tfcs
)
490 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
491 guint cpu
= tfcs
->parent
.cpu
;
492 LttvProcessState
*process
= ts
->running_process
[cpu
];
493 LttvAttributeValue elapsed_time
, cpu_time
, cum_cpu_time
;
497 /* FIXME put there in case of a missing update after a state modification */
498 //void *lasttree = tfcs->current_events_tree;
499 //update_event_tree(tfcs);
500 //g_assert (lasttree == tfcs->current_events_tree);
501 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
502 LTTV_TIME
, &elapsed_time
);
504 if(process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
) {
505 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
506 process
->state
->entry
);
508 delta
= ltt_time_zero
;
510 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
512 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
513 LTTV_TIME
, &cpu_time
);
515 /* if it is a running mode, we must count its cpu time */
516 if(process
->state
->s
== LTTV_STATE_RUN
&&
517 process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
)
518 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
519 process
->state
->change
);
521 delta
= ltt_time_zero
;
523 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
524 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
527 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CUMULATIVE_CPU_TIME
,
528 LTTV_TIME
, &cum_cpu_time
);
529 *(cum_cpu_time
.v_time
) = ltt_time_add(*(cum_cpu_time
.v_time
),
530 process
->state
->cum_cpu_time
);
534 static void after_mode_end(LttvTracefileStats
*tfcs
)
536 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
537 guint cpu
= tfcs
->parent
.cpu
;
538 LttvProcessState
*process
= ts
->running_process
[cpu
];
539 LttvAttributeValue cum_cpu_time
;
541 LttTime nested_delta
;
543 nested_delta
= process
->state
->cum_cpu_time
;
544 process
->state
->cum_cpu_time
= ltt_time_zero
; /* For after traceset hook */
546 update_event_tree(tfcs
);
548 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
552 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
554 mode_change((LttvTracefileStats
*)call_data
);
559 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
561 update_event_tree((LttvTracefileStats
*)call_data
);
566 static gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
568 mode_end((LttvTracefileStats
*)call_data
);
573 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
575 after_mode_end((LttvTracefileStats
*)call_data
);
580 static gboolean
before_trap_entry(void *hook_data
, void *call_data
)
582 mode_change((LttvTracefileStats
*)call_data
);
587 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
589 update_event_tree((LttvTracefileStats
*)call_data
);
594 static gboolean
before_trap_exit(void *hook_data
, void *call_data
)
596 mode_end((LttvTracefileStats
*)call_data
);
601 static gboolean
after_trap_exit(void *hook_data
, void *call_data
)
603 after_mode_end((LttvTracefileStats
*)call_data
);
608 static gboolean
before_irq_entry(void *hook_data
, void *call_data
)
610 mode_change((LttvTracefileStats
*)call_data
);
614 static gboolean
after_irq_entry(void *hook_data
, void *call_data
)
616 update_event_tree((LttvTracefileStats
*)call_data
);
621 static gboolean
before_irq_exit(void *hook_data
, void *call_data
)
623 mode_end((LttvTracefileStats
*)call_data
);
628 static gboolean
after_irq_exit(void *hook_data
, void *call_data
)
630 after_mode_end((LttvTracefileStats
*)call_data
);
635 static gboolean
before_soft_irq_entry(void *hook_data
, void *call_data
)
637 mode_change((LttvTracefileStats
*)call_data
);
641 static gboolean
after_soft_irq_entry(void *hook_data
, void *call_data
)
643 update_event_tree((LttvTracefileStats
*)call_data
);
647 static gboolean
before_soft_irq_exit(void *hook_data
, void *call_data
)
649 mode_end((LttvTracefileStats
*)call_data
);
654 static gboolean
after_soft_irq_exit(void *hook_data
, void *call_data
)
656 after_mode_end((LttvTracefileStats
*)call_data
);
660 static gboolean
before_function_entry(void *hook_data
, void *call_data
)
662 mode_change((LttvTracefileStats
*)call_data
);
666 static gboolean
after_function_entry(void *hook_data
, void *call_data
)
668 update_event_tree((LttvTracefileStats
*)call_data
);
672 static gboolean
before_function_exit(void *hook_data
, void *call_data
)
674 mode_end((LttvTracefileStats
*)call_data
);
678 static gboolean
after_function_exit(void *hook_data
, void *call_data
)
680 after_mode_end((LttvTracefileStats
*)call_data
);
685 static gboolean
before_schedchange(void *hook_data
, void *call_data
)
687 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
689 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
691 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
693 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
695 guint pid_in
, pid_out
;
699 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
700 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
701 state_out
= ltt_event_get_int(e
, thf
->f3
);
703 /* compute the time for the process to schedule out */
709 static gboolean
after_schedchange(void *hook_data
, void *call_data
)
711 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
713 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
715 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
717 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
719 guint pid_in
, pid_out
;
723 LttvProcessState
*process
;
725 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
726 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
727 state_out
= ltt_event_get_int(e
, thf
->f3
);
729 /* get the information for the process scheduled in */
730 guint cpu
= tfcs
->parent
.cpu
;
731 process
= ts
->running_process
[cpu
];
733 find_event_tree(tfcs
, process
->pid_time
,
735 process
->current_function
,
736 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
737 &(tfcs
->current_event_types_tree
));
739 /* compute the time waiting for the process to schedule in */
745 static gboolean
process_fork(void *hook_data
, void *call_data
)
750 static gboolean
process_exit(void *hook_data
, void *call_data
)
752 update_event_tree((LttvTracefileStats
*)call_data
);
756 static gboolean
before_enum_process_state(void *hook_data
, void *call_data
)
759 /* Broken : adds up time in the current process doing the dump */
760 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
762 after_mode_end(tfcs
);
768 static gboolean
after_enum_process_state(void *hook_data
, void *call_data
)
770 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
771 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfc
->t_context
;
772 update_trace_event_tree(tcs
);
776 static gboolean
after_statedump_end(void *hook_data
, void *call_data
)
778 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
779 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfc
->t_context
;
780 update_trace_event_tree(tcs
);
784 static gboolean
process_free(void *hook_data
, void *call_data
)
789 static gboolean
every_event(void *hook_data
, void *call_data
)
791 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
793 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
795 LttvAttributeValue v
;
797 /* The current branch corresponds to the tracefile/process/interrupt state.
798 Statistics are added within it, to count the number of events of this
799 type occuring in this context. A quark has been pre-allocated for each
800 event type and is used as name. */
802 lttv_attribute_find(tfcs
->current_event_types_tree
,
803 ltt_eventtype_name(ltt_event_eventtype(e
)),
809 static void lttv_stats_cleanup_process_state(LttvTraceState
*ts
,
810 LttvProcessState
*process
)
812 LttvTraceStats
*tcs
= (LttvTraceStats
*)ts
;
813 LttvTracesetContext
*tsc
= ts
->parent
.ts_context
;
815 LttvTracefileStats
**tfs
= (LttvTracefileStats
**)
816 &g_array_index(ts
->parent
.tracefiles
, LttvTracefileContext
*,
818 int cleanup_empty
= 0;
819 LttTime nested_delta
= ltt_time_zero
;
820 /* FIXME : ok, this is a hack. The time is infinite here :( */
821 LttTime save_time
= (*tfs
)->parent
.parent
.timestamp
;
823 ltt_trace_time_span_get(ts
->parent
.t
, &start
, &end
);
824 (*tfs
)->parent
.parent
.timestamp
= end
;
827 if(ltt_time_compare(process
->state
->cum_cpu_time
, ltt_time_zero
) != 0) {
828 find_event_tree(*tfs
, process
->pid_time
,
830 process
->current_function
,
831 process
->state
->t
, process
->state
->n
, &((*tfs
)->current_events_tree
),
832 &((*tfs
)->current_event_types_tree
));
834 nested_delta
= process
->state
->cum_cpu_time
;
836 cleanup_empty
= lttv_state_pop_state_cleanup(process
,
837 (LttvTracefileState
*)*tfs
);
838 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
841 } while(cleanup_empty
!= 1);
843 (*tfs
)->parent
.parent
.timestamp
= save_time
;
846 /* For each cpu, for each of their stacked states,
847 * perform sum of needed values. */
848 static void lttv_stats_cleanup_state(LttvTraceStats
*tcs
)
850 LttvTraceState
*ts
= (LttvTraceState
*)tcs
;
853 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
855 for(i
=0; i
<nb_cpus
; i
++) {
856 lttv_stats_cleanup_process_state(ts
, ts
->running_process
[i
]);
861 lttv_stats_sum_trace(LttvTraceStats
*self
, LttvAttribute
*ts_stats
)
863 LttvAttribute
*sum_container
= self
->stats
;
865 LttvAttributeType type
;
867 LttvAttributeValue value
;
869 LttvAttributeName name
;
877 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
878 nb_event_type
, nf
, nb_functions
;
880 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
881 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
882 *submode_tree
, *event_types_tree
, *mode_events_tree
,
885 *function_mode_types_tree
,
889 main_tree
= sum_container
;
891 lttv_attribute_find(sum_container
,
894 trace_is_summed
= *(value
.v_uint
);
897 /* First cleanup the state : sum all stalled information (never ending
900 lttv_stats_cleanup_state(self
);
902 processes_tree
= lttv_attribute_find_subdir(main_tree
,
903 LTTV_STATS_PROCESSES
);
904 nb_process
= lttv_attribute_get_number(processes_tree
);
906 for(i
= 0 ; i
< nb_process
; i
++) {
907 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
, &is_named
);
908 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
910 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
911 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
913 for(j
= 0 ; j
< nb_cpu
; j
++) {
914 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
, &is_named
);
915 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
917 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
918 trace_cpu_tree
= lttv_attribute_find_subdir_unnamed(trace_cpu_tree
, name
);
919 cpu_functions_tree
= lttv_attribute_find_subdir(cpu_tree
,
920 LTTV_STATS_FUNCTIONS
);
921 nb_functions
= lttv_attribute_get_number(cpu_functions_tree
);
923 for(nf
=0; nf
< nb_functions
; nf
++) {
924 type
= lttv_attribute_get(cpu_functions_tree
, nf
, &name
, &value
,
926 function_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
927 function_mode_types_tree
= lttv_attribute_find_subdir(function_tree
,
928 LTTV_STATS_MODE_TYPES
);
929 nb_mode_type
= lttv_attribute_get_number(function_mode_types_tree
);
930 for(k
= 0 ; k
< nb_mode_type
; k
++) {
931 type
= lttv_attribute_get(function_mode_types_tree
, k
, &name
, &value
,
933 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
935 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
936 LTTV_STATS_SUBMODES
);
937 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
939 mode_types_tree
= lttv_attribute_find_subdir(mode_tree
,
940 LTTV_STATS_MODE_TYPES
);
942 nb_submode
= lttv_attribute_get_number(submodes_tree
);
944 for(l
= 0 ; l
< nb_submode
; l
++) {
945 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
947 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
949 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
950 LTTV_STATS_EVENT_TYPES
);
951 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
954 for(m
= 0 ; m
< nb_event_type
; m
++) {
955 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
,
957 sum
+= *(value
.v_uint
);
959 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
961 *(value
.v_uint
) = sum
;
963 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
965 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
966 if(!trace_is_summed
) {
967 lttv_attribute_recursive_add(mode_events_tree
, event_types_tree
);
968 lttv_attribute_recursive_add(mode_types_tree
, submode_tree
);
971 if(!trace_is_summed
) {
972 lttv_attribute_recursive_add(function_tree
, mode_types_tree
);
975 if(!trace_is_summed
) {
976 lttv_attribute_recursive_add(cpu_tree
, function_tree
);
977 lttv_attribute_recursive_add(process_tree
, function_tree
);
978 lttv_attribute_recursive_add(trace_cpu_tree
, function_tree
);
979 lttv_attribute_recursive_add(main_tree
, function_tree
);
981 lttv_attribute_recursive_add(ts_stats
, function_tree
);
988 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
990 lttv_stats_sum_traceset((LttvTracesetStats
*)call_data
);
995 lttv_stats_sum_traceset(LttvTracesetStats
*self
)
997 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
998 LttvAttribute
*sum_container
= self
->stats
;
1000 LttvTraceStats
*tcs
;
1004 LttvAttribute
*main_tree
;
1006 LttvAttributeValue value
;
1008 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
1010 if(*(value
.v_uint
) != 0) return;
1011 *(value
.v_uint
) = 1;
1013 nb_trace
= lttv_traceset_number(traceset
);
1015 for(i
= 0 ; i
< nb_trace
; i
++) {
1016 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
1017 lttv_stats_sum_trace(tcs
, self
->stats
);
1018 // lttv_attribute_recursive_add(sum_container, tcs->stats);
1023 // Hook wrapper. call_data is a traceset context.
1024 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
1026 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1028 lttv_stats_add_event_hooks(tss
);
1033 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
1035 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1037 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1041 LttvTracefileStats
*tfs
;
1043 GArray
*hooks
, *before_hooks
, *after_hooks
;
1045 LttvTraceHook
*hook
;
1047 LttvTraceHookByFacility
*thf
;
1049 LttvAttributeValue val
;
1054 nb_trace
= lttv_traceset_number(traceset
);
1055 for(i
= 0 ; i
< nb_trace
; i
++) {
1056 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1058 /* Find the eventtype id for the following events and register the
1059 associated by id hooks. */
1061 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 12);
1062 g_array_set_size(hooks
, 12);
1065 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1066 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
1067 LTT_FIELD_SYSCALL_ID
, 0, 0,
1068 before_syscall_entry
, NULL
,
1069 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1072 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1073 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
1075 before_syscall_exit
, NULL
,
1076 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1079 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1080 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
1081 LTT_FIELD_TRAP_ID
, 0, 0,
1082 before_trap_entry
, NULL
,
1083 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1086 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1087 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1089 before_trap_exit
, NULL
,
1090 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1093 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1094 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1095 LTT_FIELD_IRQ_ID
, 0, 0,
1096 before_irq_entry
, NULL
,
1097 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1100 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1101 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1103 before_irq_exit
, NULL
,
1104 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1107 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1108 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
1109 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
1110 before_soft_irq_entry
, NULL
,
1111 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1114 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1115 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
1117 before_soft_irq_exit
, NULL
,
1118 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1121 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1122 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
1123 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
1124 before_schedchange
, NULL
,
1125 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1128 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1129 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
1130 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1131 before_function_entry
, NULL
,
1132 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1135 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1136 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
1137 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1138 before_function_exit
, NULL
,
1139 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1142 /* statedump-related hooks */
1143 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1144 LTT_FACILITY_STATEDUMP
, LTT_EVENT_ENUM_PROCESS_STATE
,
1145 LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
1146 before_enum_process_state
, NULL
,
1147 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1150 g_array_set_size(hooks
, hn
);
1152 before_hooks
= hooks
;
1154 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 16);
1155 g_array_set_size(hooks
, 16);
1158 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1159 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
1160 LTT_FIELD_SYSCALL_ID
, 0, 0,
1161 after_syscall_entry
, NULL
,
1162 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1165 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1166 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
1168 after_syscall_exit
, NULL
,
1169 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1172 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1173 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_ENTRY
,
1174 LTT_FIELD_TRAP_ID
, 0, 0,
1175 after_trap_entry
, NULL
,
1176 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1179 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1180 LTT_FACILITY_KERNEL
, LTT_EVENT_TRAP_EXIT
,
1182 after_trap_exit
, NULL
,
1183 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1186 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1187 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1188 LTT_FIELD_IRQ_ID
, 0, 0,
1189 after_irq_entry
, NULL
,
1190 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1193 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1194 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1196 after_irq_exit
, NULL
,
1197 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1200 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1201 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
1202 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
1203 after_irq_entry
, NULL
,
1204 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1207 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1208 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
1210 after_soft_irq_exit
, NULL
,
1211 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1214 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1215 LTT_FACILITY_PROCESS
, LTT_EVENT_SCHEDCHANGE
,
1216 LTT_FIELD_OUT
, LTT_FIELD_IN
, LTT_FIELD_OUT_STATE
,
1217 after_schedchange
, NULL
,
1218 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1221 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1222 LTT_FACILITY_PROCESS
, LTT_EVENT_FORK
,
1223 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1225 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1228 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1229 LTT_FACILITY_PROCESS
, LTT_EVENT_EXIT
,
1230 LTT_FIELD_PID
, 0, 0,
1232 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1235 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1236 LTT_FACILITY_PROCESS
, LTT_EVENT_FREE
,
1237 LTT_FIELD_PID
, 0, 0,
1239 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1242 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1243 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
1244 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1245 after_function_entry
, NULL
,
1246 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1249 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1250 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
1251 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1252 after_function_exit
, NULL
,
1253 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1256 /* statedump-related hooks */
1257 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1258 LTT_FACILITY_STATEDUMP
, LTT_EVENT_ENUM_PROCESS_STATE
,
1259 LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
1260 after_enum_process_state
, NULL
,
1261 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1264 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1265 LTT_FACILITY_STATEDUMP
, LTT_EVENT_STATEDUMP_END
,
1267 after_statedump_end
, NULL
,
1268 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1271 g_array_set_size(hooks
, hn
);
1273 after_hooks
= hooks
;
1275 /* Add these hooks to each event_by_id hooks list */
1277 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1279 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1280 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1281 LttvTracefileContext
*, j
));
1282 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
1285 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1286 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1287 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1288 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1290 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1293 LTTV_PRIO_STATS_BEFORE_STATE
);
1296 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1297 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1298 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1299 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1301 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1304 LTTV_PRIO_STATS_AFTER_STATE
);
1308 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1309 LTTV_POINTER
, &val
);
1310 *(val
.v_pointer
) = before_hooks
;
1311 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1312 LTTV_POINTER
, &val
);
1313 *(val
.v_pointer
) = after_hooks
;
1317 // Hook wrapper. call_data is a traceset context.
1318 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1320 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1322 lttv_stats_remove_event_hooks(tss
);
1327 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1329 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1331 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1335 LttvTracefileStats
*tfs
;
1339 GArray
*before_hooks
, *after_hooks
;
1341 LttvTraceHook
*hook
;
1343 LttvTraceHookByFacility
*thf
;
1345 LttvAttributeValue val
;
1347 nb_trace
= lttv_traceset_number(traceset
);
1348 for(i
= 0 ; i
< nb_trace
; i
++) {
1349 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1350 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1351 LTTV_POINTER
, &val
);
1352 before_hooks
= *(val
.v_pointer
);
1353 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1354 LTTV_POINTER
, &val
);
1355 after_hooks
= *(val
.v_pointer
);
1357 /* Remove these hooks from each event_by_id hooks list */
1359 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1361 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1362 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1363 LttvTracefileContext
*, j
));
1364 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1367 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1368 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1369 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1370 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1371 lttv_hooks_remove_data(
1372 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1377 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1378 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1379 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1380 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1381 lttv_hooks_remove_data(
1382 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1388 g_debug("lttv_stats_remove_event_hooks()");
1389 g_array_free(before_hooks
, TRUE
);
1390 g_array_free(after_hooks
, TRUE
);
1395 static void module_init()
1397 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1398 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1399 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1400 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1401 LTTV_STATS_MODES
= g_quark_from_string("modes");
1402 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1403 LTTV_STATS_FUNCTIONS
= g_quark_from_string("functions");
1404 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1405 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1406 LTTV_STATS_CUMULATIVE_CPU_TIME
= g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1407 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time (includes per process waiting time)");
1408 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1409 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1410 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1411 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1412 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1413 LTTV_STATS
= g_quark_from_string("statistics");
1414 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1415 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1418 static void module_destroy()
1423 LTTV_MODULE("stats", "Compute processes statistics", \
1424 "Accumulate statistics for event types, processes and CPUs", \
1425 module_init
, module_destroy
, "state");
1427 /* Change the places where stats are called (create/read/write stats)
1429 Check for options in batchtest.c to reduce writing and see what tests are
1430 best candidates for performance analysis. Once OK, commit, move to main
1431 and run tests. Update the gui for statistics. */