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/trace.h>
29 #include <ltt/event.h>
32 #define MAX_64_HEX_STRING_LEN 19
35 LTTV_STATS_PROCESS_UNKNOWN
,
38 LTTV_STATS_MODE_TYPES
,
42 LTTV_STATS_EVENT_TYPES
,
44 LTTV_STATS_CUMULATIVE_CPU_TIME
,
45 LTTV_STATS_ELAPSED_TIME
,
47 LTTV_STATS_EVENTS_COUNT
,
50 LTTV_STATS_TRACEFILES
,
52 LTTV_STATS_BEFORE_HOOKS
,
53 LTTV_STATS_AFTER_HOOKS
;
56 find_event_tree(LttvTracefileStats
*tfcs
, GQuark pid_time
, guint 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 guint cpu
= tfcs
->parent
.cpu
;
123 find_event_tree(tfcs
, LTTV_STATS_PROCESS_UNKNOWN
,
126 LTTV_STATE_MODE_UNKNOWN
,
127 LTTV_STATE_SUBMODE_UNKNOWN
, &tfcs
->current_events_tree
,
128 &tfcs
->current_event_types_tree
);
134 static void lttv_stats_fini(LttvTracesetStats
*self
)
136 guint i
, j
, nb_trace
, nb_tracefile
;
140 LttvTraceContext
*tc
;
144 LttvTracefileContext
*tfc
;
146 LttvTracefileStats
*tfcs
;
148 LttTime timestamp
= {0,0};
150 LttvAttributeValue v
;
152 LttvAttribute
*tracefiles_stats
;
154 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
158 if(*(v
.v_uint
) == 0) {
159 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
163 ts
= self
->parent
.parent
.ts
;
164 nb_trace
= lttv_traceset_number(ts
);
166 for(i
= 0 ; i
< nb_trace
; i
++) {
167 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
169 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
173 if(*(v
.v_uint
) == 0) {
174 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,LTTV_STATS
);
175 tracefiles_stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
176 LTTV_STATS_TRACEFILES
);
177 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
,
178 LTTV_STATS_TRACEFILES
);
182 nb_tracefile
= tc
->tracefiles
->len
;
184 for(j
= 0 ; j
< nb_tracefile
; j
++) {
185 tfc
= g_array_index(tc
->tracefiles
,
186 LttvTracefileContext
*, j
);
187 tfcs
= (LttvTracefileStats
*)tfc
;
189 tfcs
->current_events_tree
= NULL
;
190 tfcs
->current_event_types_tree
= NULL
;
196 void lttv_stats_reset(LttvTracesetStats
*self
)
198 lttv_stats_fini(self
);
199 lttv_stats_init(self
);
205 init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
207 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
208 init((LttvTracesetContext
*)self
, ts
);
210 lttv_stats_init(self
);
215 fini(LttvTracesetStats
*self
)
217 lttv_stats_fini(self
);
219 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
220 fini((LttvTracesetContext
*)self
);
224 static LttvTracesetContext
*
225 new_traceset_context(LttvTracesetContext
*self
)
227 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
231 static LttvTraceContext
*
232 new_trace_context(LttvTracesetContext
*self
)
234 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
238 static LttvTracefileContext
*
239 new_tracefile_context(LttvTracesetContext
*self
)
241 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
246 traceset_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
252 traceset_stats_finalize (LttvTracesetStats
*self
)
254 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
255 finalize(G_OBJECT(self
));
260 traceset_stats_class_init (LttvTracesetContextClass
*klass
)
262 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
264 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
265 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
266 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
267 klass
->new_traceset_context
= new_traceset_context
;
268 klass
->new_trace_context
= new_trace_context
;
269 klass
->new_tracefile_context
= new_tracefile_context
;
274 lttv_traceset_stats_get_type(void)
276 static GType type
= 0;
278 static const GTypeInfo info
= {
279 sizeof (LttvTracesetStatsClass
),
280 NULL
, /* base_init */
281 NULL
, /* base_finalize */
282 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
283 NULL
, /* class_finalize */
284 NULL
, /* class_data */
285 sizeof (LttvTracesetStats
),
287 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
288 NULL
/* Value handling */
291 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
292 "LttvTracesetStatsType",
300 trace_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
306 trace_stats_finalize (LttvTraceStats
*self
)
308 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
309 finalize(G_OBJECT(self
));
314 trace_stats_class_init (LttvTraceContextClass
*klass
)
316 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
318 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
323 lttv_trace_stats_get_type(void)
325 static GType type
= 0;
327 static const GTypeInfo info
= {
328 sizeof (LttvTraceStatsClass
),
329 NULL
, /* base_init */
330 NULL
, /* base_finalize */
331 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
332 NULL
, /* class_finalize */
333 NULL
, /* class_data */
334 sizeof (LttvTraceStats
),
336 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
337 NULL
/* Value handling */
340 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
341 "LttvTraceStatsType", &info
, 0);
348 tracefile_stats_instance_init (GTypeInstance
*instance
, gpointer g_class
)
354 tracefile_stats_finalize (LttvTracefileStats
*self
)
356 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
357 finalize(G_OBJECT(self
));
362 tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
364 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
366 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
371 lttv_tracefile_stats_get_type(void)
373 static GType type
= 0;
375 static const GTypeInfo info
= {
376 sizeof (LttvTracefileStatsClass
),
377 NULL
, /* base_init */
378 NULL
, /* base_finalize */
379 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
380 NULL
, /* class_finalize */
381 NULL
, /* class_data */
382 sizeof (LttvTracefileStats
),
384 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
385 NULL
/* Value handling */
388 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
389 "LttvTracefileStatsType", &info
, 0);
395 find_event_tree(LttvTracefileStats
*tfcs
,
401 LttvAttribute
**events_tree
,
402 LttvAttribute
**event_types_tree
)
404 LttvAttribute
*a
, *prev_a
;
405 gchar fstring
[MAX_64_HEX_STRING_LEN
];
408 ret
= snprintf(fstring
, MAX_64_HEX_STRING_LEN
-1,
409 "0x%llX", function
) > 0;
411 fstring
[MAX_64_HEX_STRING_LEN
-1] = '\0';
413 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfcs
->parent
.parent
.t_context
;
414 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
415 a
= lttv_attribute_find_subdir(a
, pid_time
);
416 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
417 a
= lttv_attribute_find_subdir_unnamed(a
, cpu
);
418 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_FUNCTIONS
);
419 a
= lttv_attribute_find_subdir(a
, g_quark_from_string(fstring
));
420 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
421 a
= lttv_attribute_find_subdir(a
, mode
);
422 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
423 a
= lttv_attribute_find_subdir(a
, sub_mode
);
425 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
426 *event_types_tree
= a
;
429 static void update_event_tree(LttvTracefileStats
*tfcs
)
431 guint cpu
= tfcs
->parent
.cpu
;
432 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
433 LttvProcessState
*process
= ts
->running_process
[cpu
];
434 LttvExecutionState
*es
= process
->state
;
436 find_event_tree(tfcs
, process
->pid_time
,
438 process
->current_function
,
439 es
->t
, es
->n
, &(tfcs
->current_events_tree
),
440 &(tfcs
->current_event_types_tree
));
444 /* Update the trace event tree for the specified cpu */
445 static void update_trace_event_tree(LttvTraceStats
*tcs
)
447 LttvTracefileStats
*tfcs
;
448 LttvTraceContext
*tc
= (LttvTraceContext
*)tcs
;
449 guint j
, nb_tracefile
;
451 /* For each tracefile, update the event tree */
452 nb_tracefile
= tc
->tracefiles
->len
;
453 for(j
= 0; j
< nb_tracefile
; j
++) {
454 tfcs
= LTTV_TRACEFILE_STATS(g_array_index(tc
->tracefiles
,
455 LttvTracefileContext
*, j
));
456 update_event_tree(tfcs
);
460 static void mode_change(LttvTracefileStats
*tfcs
)
462 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
463 guint cpu
= tfcs
->parent
.cpu
;
464 LttvProcessState
*process
= ts
->running_process
[cpu
];
465 LttvAttributeValue cpu_time
, cum_cpu_time
;
469 if(process
->state
->s
== LTTV_STATE_RUN
&&
470 process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
)
471 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
472 process
->state
->change
);
474 delta
= ltt_time_zero
;
476 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
477 LTTV_TIME
, &cpu_time
);
478 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
480 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
484 /* Note : every mode_end must come with a cumulative cpu time update in the
486 static void mode_end(LttvTracefileStats
*tfcs
)
488 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
489 guint cpu
= tfcs
->parent
.cpu
;
490 LttvProcessState
*process
= ts
->running_process
[cpu
];
491 LttvAttributeValue elapsed_time
, cpu_time
, cum_cpu_time
;
495 /* FIXME put there in case of a missing update after a state modification */
496 //void *lasttree = tfcs->current_events_tree;
497 //update_event_tree(tfcs);
498 //g_assert (lasttree == tfcs->current_events_tree);
499 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
500 LTTV_TIME
, &elapsed_time
);
502 if(process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
) {
503 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
504 process
->state
->entry
);
506 delta
= ltt_time_zero
;
508 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
510 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CPU_TIME
,
511 LTTV_TIME
, &cpu_time
);
513 /* if it is a running mode, we must count its cpu time */
514 if(process
->state
->s
== LTTV_STATE_RUN
&&
515 process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
)
516 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
517 process
->state
->change
);
519 delta
= ltt_time_zero
;
521 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
522 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
525 lttv_attribute_find(tfcs
->current_events_tree
, LTTV_STATS_CUMULATIVE_CPU_TIME
,
526 LTTV_TIME
, &cum_cpu_time
);
527 *(cum_cpu_time
.v_time
) = ltt_time_add(*(cum_cpu_time
.v_time
),
528 process
->state
->cum_cpu_time
);
532 static void after_mode_end(LttvTracefileStats
*tfcs
)
534 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
535 guint cpu
= tfcs
->parent
.cpu
;
536 LttvProcessState
*process
= ts
->running_process
[cpu
];
537 LttvAttributeValue cum_cpu_time
;
539 LttTime nested_delta
;
541 nested_delta
= process
->state
->cum_cpu_time
;
542 process
->state
->cum_cpu_time
= ltt_time_zero
; /* For after traceset hook */
544 update_event_tree(tfcs
);
546 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
550 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
552 mode_change((LttvTracefileStats
*)call_data
);
557 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
559 update_event_tree((LttvTracefileStats
*)call_data
);
564 static gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
566 mode_end((LttvTracefileStats
*)call_data
);
571 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
573 after_mode_end((LttvTracefileStats
*)call_data
);
578 static gboolean
before_trap_entry(void *hook_data
, void *call_data
)
580 mode_change((LttvTracefileStats
*)call_data
);
585 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
587 update_event_tree((LttvTracefileStats
*)call_data
);
592 static gboolean
before_trap_exit(void *hook_data
, void *call_data
)
594 mode_end((LttvTracefileStats
*)call_data
);
599 static gboolean
after_trap_exit(void *hook_data
, void *call_data
)
601 after_mode_end((LttvTracefileStats
*)call_data
);
606 static gboolean
before_irq_entry(void *hook_data
, void *call_data
)
608 mode_change((LttvTracefileStats
*)call_data
);
612 static gboolean
after_irq_entry(void *hook_data
, void *call_data
)
614 update_event_tree((LttvTracefileStats
*)call_data
);
619 static gboolean
before_irq_exit(void *hook_data
, void *call_data
)
621 mode_end((LttvTracefileStats
*)call_data
);
626 static gboolean
after_irq_exit(void *hook_data
, void *call_data
)
628 after_mode_end((LttvTracefileStats
*)call_data
);
633 static gboolean
before_soft_irq_entry(void *hook_data
, void *call_data
)
635 mode_change((LttvTracefileStats
*)call_data
);
639 static gboolean
after_soft_irq_entry(void *hook_data
, void *call_data
)
641 update_event_tree((LttvTracefileStats
*)call_data
);
645 static gboolean
before_soft_irq_exit(void *hook_data
, void *call_data
)
647 mode_end((LttvTracefileStats
*)call_data
);
652 static gboolean
after_soft_irq_exit(void *hook_data
, void *call_data
)
654 after_mode_end((LttvTracefileStats
*)call_data
);
658 static gboolean
before_function_entry(void *hook_data
, void *call_data
)
660 mode_change((LttvTracefileStats
*)call_data
);
664 static gboolean
after_function_entry(void *hook_data
, void *call_data
)
666 update_event_tree((LttvTracefileStats
*)call_data
);
670 static gboolean
before_function_exit(void *hook_data
, void *call_data
)
672 mode_end((LttvTracefileStats
*)call_data
);
676 static gboolean
after_function_exit(void *hook_data
, void *call_data
)
678 after_mode_end((LttvTracefileStats
*)call_data
);
683 static gboolean
before_schedchange(void *hook_data
, void *call_data
)
685 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
687 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
689 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
691 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
693 guint pid_in
, pid_out
;
697 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
698 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
699 state_out
= ltt_event_get_long_int(e
, thf
->f3
);
701 /* compute the time for the process to schedule out */
707 static gboolean
after_schedchange(void *hook_data
, void *call_data
)
709 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
711 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
713 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
715 LttvTraceHookByFacility
*thf
= (LttvTraceHookByFacility
*)hook_data
;
717 guint pid_in
, pid_out
;
721 LttvProcessState
*process
;
723 pid_out
= ltt_event_get_unsigned(e
, thf
->f1
);
724 pid_in
= ltt_event_get_unsigned(e
, thf
->f2
);
725 state_out
= ltt_event_get_long_int(e
, thf
->f3
);
727 /* get the information for the process scheduled in */
728 guint cpu
= tfcs
->parent
.cpu
;
729 process
= ts
->running_process
[cpu
];
731 find_event_tree(tfcs
, process
->pid_time
,
733 process
->current_function
,
734 process
->state
->t
, process
->state
->n
, &(tfcs
->current_events_tree
),
735 &(tfcs
->current_event_types_tree
));
737 /* compute the time waiting for the process to schedule in */
743 static gboolean
process_fork(void *hook_data
, void *call_data
)
748 static gboolean
process_exit(void *hook_data
, void *call_data
)
750 update_event_tree((LttvTracefileStats
*)call_data
);
754 static gboolean
before_enum_process_state(void *hook_data
, void *call_data
)
757 /* Broken : adds up time in the current process doing the dump */
758 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
760 after_mode_end(tfcs
);
766 static gboolean
after_enum_process_state(void *hook_data
, void *call_data
)
768 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
769 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfc
->t_context
;
770 update_trace_event_tree(tcs
);
774 static gboolean
after_statedump_end(void *hook_data
, void *call_data
)
776 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
777 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfc
->t_context
;
778 update_trace_event_tree(tcs
);
782 static gboolean
process_free(void *hook_data
, void *call_data
)
787 static gboolean
every_event(void *hook_data
, void *call_data
)
789 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
791 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
793 LttvAttributeValue v
;
795 /* The current branch corresponds to the tracefile/process/interrupt state.
796 Statistics are added within it, to count the number of events of this
797 type occuring in this context. A quark has been pre-allocated for each
798 event type and is used as name. */
800 lttv_attribute_find(tfcs
->current_event_types_tree
,
801 ltt_eventtype_name(ltt_event_eventtype(e
)),
807 struct cleanup_state_struct
{
809 LttTime current_time
;
812 //static void lttv_stats_cleanup_process_state(LttvTraceState *ts,
813 // LttvProcessState *process, LttTime current_time)
814 static void lttv_stats_cleanup_process_state(gpointer key
, gpointer value
,
817 struct cleanup_state_struct
*cleanup_closure
=
818 (struct cleanup_state_struct
*)user_data
;
819 LttvTraceState
*ts
= cleanup_closure
->ts
;
820 LttvTraceStats
*tcs
= (LttvTraceStats
*)ts
;
821 LttvProcessState
*process
= (LttvProcessState
*)value
;
822 LttvTracesetContext
*tsc
= ts
->parent
.ts_context
;
823 LttTime current_time
= cleanup_closure
->current_time
;
825 LttvTracefileStats
**tfs
= (LttvTracefileStats
**)
826 &g_array_index(ts
->parent
.tracefiles
, LttvTracefileContext
*,
828 int cleanup_empty
= 0;
829 LttTime nested_delta
= ltt_time_zero
;
831 /* FIXME : ok, this is a hack. The time is infinite here :( */
832 //LttTime save_time = (*tfs)->parent.parent.timestamp;
833 //LttTime start, end;
834 //ltt_trace_time_span_get(ts->parent.t, &start, &end);
835 //(*tfs)->parent.parent.timestamp = end;
838 if(ltt_time_compare(process
->state
->cum_cpu_time
, ltt_time_zero
) != 0) {
839 find_event_tree(*tfs
, process
->pid_time
,
841 process
->current_function
,
842 process
->state
->t
, process
->state
->n
, &((*tfs
)->current_events_tree
),
843 &((*tfs
)->current_event_types_tree
));
844 /* Call mode_end only if not at end of trace */
845 if(ltt_time_compare(current_time
, ltt_time_infinite
) != 0)
847 nested_delta
= process
->state
->cum_cpu_time
;
849 cleanup_empty
= lttv_state_pop_state_cleanup(process
,
850 (LttvTracefileState
*)*tfs
);
851 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
854 } while(cleanup_empty
!= 1);
856 //(*tfs)->parent.parent.timestamp = save_time;
859 /* For each cpu, for each of their stacked states,
860 * perform sum of needed values. */
861 static void lttv_stats_cleanup_state(LttvTraceStats
*tcs
, LttTime current_time
)
863 LttvTraceState
*ts
= (LttvTraceState
*)tcs
;
864 struct cleanup_state_struct cleanup_closure
;
868 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
870 for(i
=0; i
<nb_cpus
; i
++) {
871 lttv_stats_cleanup_process_state(ts
, ts
->running_process
[i
], current_time
);
874 cleanup_closure
.ts
= tcs
;
875 cleanup_closure
.current_time
= current_time
;
876 g_hash_table_foreach(ts
->processes
, lttv_stats_cleanup_process_state
,
881 lttv_stats_sum_trace(LttvTraceStats
*self
, LttvAttribute
*ts_stats
,
882 LttTime current_time
)
884 LttvAttribute
*sum_container
= self
->stats
;
886 LttvAttributeType type
;
888 LttvAttributeValue value
;
890 LttvAttributeName name
;
898 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
899 nb_event_type
, nf
, nb_functions
;
901 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
902 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
903 *submode_tree
, *event_types_tree
, *mode_events_tree
,
906 *function_mode_types_tree
,
910 main_tree
= sum_container
;
912 lttv_attribute_find(sum_container
,
915 trace_is_summed
= *(value
.v_uint
);
918 /* First cleanup the state : sum all stalled information (never ending
921 lttv_stats_cleanup_state(self
, current_time
);
923 processes_tree
= lttv_attribute_find_subdir(main_tree
,
924 LTTV_STATS_PROCESSES
);
925 nb_process
= lttv_attribute_get_number(processes_tree
);
927 for(i
= 0 ; i
< nb_process
; i
++) {
928 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
, &is_named
);
929 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
931 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
932 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
934 for(j
= 0 ; j
< nb_cpu
; j
++) {
935 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
, &is_named
);
936 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
938 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
, LTTV_STATS_CPU
);
939 trace_cpu_tree
= lttv_attribute_find_subdir_unnamed(trace_cpu_tree
, name
);
940 cpu_functions_tree
= lttv_attribute_find_subdir(cpu_tree
,
941 LTTV_STATS_FUNCTIONS
);
942 nb_functions
= lttv_attribute_get_number(cpu_functions_tree
);
944 for(nf
=0; nf
< nb_functions
; nf
++) {
945 type
= lttv_attribute_get(cpu_functions_tree
, nf
, &name
, &value
,
947 function_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
948 function_mode_types_tree
= lttv_attribute_find_subdir(function_tree
,
949 LTTV_STATS_MODE_TYPES
);
950 nb_mode_type
= lttv_attribute_get_number(function_mode_types_tree
);
951 for(k
= 0 ; k
< nb_mode_type
; k
++) {
952 type
= lttv_attribute_get(function_mode_types_tree
, k
, &name
, &value
,
954 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
956 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
957 LTTV_STATS_SUBMODES
);
958 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
960 mode_types_tree
= lttv_attribute_find_subdir(mode_tree
,
961 LTTV_STATS_MODE_TYPES
);
963 nb_submode
= lttv_attribute_get_number(submodes_tree
);
965 for(l
= 0 ; l
< nb_submode
; l
++) {
966 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
968 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
970 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
971 LTTV_STATS_EVENT_TYPES
);
972 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
975 for(m
= 0 ; m
< nb_event_type
; m
++) {
976 type
= lttv_attribute_get(event_types_tree
, m
, &name
, &value
,
978 sum
+= *(value
.v_uint
);
980 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
982 *(value
.v_uint
) = sum
;
984 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
986 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
987 if(!trace_is_summed
) {
988 lttv_attribute_recursive_add(mode_events_tree
, event_types_tree
);
989 lttv_attribute_recursive_add(mode_types_tree
, submode_tree
);
992 if(!trace_is_summed
) {
993 lttv_attribute_recursive_add(function_tree
, mode_types_tree
);
996 if(!trace_is_summed
) {
997 lttv_attribute_recursive_add(cpu_tree
, function_tree
);
998 lttv_attribute_recursive_add(process_tree
, function_tree
);
999 lttv_attribute_recursive_add(trace_cpu_tree
, function_tree
);
1000 lttv_attribute_recursive_add(main_tree
, function_tree
);
1002 lttv_attribute_recursive_add(ts_stats
, function_tree
);
1009 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
1011 struct sum_traceset_closure
*closure
=
1012 (struct sum_traceset_closure
*)call_data
;
1013 lttv_stats_sum_traceset(closure
->tss
, closure
->current_time
);
1018 lttv_stats_sum_traceset(LttvTracesetStats
*self
, LttTime current_time
)
1020 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1021 LttvAttribute
*sum_container
= self
->stats
;
1023 LttvTraceStats
*tcs
;
1027 LttvAttribute
*main_tree
;
1029 LttvAttributeValue value
;
1031 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
1033 if(*(value
.v_uint
) != 0) return;
1034 *(value
.v_uint
) = 1;
1036 nb_trace
= lttv_traceset_number(traceset
);
1038 for(i
= 0 ; i
< nb_trace
; i
++) {
1039 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
1040 lttv_stats_sum_trace(tcs
, self
->stats
, current_time
);
1041 // lttv_attribute_recursive_add(sum_container, tcs->stats);
1046 // Hook wrapper. call_data is a traceset context.
1047 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
1049 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1051 lttv_stats_add_event_hooks(tss
);
1056 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
1058 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1060 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1064 LttvTracefileStats
*tfs
;
1066 GArray
*hooks
, *before_hooks
, *after_hooks
;
1068 LttvTraceHook
*hook
;
1070 LttvTraceHookByFacility
*thf
;
1072 LttvAttributeValue val
;
1077 nb_trace
= lttv_traceset_number(traceset
);
1078 for(i
= 0 ; i
< nb_trace
; i
++) {
1079 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1081 /* Find the eventtype id for the following events and register the
1082 associated by id hooks. */
1084 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 12);
1085 g_array_set_size(hooks
, 12);
1088 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1089 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
1090 LTT_FIELD_SYSCALL_ID
, 0, 0,
1091 before_syscall_entry
, NULL
,
1092 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1095 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1096 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
1098 before_syscall_exit
, NULL
,
1099 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1102 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1103 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_ENTRY
,
1104 LTT_FIELD_TRAP_ID
, 0, 0,
1105 before_trap_entry
, NULL
,
1106 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1109 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1110 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_EXIT
,
1112 before_trap_exit
, NULL
,
1113 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1116 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1117 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1118 LTT_FIELD_IRQ_ID
, 0, 0,
1119 before_irq_entry
, NULL
,
1120 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1123 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1124 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1126 before_irq_exit
, NULL
,
1127 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1130 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1131 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
1132 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
1133 before_soft_irq_entry
, NULL
,
1134 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1137 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1138 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
1140 before_soft_irq_exit
, NULL
,
1141 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1144 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1145 LTT_FACILITY_KERNEL
, LTT_EVENT_SCHED_SCHEDULE
,
1146 LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
, LTT_FIELD_PREV_STATE
,
1147 before_schedchange
, NULL
,
1148 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1151 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1152 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
1153 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1154 before_function_entry
, NULL
,
1155 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1158 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1159 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
1160 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1161 before_function_exit
, NULL
,
1162 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1165 /* statedump-related hooks */
1166 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1167 LTT_FACILITY_LIST
, LTT_EVENT_PROCESS_STATE
,
1168 LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
1169 before_enum_process_state
, NULL
,
1170 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1173 g_array_set_size(hooks
, hn
);
1175 before_hooks
= hooks
;
1177 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 16);
1178 g_array_set_size(hooks
, 16);
1181 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1182 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_ENTRY
,
1183 LTT_FIELD_SYSCALL_ID
, 0, 0,
1184 after_syscall_entry
, NULL
,
1185 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1188 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1189 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_SYSCALL_EXIT
,
1191 after_syscall_exit
, NULL
,
1192 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1195 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1196 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_ENTRY
,
1197 LTT_FIELD_TRAP_ID
, 0, 0,
1198 after_trap_entry
, NULL
,
1199 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1202 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1203 LTT_FACILITY_KERNEL_ARCH
, LTT_EVENT_TRAP_EXIT
,
1205 after_trap_exit
, NULL
,
1206 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1209 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1210 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_ENTRY
,
1211 LTT_FIELD_IRQ_ID
, 0, 0,
1212 after_irq_entry
, NULL
,
1213 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1216 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1217 LTT_FACILITY_KERNEL
, LTT_EVENT_IRQ_EXIT
,
1219 after_irq_exit
, NULL
,
1220 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1223 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1224 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_ENTRY
,
1225 LTT_FIELD_SOFT_IRQ_ID
, 0, 0,
1226 after_irq_entry
, NULL
,
1227 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1230 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1231 LTT_FACILITY_KERNEL
, LTT_EVENT_SOFT_IRQ_EXIT
,
1233 after_soft_irq_exit
, NULL
,
1234 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1237 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1238 LTT_FACILITY_KERNEL
, LTT_EVENT_SCHED_SCHEDULE
,
1239 LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
, LTT_FIELD_PREV_STATE
,
1240 after_schedchange
, NULL
,
1241 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1244 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1245 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_FORK
,
1246 LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
, 0,
1248 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1251 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1252 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_EXIT
,
1253 LTT_FIELD_PID
, 0, 0,
1255 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1258 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1259 LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_FREE
,
1260 LTT_FIELD_PID
, 0, 0,
1262 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1265 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1266 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_ENTRY
,
1267 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1268 after_function_entry
, NULL
,
1269 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1272 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1273 LTT_FACILITY_USER_GENERIC
, LTT_EVENT_FUNCTION_EXIT
,
1274 LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
, 0,
1275 after_function_exit
, NULL
,
1276 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1279 /* statedump-related hooks */
1280 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1281 LTT_FACILITY_LIST
, LTT_EVENT_PROCESS_STATE
,
1282 LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
,
1283 after_enum_process_state
, NULL
,
1284 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1287 ret
= lttv_trace_find_hook(ts
->parent
.parent
.t
,
1288 LTT_FACILITY_LIST
, LTT_EVENT_STATEDUMP_END
,
1290 after_statedump_end
, NULL
,
1291 &g_array_index(hooks
, LttvTraceHook
, hn
++));
1294 g_array_set_size(hooks
, hn
);
1296 after_hooks
= hooks
;
1298 /* Add these hooks to each event_by_id hooks list */
1300 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1302 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1303 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1304 LttvTracefileContext
*, j
));
1305 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
1308 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1309 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1310 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1311 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1313 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1316 LTTV_PRIO_STATS_BEFORE_STATE
);
1319 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1320 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1321 for(l
= 0; l
<hook
->fac_list
->len
;l
++) {
1322 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1324 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1327 LTTV_PRIO_STATS_AFTER_STATE
);
1331 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1332 LTTV_POINTER
, &val
);
1333 *(val
.v_pointer
) = before_hooks
;
1334 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1335 LTTV_POINTER
, &val
);
1336 *(val
.v_pointer
) = after_hooks
;
1340 // Hook wrapper. call_data is a traceset context.
1341 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1343 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1345 lttv_stats_remove_event_hooks(tss
);
1350 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1352 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1354 guint i
, j
, k
, l
, nb_trace
, nb_tracefile
;
1358 LttvTracefileStats
*tfs
;
1362 GArray
*before_hooks
, *after_hooks
;
1364 LttvTraceHook
*hook
;
1366 LttvTraceHookByFacility
*thf
;
1368 LttvAttributeValue val
;
1370 nb_trace
= lttv_traceset_number(traceset
);
1371 for(i
= 0 ; i
< nb_trace
; i
++) {
1372 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1373 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1374 LTTV_POINTER
, &val
);
1375 before_hooks
= *(val
.v_pointer
);
1376 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1377 LTTV_POINTER
, &val
);
1378 after_hooks
= *(val
.v_pointer
);
1380 /* Remove these hooks from each event_by_id hooks list */
1382 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1384 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1385 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1386 LttvTracefileContext
*, j
));
1387 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1390 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1391 hook
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1392 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1393 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1394 lttv_hooks_remove_data(
1395 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1400 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1401 hook
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1402 for(l
= 0 ; l
< hook
->fac_list
->len
; l
++) {
1403 thf
= g_array_index(hook
->fac_list
, LttvTraceHookByFacility
*, l
);
1404 lttv_hooks_remove_data(
1405 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, thf
->id
),
1411 g_debug("lttv_stats_remove_event_hooks()");
1412 g_array_free(before_hooks
, TRUE
);
1413 g_array_free(after_hooks
, TRUE
);
1418 static void module_init()
1420 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1421 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1422 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1423 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1424 LTTV_STATS_MODES
= g_quark_from_string("modes");
1425 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1426 LTTV_STATS_FUNCTIONS
= g_quark_from_string("functions");
1427 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1428 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1429 LTTV_STATS_CUMULATIVE_CPU_TIME
= g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1430 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time (includes per process waiting time)");
1431 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1432 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1433 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1434 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1435 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1436 LTTV_STATS
= g_quark_from_string("statistics");
1437 LTTV_STATS_TRACEFILES
= g_quark_from_string("tracefiles statistics");
1438 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1441 static void module_destroy()
1446 LTTV_MODULE("stats", "Compute processes statistics", \
1447 "Accumulate statistics for event types, processes and CPUs", \
1448 module_init
, module_destroy
, "state");
1450 /* Change the places where stats are called (create/read/write stats)
1452 Check for options in batchtest.c to reduce writing and see what tests are
1453 best candidates for performance analysis. Once OK, commit, move to main
1454 and run tests. Update the gui for statistics. */