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_long_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_long_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 struct cleanup_state_struct
{
811 LttTime current_time
;
814 //static void lttv_stats_cleanup_process_state(LttvTraceState *ts,
815 // LttvProcessState *process, LttTime current_time)
816 static void lttv_stats_cleanup_process_state(gpointer key
, gpointer value
,
819 struct cleanup_state_struct
*cleanup_closure
=
820 (struct cleanup_state_struct
*)user_data
;
821 LttvTraceState
*ts
= cleanup_closure
->ts
;
822 LttvTraceStats
*tcs
= (LttvTraceStats
*)ts
;
823 LttvProcessState
*process
= (LttvProcessState
*)value
;
824 LttvTracesetContext
*tsc
= ts
->parent
.ts_context
;
825 LttTime current_time
= cleanup_closure
->current_time
;
827 LttvTracefileStats
**tfs
= (LttvTracefileStats
**)
828 &g_array_index(ts
->parent
.tracefiles
, LttvTracefileContext
*,
830 int cleanup_empty
= 0;
831 LttTime nested_delta
= ltt_time_zero
;
833 /* FIXME : ok, this is a hack. The time is infinite here :( */
834 //LttTime save_time = (*tfs)->parent.parent.timestamp;
835 //LttTime start, end;
836 //ltt_trace_time_span_get(ts->parent.t, &start, &end);
837 //(*tfs)->parent.parent.timestamp = end;
840 if(ltt_time_compare(process
->state
->cum_cpu_time
, ltt_time_zero
) != 0) {
841 find_event_tree(*tfs
, process
->pid_time
,
843 process
->current_function
,
844 process
->state
->t
, process
->state
->n
, &((*tfs
)->current_events_tree
),
845 &((*tfs
)->current_event_types_tree
));
846 /* Call mode_end only if not at end of trace */
847 if(ltt_time_compare(current_time
, ltt_time_infinite
) != 0)
849 nested_delta
= process
->state
->cum_cpu_time
;
851 cleanup_empty
= lttv_state_pop_state_cleanup(process
,
852 (LttvTracefileState
*)*tfs
);
853 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
856 } while(cleanup_empty
!= 1);
858 //(*tfs)->parent.parent.timestamp = save_time;
861 /* For each cpu, for each of their stacked states,
862 * perform sum of needed values. */
863 static void lttv_stats_cleanup_state(LttvTraceStats
*tcs
, LttTime current_time
)
865 LttvTraceState
*ts
= (LttvTraceState
*)tcs
;
866 struct cleanup_state_struct cleanup_closure
;
870 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
872 for(i
=0; i
<nb_cpus
; i
++) {
873 lttv_stats_cleanup_process_state(ts
, ts
->running_process
[i
], current_time
);
876 cleanup_closure
.ts
= tcs
;
877 cleanup_closure
.current_time
= current_time
;
878 g_hash_table_foreach(ts
->processes
, lttv_stats_cleanup_process_state
,
883 lttv_stats_sum_trace(LttvTraceStats
*self
, LttvAttribute
*ts_stats
,
884 LttTime current_time
)
886 LttvAttribute
*sum_container
= self
->stats
;
888 LttvAttributeType type
;
890 LttvAttributeValue value
;
892 LttvAttributeName name
;
900 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
901 nb_event_type
, nf
, nb_functions
;
903 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
904 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
905 *submode_tree
, *event_types_tree
, *mode_events_tree
,
908 *function_mode_types_tree
,
912 main_tree
= sum_container
;
914 lttv_attribute_find(sum_container
,
917 trace_is_summed
= *(value
.v_uint
);
920 /* First cleanup the state : sum all stalled information (never ending
923 lttv_stats_cleanup_state(self
, current_time
);
925 processes_tree
= lttv_attribute_find_subdir(main_tree
,
926 LTTV_STATS_PROCESSES
);
927 nb_process
= lttv_attribute_get_number(processes_tree
);
929 for(i
= 0 ; i
< nb_process
; i
++) {
930 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
, &is_named
);
931 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
933 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
934 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
936 for(j
= 0 ; j
< nb_cpu
; j
++) {
937 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
, &is_named
);
938 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
940 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
941 trace_cpu_tree
= lttv_attribute_find_subdir_unnamed(trace_cpu_tree
, name
);
942 cpu_functions_tree
= lttv_attribute_find_subdir(cpu_tree
,
943 LTTV_STATS_FUNCTIONS
);
944 nb_functions
= lttv_attribute_get_number(cpu_functions_tree
);
946 for(nf
=0; nf
< nb_functions
; nf
++) {
947 type
= lttv_attribute_get(cpu_functions_tree
, nf
, &name
, &value
,
949 function_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
950 function_mode_types_tree
= lttv_attribute_find_subdir(function_tree
,
951 LTTV_STATS_MODE_TYPES
);
952 nb_mode_type
= lttv_attribute_get_number(function_mode_types_tree
);
953 for(k
= 0 ; k
< nb_mode_type
; k
++) {
954 type
= lttv_attribute_get(function_mode_types_tree
, k
, &name
, &value
,
956 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
958 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
959 LTTV_STATS_SUBMODES
);
960 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
962 mode_types_tree
= lttv_attribute_find_subdir(mode_tree
,
963 LTTV_STATS_MODE_TYPES
);
965 nb_submode
= lttv_attribute_get_number(submodes_tree
);
967 for(l
= 0 ; l
< nb_submode
; l
++) {
968 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
970 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
972 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
973 LTTV_STATS_EVENT_TYPES
);
974 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
977 for(m
= 0 ; m
< nb_event_type
; m
++) {
978 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
,
980 sum
+= *(value
.v_uint
);
982 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
984 *(value
.v_uint
) = sum
;
986 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
988 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
989 if(!trace_is_summed
) {
990 lttv_attribute_recursive_add(mode_events_tree
, event_types_tree
);
991 lttv_attribute_recursive_add(mode_types_tree
, submode_tree
);
994 if(!trace_is_summed
) {
995 lttv_attribute_recursive_add(function_tree
, mode_types_tree
);
998 if(!trace_is_summed
) {
999 lttv_attribute_recursive_add(cpu_tree
, function_tree
);
1000 lttv_attribute_recursive_add(process_tree
, function_tree
);
1001 lttv_attribute_recursive_add(trace_cpu_tree
, function_tree
);
1002 lttv_attribute_recursive_add(main_tree
, function_tree
);
1004 lttv_attribute_recursive_add(ts_stats
, function_tree
);
1011 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
1013 struct sum_traceset_closure
*closure
=
1014 (struct sum_traceset_closure
*)call_data
;
1015 lttv_stats_sum_traceset(closure
->tss
, closure
->current_time
);
1020 lttv_stats_sum_traceset(LttvTracesetStats
*self
, LttTime current_time
)
1022 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1023 LttvAttribute
*sum_container
= self
->stats
;
1025 LttvTraceStats
*tcs
;
1029 LttvAttribute
*main_tree
;
1031 LttvAttributeValue value
;
1033 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
1035 if(*(value
.v_uint
) != 0) return;
1036 *(value
.v_uint
) = 1;
1038 nb_trace
= lttv_traceset_number(traceset
);
1040 for(i
= 0 ; i
< nb_trace
; i
++) {
1041 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
1042 lttv_stats_sum_trace(tcs
, self
->stats
, current_time
);
1043 // lttv_attribute_recursive_add(sum_container, tcs->stats);
1048 // Hook wrapper. call_data is a traceset context.
1049 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
1051 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1053 lttv_stats_add_event_hooks(tss
);
1058 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
1060 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1062 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1066 LttvTracefileStats
*tfs
;
1068 GArray
*hooks
, *before_hooks
, *after_hooks
;
1070 LttvTraceHook
*hook
;
1072 LttvTraceHookByFacility
*thf
;
1074 LttvAttributeValue val
;
1079 nb_trace
= lttv_traceset_number(traceset
);
1080 for(i
= 0 ; i
< nb_trace
; i
++) {
1081 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1083 /* Find the eventtype id for the following events and register the
1084 associated by id hooks. */
1086 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 12);
1087 g_array_set_size(hooks
, 12);
1090 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1091 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
1092 LTT_FIELD_SYSCALL_ID
, 0, 0,
1093 before_syscall_entry
, NULL
,
1094 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1097 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1098 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
1100 before_syscall_exit
, NULL
,
1101 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1104 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1105 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_ENTRY
,
1106 LTT_FIELD_TRAP_ID
, 0, 0,
1107 before_trap_entry
, NULL
,
1108 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1111 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1112 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_EXIT
,
1114 before_trap_exit
, NULL
,
1115 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1118 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1119 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1120 LTT_FIELD_IRQ_ID
, 0, 0,
1121 before_irq_entry
, NULL
,
1122 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1125 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1126 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1128 before_irq_exit
, NULL
,
1129 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1132 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1133 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
1134 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
1135 before_soft_irq_entry
, NULL
,
1136 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1139 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1140 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
1142 before_soft_irq_exit
, NULL
,
1143 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1146 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1147 LTT_FACILITY_KERNEL
, LTT_EVENT_SCHED_SCHEDULE
,
1148 LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
, LTT_FIELD_PREV_STATE
,
1149 before_schedchange
, NULL
,
1150 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1153 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1154 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
1155 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1156 before_function_entry
, NULL
,
1157 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1160 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1161 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
1162 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1163 before_function_exit
, NULL
,
1164 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1167 /* statedump-related hooks */
1168 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1169 LTT_FACILITY_LIST
, LTT_EVENT_PROCESS_STATE
,
1170 LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
1171 before_enum_process_state
, NULL
,
1172 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1175 g_array_set_size(hooks
, hn
);
1177 before_hooks
= hooks
;
1179 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 16);
1180 g_array_set_size(hooks
, 16);
1183 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1184 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
1185 LTT_FIELD_SYSCALL_ID
, 0, 0,
1186 after_syscall_entry
, NULL
,
1187 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1190 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1191 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
1193 after_syscall_exit
, NULL
,
1194 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1197 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1198 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_ENTRY
,
1199 LTT_FIELD_TRAP_ID
, 0, 0,
1200 after_trap_entry
, NULL
,
1201 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1204 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1205 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_EXIT
,
1207 after_trap_exit
, NULL
,
1208 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1211 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1212 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1213 LTT_FIELD_IRQ_ID
, 0, 0,
1214 after_irq_entry
, NULL
,
1215 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1218 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1219 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1221 after_irq_exit
, NULL
,
1222 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1225 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1226 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
1227 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
1228 after_irq_entry
, NULL
,
1229 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1232 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1233 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
1235 after_soft_irq_exit
, NULL
,
1236 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1239 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1240 LTT_FACILITY_KERNEL
, LTT_EVENT_SCHED_SCHEDULE
,
1241 LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
, LTT_FIELD_PREV_STATE
,
1242 after_schedchange
, NULL
,
1243 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1246 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1247 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_FORK
,
1248 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1250 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1253 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1254 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_EXIT
,
1255 LTT_FIELD_PID
, 0, 0,
1257 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1260 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1261 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_FREE
,
1262 LTT_FIELD_PID
, 0, 0,
1264 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1267 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1268 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
1269 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1270 after_function_entry
, NULL
,
1271 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1274 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1275 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
1276 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1277 after_function_exit
, NULL
,
1278 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1281 /* statedump-related hooks */
1282 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1283 LTT_FACILITY_LIST
, LTT_EVENT_PROCESS_STATE
,
1284 LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
1285 after_enum_process_state
, NULL
,
1286 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1289 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1290 LTT_FACILITY_LIST
, LTT_EVENT_STATEDUMP_END
,
1292 after_statedump_end
, NULL
,
1293 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1296 g_array_set_size(hooks
, hn
);
1298 after_hooks
= hooks
;
1300 /* Add these hooks to each event_by_id hooks list */
1302 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1304 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1305 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1306 LttvTracefileContext
*, j
));
1307 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
1310 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1311 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1312 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1313 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1315 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1318 LTTV_PRIO_STATS_BEFORE_STATE
);
1321 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1322 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1323 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1324 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1326 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1329 LTTV_PRIO_STATS_AFTER_STATE
);
1333 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1334 LTTV_POINTER
, &val
);
1335 *(val
.v_pointer
) = before_hooks
;
1336 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1337 LTTV_POINTER
, &val
);
1338 *(val
.v_pointer
) = after_hooks
;
1342 // Hook wrapper. call_data is a traceset context.
1343 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1345 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1347 lttv_stats_remove_event_hooks(tss
);
1352 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1354 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1356 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1360 LttvTracefileStats
*tfs
;
1364 GArray
*before_hooks
, *after_hooks
;
1366 LttvTraceHook
*hook
;
1368 LttvTraceHookByFacility
*thf
;
1370 LttvAttributeValue val
;
1372 nb_trace
= lttv_traceset_number(traceset
);
1373 for(i
= 0 ; i
< nb_trace
; i
++) {
1374 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1375 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1376 LTTV_POINTER
, &val
);
1377 before_hooks
= *(val
.v_pointer
);
1378 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1379 LTTV_POINTER
, &val
);
1380 after_hooks
= *(val
.v_pointer
);
1382 /* Remove these hooks from each event_by_id hooks list */
1384 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1386 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1387 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1388 LttvTracefileContext
*, j
));
1389 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1392 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1393 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1394 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1395 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1396 lttv_hooks_remove_data(
1397 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1402 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1403 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1404 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1405 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1406 lttv_hooks_remove_data(
1407 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1413 g_debug("lttv_stats_remove_event_hooks()");
1414 g_array_free(before_hooks
, TRUE
);
1415 g_array_free(after_hooks
, TRUE
);
1420 static void module_init()
1422 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1423 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1424 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1425 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1426 LTTV_STATS_MODES
= g_quark_from_string("modes");
1427 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1428 LTTV_STATS_FUNCTIONS
= g_quark_from_string("functions");
1429 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1430 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1431 LTTV_STATS_CUMULATIVE_CPU_TIME
= g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1432 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time (includes per process waiting time)");
1433 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1434 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1435 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1436 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1437 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1438 LTTV_STATS
= g_quark_from_string("statistics");
1439 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1440 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1443 static void module_destroy()
1448 LTTV_MODULE("stats", "Compute processes statistics", \
1449 "Accumulate statistics for event types, processes and CPUs", \
1450 module_init
, module_destroy
, "state");
1452 /* Change the places where stats are called (create/read/write stats)
1454 Check for options in batchtest.c to reduce writing and see what tests are
1455 best candidates for performance analysis. Once OK, commit, move to main
1456 and run tests. Update the gui for statistics. */