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,
25 #include <lttv/module.h>
26 #include <lttv/stats.h>
27 #include <lttv/lttv.h>
28 #include <lttv/attribute.h>
29 #include <ltt/trace.h>
30 #include <ltt/event.h>
33 #define MAX_64_HEX_STRING_LEN 19
36 LTTV_STATS_PROCESS_UNKNOWN
,
39 LTTV_STATS_MODE_TYPES
,
43 LTTV_STATS_EVENT_TYPES
,
45 LTTV_STATS_CUMULATIVE_CPU_TIME
,
46 LTTV_STATS_ELAPSED_TIME
,
48 LTTV_STATS_EVENTS_COUNT
,
52 LTTV_STATS_BEFORE_HOOKS
,
53 LTTV_STATS_AFTER_HOOKS
;
55 static void find_event_tree(LttvCPUStats
*cpu_stats
, GQuark pid_time
,
56 guint cpu
, guint64 function
,
57 GQuark mode
, GQuark sub_mode
, LttvAttribute
**events_tree
,
58 LttvAttribute
**event_types_tree
);
61 static void lttv_stats_init(LttvTracesetStats
*self
)
63 guint i
, j
, nb_trace
, nb_cpu
, nb_tracefile
;
69 LttvTracefileContext
**tfs
;
70 LttvTracefileStats
*tfcs
;
71 LttvCPUStats
*cpu_stats
;
75 LttvTraceset
*ts
= self
->parent
.parent
.ts
;
77 self
->stats
= lttv_attribute_find_subdir(
78 lttv_traceset_attribute(self
->parent
.parent
.ts
), LTTV_STATS
);
79 lttv_attribute_find(lttv_traceset_attribute(self
->parent
.parent
.ts
),
84 if(*(v
.v_uint
) == 1) {
85 g_assert(lttv_attribute_get_number(self
->stats
) == 0);
88 nb_trace
= lttv_traceset_number(ts
);
90 for(i
= 0 ; i
< nb_trace
; i
++) {
91 tc
= self
->parent
.parent
.traces
[i
];
92 tcs
= LTTV_TRACE_STATS(tc
);
94 tcs
->stats
= lttv_attribute_find_subdir(tcs
->parent
.parent
.t_a
,
96 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
100 if(*(v
.v_uint
) == 1) {
101 g_assert(lttv_attribute_get_number(tcs
->stats
) == 0);
104 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
105 tcs
->cpu_stats
= g_new(LttvCPUStats
, nb_cpu
);
106 for(j
= 0 ; j
< nb_cpu
; j
++) {
107 cpu_stats
= &tcs
->cpu_stats
[j
];
109 cpu_stats
->tcs
= tcs
;
110 find_event_tree(cpu_stats
, LTTV_STATS_PROCESS_UNKNOWN
,
113 LTTV_STATE_MODE_UNKNOWN
,
114 LTTV_STATE_SUBMODE_UNKNOWN
, &cpu_stats
->current_events_tree
,
115 &cpu_stats
->current_event_types_tree
);
117 nb_tracefile
= tc
->tracefiles
->len
;
118 for (j
= 0; j
< nb_tracefile
; j
++) {
119 tfs
= &g_array_index(tc
->tracefiles
, LttvTracefileContext
*, j
);
120 tfcs
= LTTV_TRACEFILE_STATS(*tfs
);
121 tfcs
->cpu_stats
= &tcs
->cpu_stats
[tfcs
->parent
.cpu
];
127 static void lttv_stats_fini(LttvTracesetStats
*self
)
129 guint i
, j
, nb_trace
, nb_cpu
, nb_tracefile
;
133 LttvTraceContext
*tc
;
137 LttvTracefileContext
*tfc
;
139 LttvTracefileStats
*tfcs
;
141 LttvCPUStats
*cpu_stats
;
143 LttvAttributeValue v
;
145 lttv_attribute_find(self
->parent
.parent
.ts_a
, LTTV_STATS_USE_COUNT
,
149 if(*(v
.v_uint
) == 0) {
150 lttv_attribute_remove_by_name(self
->parent
.parent
.ts_a
, LTTV_STATS
);
154 ts
= self
->parent
.parent
.ts
;
155 nb_trace
= lttv_traceset_number(ts
);
157 for(i
= 0 ; i
< nb_trace
; i
++) {
158 tcs
= (LttvTraceStats
*)(tc
= (LTTV_TRACESET_CONTEXT(self
)->traces
[i
]));
160 lttv_attribute_find(tcs
->parent
.parent
.t_a
, LTTV_STATS_USE_COUNT
,
165 lttv_attribute_remove_by_name(tcs
->parent
.parent
.t_a
, LTTV_STATS
);
168 nb_tracefile
= tc
->tracefiles
->len
;
169 for (j
= 0; j
< nb_tracefile
; j
++) {
170 tfc
= g_array_index(tc
->tracefiles
, LttvTracefileContext
*, j
);
171 tfcs
= LTTV_TRACEFILE_STATS(tfc
);
172 tfcs
->cpu_stats
= NULL
;
175 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
177 for(j
= 0 ; j
< nb_cpu
; j
++) {
178 cpu_stats
= &tcs
->cpu_stats
[j
];
179 cpu_stats
->current_events_tree
= NULL
;
180 cpu_stats
->current_event_types_tree
= NULL
;
182 g_free(tcs
->cpu_stats
);
187 void lttv_stats_reset(LttvTracesetStats
*self
)
189 lttv_stats_fini(self
);
190 lttv_stats_init(self
);
195 static void init(LttvTracesetStats
*self
, LttvTraceset
*ts
)
197 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
198 init((LttvTracesetContext
*)self
, ts
);
200 lttv_stats_init(self
);
204 static void fini(LttvTracesetStats
*self
)
206 lttv_stats_fini(self
);
208 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
209 fini((LttvTracesetContext
*)self
);
213 static LttvTracesetContext
*new_traceset_context(LttvTracesetContext
*self
)
215 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
));
219 static LttvTraceContext
*new_trace_context(LttvTracesetContext
*self
)
221 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE
, NULL
));
225 static LttvTracefileContext
*new_tracefile_context(LttvTracesetContext
*self
)
227 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE
, NULL
));
231 static void traceset_stats_instance_init (GTypeInstance
*instance
,
237 static void traceset_stats_finalize (LttvTracesetStats
*self
)
239 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE
))->
240 finalize(G_OBJECT(self
));
244 static void traceset_stats_class_init (LttvTracesetContextClass
*klass
)
246 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
248 gobject_class
->finalize
= (void (*)(GObject
*self
)) traceset_stats_finalize
;
249 klass
->init
= (void (*)(LttvTracesetContext
*self
, LttvTraceset
*ts
))init
;
250 klass
->fini
= (void (*)(LttvTracesetContext
*self
))fini
;
251 klass
->new_traceset_context
= new_traceset_context
;
252 klass
->new_trace_context
= new_trace_context
;
253 klass
->new_tracefile_context
= new_tracefile_context
;
257 GType
lttv_traceset_stats_get_type(void)
259 static GType type
= 0;
261 static const GTypeInfo info
= {
262 sizeof (LttvTracesetStatsClass
),
263 NULL
, /* base_init */
264 NULL
, /* base_finalize */
265 (GClassInitFunc
) traceset_stats_class_init
, /* class_init */
266 NULL
, /* class_finalize */
267 NULL
, /* class_data */
268 sizeof (LttvTracesetStats
),
270 (GInstanceInitFunc
) traceset_stats_instance_init
, /* instance_init */
271 NULL
/* Value handling */
274 type
= g_type_register_static (LTTV_TRACESET_STATE_TYPE
,
275 "LttvTracesetStatsType", &info
, 0);
281 static void trace_stats_instance_init (GTypeInstance
*instance
,
287 static void trace_stats_finalize (LttvTraceStats
*self
)
289 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE
))->
290 finalize(G_OBJECT(self
));
294 static void trace_stats_class_init (LttvTraceContextClass
*klass
)
296 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
298 gobject_class
->finalize
= (void (*)(GObject
*self
)) trace_stats_finalize
;
302 GType
lttv_trace_stats_get_type(void)
304 static GType type
= 0;
306 static const GTypeInfo info
= {
307 sizeof (LttvTraceStatsClass
),
308 NULL
, /* base_init */
309 NULL
, /* base_finalize */
310 (GClassInitFunc
) trace_stats_class_init
, /* class_init */
311 NULL
, /* class_finalize */
312 NULL
, /* class_data */
313 sizeof (LttvTraceStats
),
315 (GInstanceInitFunc
) trace_stats_instance_init
, /* instance_init */
316 NULL
/* Value handling */
319 type
= g_type_register_static (LTTV_TRACE_STATE_TYPE
,
320 "LttvTraceStatsType", &info
, 0);
326 static void tracefile_stats_instance_init (GTypeInstance
*instance
,
332 static void tracefile_stats_finalize (LttvTracefileStats
*self
)
334 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE
))->
335 finalize(G_OBJECT(self
));
339 static void tracefile_stats_class_init (LttvTracefileStatsClass
*klass
)
341 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
343 gobject_class
->finalize
= (void (*)(GObject
*self
)) tracefile_stats_finalize
;
347 GType
lttv_tracefile_stats_get_type(void)
349 static GType type
= 0;
351 static const GTypeInfo info
= {
352 sizeof (LttvTracefileStatsClass
),
353 NULL
, /* base_init */
354 NULL
, /* base_finalize */
355 (GClassInitFunc
) tracefile_stats_class_init
, /* class_init */
356 NULL
, /* class_finalize */
357 NULL
, /* class_data */
358 sizeof (LttvTracefileStats
),
360 (GInstanceInitFunc
) tracefile_stats_instance_init
, /* instance_init */
361 NULL
/* Value handling */
364 type
= g_type_register_static (LTTV_TRACEFILE_STATE_TYPE
,
365 "LttvTracefileStatsType", &info
, 0);
370 static void find_event_tree(LttvCPUStats
*cpu_stats
,
376 LttvAttribute
**events_tree
,
377 LttvAttribute
**event_types_tree
)
380 gchar fstring
[MAX_64_HEX_STRING_LEN
];
383 ret
= snprintf(fstring
, MAX_64_HEX_STRING_LEN
-1,
384 "0x%" PRIX64
, function
) > 0;
386 fstring
[MAX_64_HEX_STRING_LEN
-1] = '\0';
388 LttvTraceStats
*tcs
= cpu_stats
->tcs
;
389 a
= lttv_attribute_find_subdir(tcs
->stats
, LTTV_STATS_PROCESSES
);
390 a
= lttv_attribute_find_subdir(a
, pid_time
);
391 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_CPU
);
392 a
= lttv_attribute_find_subdir_unnamed(a
, cpu
);
393 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_FUNCTIONS
);
394 a
= lttv_attribute_find_subdir(a
, g_quark_from_string(fstring
));
395 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_MODE_TYPES
);
396 a
= lttv_attribute_find_subdir(a
, mode
);
397 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_SUBMODES
);
398 a
= lttv_attribute_find_subdir(a
, sub_mode
);
400 a
= lttv_attribute_find_subdir(a
, LTTV_STATS_EVENT_TYPES
);
401 *event_types_tree
= a
;
404 static void update_event_tree(LttvCPUStats
*cpu_stats
)
406 LttvTraceStats
*tcs
= cpu_stats
->tcs
;
407 guint cpu
= cpu_stats
->cpu
;
408 LttvTraceState
*ts
= &tcs
->parent
;
409 LttvProcessState
*process
= ts
->running_process
[cpu
];
410 LttvExecutionState
*es
= process
->state
;
412 find_event_tree(cpu_stats
, process
->pid_time
,
414 process
->current_function
,
415 es
->t
, es
->n
, &(cpu_stats
->current_events_tree
),
416 &(cpu_stats
->current_event_types_tree
));
419 /* Update the trace event tree each cpu */
420 static void update_trace_event_tree(LttvTraceStats
*tcs
)
422 LttvCPUStats
*cpu_stats
;
423 LttvTraceContext
*tc
= (LttvTraceContext
*)tcs
;
426 /* For each cpu, update the event tree */
427 nb_cpu
= ltt_trace_get_num_cpu(tc
->t
);
428 for(j
= 0; j
< nb_cpu
; j
++) {
429 cpu_stats
= &tcs
->cpu_stats
[j
];
430 update_event_tree(cpu_stats
);
434 static void mode_change(LttvTracefileStats
*tfcs
)
436 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
437 guint cpu
= tfcs
->parent
.cpu
;
438 LttvProcessState
*process
= ts
->running_process
[cpu
];
439 LttvAttributeValue cpu_time
;
443 if(process
->state
->s
== LTTV_STATE_RUN
&&
444 process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
)
445 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
446 process
->state
->change
);
448 delta
= ltt_time_zero
;
450 lttv_attribute_find(tfcs
->cpu_stats
->current_events_tree
, LTTV_STATS_CPU_TIME
,
451 LTTV_TIME
, &cpu_time
);
452 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
454 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
458 /* Note : every mode_end must come with a cumulative cpu time update in the
460 static void mode_end(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 elapsed_time
, cpu_time
, cum_cpu_time
;
469 /* FIXME put there in case of a missing update after a state modification */
470 //void *lasttree = tfcs->cpu_stats->current_events_tree;
471 //update_event_tree(tfcs);
472 //g_assert (lasttree == tfcs->cpu_stats->current_events_tree);
473 lttv_attribute_find(tfcs
->cpu_stats
->current_events_tree
, LTTV_STATS_ELAPSED_TIME
,
474 LTTV_TIME
, &elapsed_time
);
476 if(process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
) {
477 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
478 process
->state
->entry
);
480 delta
= ltt_time_zero
;
482 *(elapsed_time
.v_time
) = ltt_time_add(*(elapsed_time
.v_time
), delta
);
484 lttv_attribute_find(tfcs
->cpu_stats
->current_events_tree
, LTTV_STATS_CPU_TIME
,
485 LTTV_TIME
, &cpu_time
);
487 /* if it is a running mode, we must count its cpu time */
488 if(process
->state
->s
== LTTV_STATE_RUN
&&
489 process
->state
->t
!= LTTV_STATE_MODE_UNKNOWN
)
490 delta
= ltt_time_sub(tfcs
->parent
.parent
.timestamp
,
491 process
->state
->change
);
493 delta
= ltt_time_zero
;
495 *(cpu_time
.v_time
) = ltt_time_add(*(cpu_time
.v_time
), delta
);
496 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
499 lttv_attribute_find(tfcs
->cpu_stats
->current_events_tree
, LTTV_STATS_CUMULATIVE_CPU_TIME
,
500 LTTV_TIME
, &cum_cpu_time
);
501 *(cum_cpu_time
.v_time
) = ltt_time_add(*(cum_cpu_time
.v_time
),
502 process
->state
->cum_cpu_time
);
506 static void after_mode_end(LttvTracefileStats
*tfcs
)
508 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
509 guint cpu
= tfcs
->parent
.cpu
;
510 LttvProcessState
*process
= ts
->running_process
[cpu
];
512 LttTime nested_delta
;
514 nested_delta
= process
->state
->cum_cpu_time
;
515 process
->state
->cum_cpu_time
= ltt_time_zero
; /* For after traceset hook */
517 update_event_tree(tfcs
->cpu_stats
);
519 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
523 static gboolean
before_syscall_entry(void *hook_data
, void *call_data
)
525 mode_change((LttvTracefileStats
*)call_data
);
530 static gboolean
after_syscall_entry(void *hook_data
, void *call_data
)
532 update_event_tree(((LttvTracefileStats
*)call_data
)->cpu_stats
);
537 static gboolean
before_syscall_exit(void *hook_data
, void *call_data
)
539 mode_end((LttvTracefileStats
*)call_data
);
544 static gboolean
after_syscall_exit(void *hook_data
, void *call_data
)
546 after_mode_end((LttvTracefileStats
*)call_data
);
551 static gboolean
before_trap_entry(void *hook_data
, void *call_data
)
553 mode_change((LttvTracefileStats
*)call_data
);
558 static gboolean
after_trap_entry(void *hook_data
, void *call_data
)
560 update_event_tree(((LttvTracefileStats
*)call_data
)->cpu_stats
);
565 static gboolean
before_trap_exit(void *hook_data
, void *call_data
)
567 mode_end((LttvTracefileStats
*)call_data
);
572 static gboolean
after_trap_exit(void *hook_data
, void *call_data
)
574 after_mode_end((LttvTracefileStats
*)call_data
);
579 static gboolean
before_irq_entry(void *hook_data
, void *call_data
)
581 mode_change((LttvTracefileStats
*)call_data
);
585 static gboolean
after_irq_entry(void *hook_data
, void *call_data
)
587 update_event_tree(((LttvTracefileStats
*)call_data
)->cpu_stats
);
592 static gboolean
before_irq_exit(void *hook_data
, void *call_data
)
594 mode_end((LttvTracefileStats
*)call_data
);
599 static gboolean
after_irq_exit(void *hook_data
, void *call_data
)
601 after_mode_end((LttvTracefileStats
*)call_data
);
606 static gboolean
before_soft_irq_entry(void *hook_data
, void *call_data
)
608 mode_change((LttvTracefileStats
*)call_data
);
612 static gboolean
after_soft_irq_entry(void *hook_data
, void *call_data
)
614 update_event_tree(((LttvTracefileStats
*)call_data
)->cpu_stats
);
618 static gboolean
before_soft_irq_exit(void *hook_data
, void *call_data
)
620 mode_end((LttvTracefileStats
*)call_data
);
625 static gboolean
after_soft_irq_exit(void *hook_data
, void *call_data
)
627 after_mode_end((LttvTracefileStats
*)call_data
);
631 static gboolean
before_function_entry(void *hook_data
, void *call_data
)
633 mode_change((LttvTracefileStats
*)call_data
);
637 static gboolean
after_function_entry(void *hook_data
, void *call_data
)
639 update_event_tree(((LttvTracefileStats
*)call_data
)->cpu_stats
);
643 static gboolean
before_function_exit(void *hook_data
, void *call_data
)
645 mode_end((LttvTracefileStats
*)call_data
);
649 static gboolean
after_function_exit(void *hook_data
, void *call_data
)
651 after_mode_end((LttvTracefileStats
*)call_data
);
656 static gboolean
before_schedchange(void *hook_data
, void *call_data
)
658 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
660 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
662 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
664 guint pid_in
, pid_out
;
668 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
669 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
670 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
672 /* compute the time for the process to schedule out */
678 static gboolean
after_schedchange(void *hook_data
, void *call_data
)
680 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
682 LttvTraceState
*ts
= (LttvTraceState
*)tfcs
->parent
.parent
.t_context
;
684 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
686 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
688 guint pid_in
, pid_out
;
692 LttvProcessState
*process
;
694 pid_out
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 0));
695 pid_in
= ltt_event_get_unsigned(e
, lttv_trace_get_hook_field(th
, 1));
696 state_out
= ltt_event_get_long_int(e
, lttv_trace_get_hook_field(th
, 2));
698 /* get the information for the process scheduled in */
699 guint cpu
= tfcs
->parent
.cpu
;
700 process
= ts
->running_process
[cpu
];
702 find_event_tree(tfcs
->cpu_stats
, process
->pid_time
,
704 process
->current_function
,
705 process
->state
->t
, process
->state
->n
,
706 &(tfcs
->cpu_stats
->current_events_tree
),
707 &(tfcs
->cpu_stats
->current_event_types_tree
));
709 /* compute the time waiting for the process to schedule in */
715 static gboolean
process_fork(void *hook_data
, void *call_data
)
720 static gboolean
process_exit(void *hook_data
, void *call_data
)
722 update_event_tree(((LttvTracefileStats
*)call_data
)->cpu_stats
);
726 static gboolean
before_enum_process_state(void *hook_data
, void *call_data
)
729 /* Broken : adds up time in the current process doing the dump */
730 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
732 after_mode_end(tfcs
);
738 static gboolean
after_enum_process_state(void *hook_data
, void *call_data
)
740 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
741 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfc
->t_context
;
742 update_trace_event_tree(tcs
);
746 static gboolean
after_statedump_end(void *hook_data
, void *call_data
)
748 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
749 LttvTraceStats
*tcs
= (LttvTraceStats
*)tfc
->t_context
;
750 update_trace_event_tree(tcs
);
754 static gboolean
process_free(void *hook_data
, void *call_data
)
759 static gboolean
every_event(void *hook_data
, void *call_data
)
761 LttvTracefileStats
*tfcs
= (LttvTracefileStats
*)call_data
;
763 LttEvent
*e
= ltt_tracefile_get_event(tfcs
->parent
.parent
.tf
);
765 LttvAttributeValue v
;
767 struct marker_info
*info
;
769 /* The current branch corresponds to the tracefile/process/interrupt state.
770 Statistics are added within it, to count the number of events of this
771 type occuring in this context. A quark has been pre-allocated for each
772 event type and is used as name. */
774 info
= marker_get_info_from_id(tfcs
->parent
.parent
.tf
->mdata
, e
->event_id
);
776 lttv_attribute_find(tfcs
->cpu_stats
->current_event_types_tree
,
777 info
->name
, LTTV_UINT
, &v
);
782 struct cleanup_state_struct
{
784 LttTime current_time
;
787 //static void lttv_stats_cleanup_process_state(LttvTraceState *ts,
788 // LttvProcessState *process, LttTime current_time)
789 static void lttv_stats_cleanup_process_state(gpointer key
, gpointer value
,
792 struct cleanup_state_struct
*cleanup_closure
=
793 (struct cleanup_state_struct
*)user_data
;
794 LttvTraceState
*ts
= cleanup_closure
->ts
;
795 LttvProcessState
*process
= (LttvProcessState
*)value
;
796 LttTime current_time
= cleanup_closure
->current_time
;
797 LttvTracefileStats
**tfs
= (LttvTracefileStats
**)
798 &g_array_index(ts
->parent
.tracefiles
, LttvTracefileContext
*,
800 int cleanup_empty
= 0;
801 LttTime nested_delta
= ltt_time_zero
;
803 /* FIXME : ok, this is a hack. The time is infinite here :( */
804 //LttTime save_time = (*tfs)->parent.parent.timestamp;
805 //LttTime start, end;
806 //ltt_trace_time_span_get(ts->parent.t, &start, &end);
807 //(*tfs)->parent.parent.timestamp = end;
810 if(ltt_time_compare(process
->state
->cum_cpu_time
, ltt_time_zero
) != 0) {
811 find_event_tree((*tfs
)->cpu_stats
, process
->pid_time
,
813 process
->current_function
,
814 process
->state
->t
, process
->state
->n
,
815 &((*tfs
)->cpu_stats
->current_events_tree
),
816 &((*tfs
)->cpu_stats
->current_event_types_tree
));
817 /* Call mode_end only if not at end of trace */
818 if(ltt_time_compare(current_time
, ltt_time_infinite
) != 0)
820 nested_delta
= process
->state
->cum_cpu_time
;
822 cleanup_empty
= lttv_state_pop_state_cleanup(process
,
823 (LttvTracefileState
*)*tfs
);
824 process
->state
->cum_cpu_time
= ltt_time_add(process
->state
->cum_cpu_time
,
827 } while(cleanup_empty
!= 1);
829 //(*tfs)->parent.parent.timestamp = save_time;
832 /* For each cpu, for each of their stacked states,
833 * perform sum of needed values. */
834 static void lttv_stats_cleanup_state(LttvTraceStats
*tcs
, LttTime current_time
)
836 LttvTraceState
*ts
= (LttvTraceState
*)tcs
;
837 struct cleanup_state_struct cleanup_closure
;
841 nb_cpus
= ltt_trace_get_num_cpu(ts
->parent
.t
);
843 for(i
=0; i
<nb_cpus
; i
++) {
844 lttv_stats_cleanup_process_state(ts
, ts
->running_process
[i
], current_time
);
847 cleanup_closure
.ts
= ts
;
848 cleanup_closure
.current_time
= current_time
;
849 g_hash_table_foreach(ts
->processes
, lttv_stats_cleanup_process_state
,
853 void lttv_stats_sum_trace(LttvTraceStats
*self
, LttvAttribute
*ts_stats
,
854 LttTime current_time
)
856 LttvAttribute
*sum_container
= self
->stats
;
858 LttvAttributeType type
;
860 LttvAttributeValue value
;
862 LttvAttributeName name
;
870 int i
, j
, k
, l
, m
, nb_process
, nb_cpu
, nb_mode_type
, nb_submode
,
871 nb_event_type
, nf
, nb_functions
;
873 LttvAttribute
*main_tree
, *processes_tree
, *process_tree
, *cpus_tree
,
874 *cpu_tree
, *mode_tree
, *mode_types_tree
, *submodes_tree
,
875 *submode_tree
, *event_types_tree
, *mode_events_tree
,
878 *function_mode_types_tree
,
882 main_tree
= sum_container
;
884 lttv_attribute_find(sum_container
,
887 trace_is_summed
= *(value
.v_uint
);
890 /* First cleanup the state : sum all stalled information (never ending
893 lttv_stats_cleanup_state(self
, current_time
);
895 processes_tree
= lttv_attribute_find_subdir(main_tree
,
896 LTTV_STATS_PROCESSES
);
897 nb_process
= lttv_attribute_get_number(processes_tree
);
899 for(i
= 0 ; i
< nb_process
; i
++) {
900 type
= lttv_attribute_get(processes_tree
, i
, &name
, &value
, &is_named
);
901 process_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
903 cpus_tree
= lttv_attribute_find_subdir(process_tree
, LTTV_STATS_CPU
);
904 nb_cpu
= lttv_attribute_get_number(cpus_tree
);
906 for(j
= 0 ; j
< nb_cpu
; j
++) {
907 type
= lttv_attribute_get(cpus_tree
, j
, &name
, &value
, &is_named
);
908 cpu_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
910 trace_cpu_tree
= lttv_attribute_find_subdir(main_tree
,
912 trace_cpu_tree
= lttv_attribute_find_subdir_unnamed(trace_cpu_tree
, name
);
913 cpu_functions_tree
= lttv_attribute_find_subdir(cpu_tree
,
914 LTTV_STATS_FUNCTIONS
);
915 nb_functions
= lttv_attribute_get_number(cpu_functions_tree
);
917 for(nf
=0; nf
< nb_functions
; nf
++) {
918 type
= lttv_attribute_get(cpu_functions_tree
, nf
, &name
, &value
,
920 function_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
921 function_mode_types_tree
= lttv_attribute_find_subdir(function_tree
,
922 LTTV_STATS_MODE_TYPES
);
923 nb_mode_type
= lttv_attribute_get_number(function_mode_types_tree
);
924 for(k
= 0 ; k
< nb_mode_type
; k
++) {
925 type
= lttv_attribute_get(function_mode_types_tree
, k
, &name
,
927 mode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
929 submodes_tree
= lttv_attribute_find_subdir(mode_tree
,
930 LTTV_STATS_SUBMODES
);
931 mode_events_tree
= lttv_attribute_find_subdir(mode_tree
,
933 mode_types_tree
= lttv_attribute_find_subdir(mode_tree
,
934 LTTV_STATS_MODE_TYPES
);
936 nb_submode
= lttv_attribute_get_number(submodes_tree
);
938 for(l
= 0 ; l
< nb_submode
; l
++) {
939 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
941 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
943 event_types_tree
= lttv_attribute_find_subdir(submode_tree
,
944 LTTV_STATS_EVENT_TYPES
);
945 nb_event_type
= lttv_attribute_get_number(event_types_tree
);
948 for(m
= 0 ; m
< nb_event_type
; m
++) {
949 type
= lttv_attribute_get(event_types_tree
, m
, &name
,
951 sum
+= *(value
.v_uint
);
953 lttv_attribute_find(submode_tree
, LTTV_STATS_EVENTS_COUNT
,
955 *(value
.v_uint
) = sum
;
957 type
= lttv_attribute_get(submodes_tree
, l
, &name
, &value
,
959 submode_tree
= LTTV_ATTRIBUTE(*(value
.v_gobject
));
960 if(!trace_is_summed
) {
961 lttv_attribute_recursive_add(mode_events_tree
, event_types_tree
);
962 lttv_attribute_recursive_add(mode_types_tree
, submode_tree
);
965 if(!trace_is_summed
) {
966 lttv_attribute_recursive_add(function_tree
, mode_types_tree
);
969 if(!trace_is_summed
) {
970 lttv_attribute_recursive_add(cpu_tree
, function_tree
);
971 lttv_attribute_recursive_add(process_tree
, function_tree
);
972 lttv_attribute_recursive_add(trace_cpu_tree
, function_tree
);
973 lttv_attribute_recursive_add(main_tree
, function_tree
);
975 lttv_attribute_recursive_add(ts_stats
, function_tree
);
982 gboolean
lttv_stats_sum_traceset_hook(void *hook_data
, void *call_data
)
984 struct sum_traceset_closure
*closure
=
985 (struct sum_traceset_closure
*)call_data
;
986 lttv_stats_sum_traceset(closure
->tss
, closure
->current_time
);
990 void lttv_stats_sum_traceset(LttvTracesetStats
*self
, LttTime current_time
)
992 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
993 LttvAttribute
*sum_container
= self
->stats
;
999 LttvAttributeValue value
;
1001 lttv_attribute_find(sum_container
, LTTV_STATS_SUMMED
,
1003 if(*(value
.v_uint
) != 0) return;
1004 *(value
.v_uint
) = 1;
1006 nb_trace
= lttv_traceset_number(traceset
);
1008 for(i
= 0 ; i
< nb_trace
; i
++) {
1009 tcs
= (LttvTraceStats
*)(self
->parent
.parent
.traces
[i
]);
1010 lttv_stats_sum_trace(tcs
, self
->stats
, current_time
);
1011 // lttv_attribute_recursive_add(sum_container, tcs->stats);
1016 // Hook wrapper. call_data is a traceset context.
1017 gboolean
lttv_stats_hook_add_event_hooks(void *hook_data
, void *call_data
)
1019 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1021 lttv_stats_add_event_hooks(tss
);
1026 void lttv_stats_add_event_hooks(LttvTracesetStats
*self
)
1028 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1030 guint i
, j
, k
, nb_trace
, nb_tracefile
;
1034 LttvTracefileStats
*tfs
;
1036 GArray
*hooks
, *before_hooks
, *after_hooks
;
1040 LttvAttributeValue val
;
1042 nb_trace
= lttv_traceset_number(traceset
);
1043 for(i
= 0 ; i
< nb_trace
; i
++) {
1044 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1046 /* Find the eventtype id for the following events and register the
1047 associated by id hooks. */
1049 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 12);
1051 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1053 LTT_EVENT_SYSCALL_ENTRY
,
1054 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1055 before_syscall_entry
, NULL
,
1058 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1060 LTT_EVENT_SYSCALL_EXIT
,
1062 before_syscall_exit
, NULL
,
1065 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1067 LTT_EVENT_TRAP_ENTRY
,
1068 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1069 before_trap_entry
, NULL
,
1072 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1074 LTT_EVENT_TRAP_EXIT
,
1076 before_trap_exit
, NULL
,
1079 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1081 LTT_EVENT_IRQ_ENTRY
,
1082 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1083 before_irq_entry
, NULL
,
1086 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1090 before_irq_exit
, NULL
,
1093 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1095 LTT_EVENT_SOFT_IRQ_ENTRY
,
1096 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
1097 before_soft_irq_entry
, NULL
,
1100 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1102 LTT_EVENT_SOFT_IRQ_EXIT
,
1104 before_soft_irq_exit
, NULL
,
1107 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1109 LTT_EVENT_SCHED_SCHEDULE
,
1110 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
, LTT_FIELD_PREV_STATE
),
1111 before_schedchange
, NULL
,
1114 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1115 LTT_CHANNEL_USERSPACE
,
1116 LTT_EVENT_FUNCTION_ENTRY
,
1117 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
1118 before_function_entry
, NULL
,
1121 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1122 LTT_CHANNEL_USERSPACE
,
1123 LTT_EVENT_FUNCTION_EXIT
,
1124 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
1125 before_function_exit
, NULL
,
1128 /* statedump-related hooks */
1129 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1130 LTT_CHANNEL_TASK_STATE
,
1131 LTT_EVENT_PROCESS_STATE
,
1132 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
),
1133 before_enum_process_state
, NULL
,
1136 before_hooks
= hooks
;
1138 hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 16);
1140 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1142 LTT_EVENT_SYSCALL_ENTRY
,
1143 FIELD_ARRAY(LTT_FIELD_SYSCALL_ID
),
1144 after_syscall_entry
, NULL
,
1147 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1149 LTT_EVENT_SYSCALL_EXIT
,
1151 after_syscall_exit
, NULL
,
1154 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1156 LTT_EVENT_TRAP_ENTRY
,
1157 FIELD_ARRAY(LTT_FIELD_TRAP_ID
),
1158 after_trap_entry
, NULL
,
1161 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1163 LTT_EVENT_TRAP_EXIT
,
1165 after_trap_exit
, NULL
,
1168 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1170 LTT_EVENT_IRQ_ENTRY
,
1171 FIELD_ARRAY(LTT_FIELD_IRQ_ID
),
1172 after_irq_entry
, NULL
,
1175 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1179 after_irq_exit
, NULL
,
1182 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1184 LTT_EVENT_SOFT_IRQ_ENTRY
,
1185 FIELD_ARRAY(LTT_FIELD_SOFT_IRQ_ID
),
1186 after_soft_irq_entry
, NULL
,
1189 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1191 LTT_EVENT_SOFT_IRQ_EXIT
,
1193 after_soft_irq_exit
, NULL
,
1196 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1198 LTT_EVENT_SCHED_SCHEDULE
,
1199 FIELD_ARRAY(LTT_FIELD_PREV_PID
, LTT_FIELD_NEXT_PID
, LTT_FIELD_PREV_STATE
),
1200 after_schedchange
, NULL
,
1203 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1205 LTT_EVENT_PROCESS_FORK
,
1206 FIELD_ARRAY(LTT_FIELD_PARENT_PID
, LTT_FIELD_CHILD_PID
),
1210 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1212 LTT_EVENT_PROCESS_EXIT
,
1213 FIELD_ARRAY(LTT_FIELD_PID
),
1217 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1219 LTT_EVENT_PROCESS_FREE
,
1220 FIELD_ARRAY(LTT_FIELD_PID
),
1224 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1225 LTT_CHANNEL_USERSPACE
,
1226 LTT_EVENT_FUNCTION_ENTRY
,
1227 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
1228 after_function_entry
, NULL
,
1231 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1232 LTT_CHANNEL_USERSPACE
,
1233 LTT_EVENT_FUNCTION_EXIT
,
1234 FIELD_ARRAY(LTT_FIELD_THIS_FN
, LTT_FIELD_CALL_SITE
),
1235 after_function_exit
, NULL
,
1238 /* statedump-related hooks */
1239 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1240 LTT_CHANNEL_TASK_STATE
,
1241 LTT_EVENT_PROCESS_STATE
,
1242 FIELD_ARRAY(LTT_FIELD_PID
, LTT_FIELD_PARENT_PID
, LTT_FIELD_NAME
),
1243 after_enum_process_state
, NULL
,
1246 lttv_trace_find_hook(ts
->parent
.parent
.t
,
1247 LTT_CHANNEL_GLOBAL_STATE
,
1248 LTT_EVENT_STATEDUMP_END
,
1250 after_statedump_end
, NULL
,
1253 after_hooks
= hooks
;
1255 /* Add these hooks to each event_by_id hooks list */
1257 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1259 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1260 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1261 LttvTracefileContext
*, j
));
1262 lttv_hooks_add(tfs
->parent
.parent
.event
, every_event
, NULL
,
1265 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1266 th
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1267 if (th
->mdata
== tfs
->parent
.parent
.tf
->mdata
)
1269 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, th
->id
),
1272 LTTV_PRIO_STATS_BEFORE_STATE
);
1274 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1275 th
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1276 if (th
->mdata
== tfs
->parent
.parent
.tf
->mdata
)
1278 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, th
->id
),
1281 LTTV_PRIO_STATS_AFTER_STATE
);
1284 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1285 LTTV_POINTER
, &val
);
1286 *(val
.v_pointer
) = before_hooks
;
1287 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1288 LTTV_POINTER
, &val
);
1289 *(val
.v_pointer
) = after_hooks
;
1293 // Hook wrapper. call_data is a traceset context.
1294 gboolean
lttv_stats_hook_remove_event_hooks(void *hook_data
, void *call_data
)
1296 LttvTracesetStats
*tss
= (LttvTracesetStats
*)call_data
;
1298 lttv_stats_remove_event_hooks(tss
);
1303 void lttv_stats_remove_event_hooks(LttvTracesetStats
*self
)
1305 LttvTraceset
*traceset
= self
->parent
.parent
.ts
;
1307 guint i
, j
, k
, nb_trace
, nb_tracefile
;
1311 LttvTracefileStats
*tfs
;
1313 GArray
*before_hooks
, *after_hooks
;
1317 LttvAttributeValue val
;
1319 nb_trace
= lttv_traceset_number(traceset
);
1320 for(i
= 0 ; i
< nb_trace
; i
++) {
1321 ts
= (LttvTraceStats
*)self
->parent
.parent
.traces
[i
];
1322 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_BEFORE_HOOKS
,
1323 LTTV_POINTER
, &val
);
1324 before_hooks
= *(val
.v_pointer
);
1325 lttv_attribute_find(self
->parent
.parent
.a
, LTTV_STATS_AFTER_HOOKS
,
1326 LTTV_POINTER
, &val
);
1327 after_hooks
= *(val
.v_pointer
);
1329 /* Remove these hooks from each event_by_id hooks list */
1331 nb_tracefile
= ts
->parent
.parent
.tracefiles
->len
;
1333 for(j
= 0 ; j
< nb_tracefile
; j
++) {
1334 tfs
= LTTV_TRACEFILE_STATS(g_array_index(ts
->parent
.parent
.tracefiles
,
1335 LttvTracefileContext
*, j
));
1336 lttv_hooks_remove_data(tfs
->parent
.parent
.event
, every_event
,
1339 for(k
= 0 ; k
< before_hooks
->len
; k
++) {
1340 th
= &g_array_index(before_hooks
, LttvTraceHook
, k
);
1341 if (th
->mdata
== tfs
->parent
.parent
.tf
->mdata
)
1342 lttv_hooks_remove_data(
1343 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, th
->id
),
1347 for(k
= 0 ; k
< after_hooks
->len
; k
++) {
1348 th
= &g_array_index(after_hooks
, LttvTraceHook
, k
);
1349 if (th
->mdata
== tfs
->parent
.parent
.tf
->mdata
)
1350 lttv_hooks_remove_data(
1351 lttv_hooks_by_id_find(tfs
->parent
.parent
.event_by_id
, th
->id
),
1357 g_debug("lttv_stats_remove_event_hooks()");
1358 lttv_trace_hook_remove_all(&before_hooks
);
1359 lttv_trace_hook_remove_all(&after_hooks
);
1360 g_array_free(before_hooks
, TRUE
);
1361 g_array_free(after_hooks
, TRUE
);
1366 static void module_init()
1368 LTTV_STATS_PROCESS_UNKNOWN
= g_quark_from_string("unknown process");
1369 LTTV_STATS_PROCESSES
= g_quark_from_string("processes");
1370 LTTV_STATS_CPU
= g_quark_from_string("cpu");
1371 LTTV_STATS_MODE_TYPES
= g_quark_from_string("mode_types");
1372 LTTV_STATS_MODES
= g_quark_from_string("modes");
1373 LTTV_STATS_SUBMODES
= g_quark_from_string("submodes");
1374 LTTV_STATS_FUNCTIONS
= g_quark_from_string("functions");
1375 LTTV_STATS_EVENT_TYPES
= g_quark_from_string("event_types");
1376 LTTV_STATS_CPU_TIME
= g_quark_from_string("cpu time");
1377 LTTV_STATS_CUMULATIVE_CPU_TIME
= g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1378 LTTV_STATS_ELAPSED_TIME
= g_quark_from_string("elapsed time (includes per process waiting time)");
1379 LTTV_STATS_EVENTS
= g_quark_from_string("events");
1380 LTTV_STATS_EVENTS_COUNT
= g_quark_from_string("events count");
1381 LTTV_STATS_BEFORE_HOOKS
= g_quark_from_string("saved stats before hooks");
1382 LTTV_STATS_AFTER_HOOKS
= g_quark_from_string("saved stats after hooks");
1383 LTTV_STATS_USE_COUNT
= g_quark_from_string("stats_use_count");
1384 LTTV_STATS
= g_quark_from_string("statistics");
1385 LTTV_STATS_SUMMED
= g_quark_from_string("statistics summed");
1388 static void module_destroy()
1393 LTTV_MODULE("stats", "Compute processes statistics", \
1394 "Accumulate statistics for event types, processes and CPUs", \
1395 module_init
, module_destroy
, "state");
1397 /* Change the places where stats are called (create/read/write stats)
1399 Check for options in batchtest.c to reduce writing and see what tests are
1400 best candidates for performance analysis. Once OK, commit, move to main
1401 and run tests. Update the gui for statistics. */