fix type casting
[lttv.git] / ltt / branches / poly / lttv / lttv / stats.c
CommitLineData
9c312311 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
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;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
4e4d11b3 19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
b445142a 22
9f797243 23#include <stdio.h>
08b1c66e 24#include <lttv/module.h>
b445142a 25#include <lttv/stats.h>
2a2fa4f0 26#include <lttv/lttv.h>
f95bc830 27#include <lttv/attribute.h>
b445142a 28#include <ltt/facility.h>
29#include <ltt/trace.h>
30#include <ltt/event.h>
31
9f797243 32#define BUF_SIZE 256
33
b445142a 34GQuark
35 LTTV_STATS_PROCESS_UNKNOWN,
36 LTTV_STATS_PROCESSES,
37 LTTV_STATS_CPU,
38 LTTV_STATS_MODE_TYPES,
39 LTTV_STATS_MODES,
40 LTTV_STATS_SUBMODES,
41 LTTV_STATS_EVENT_TYPES,
42 LTTV_STATS_CPU_TIME,
43 LTTV_STATS_ELAPSED_TIME,
44 LTTV_STATS_EVENTS,
f95bc830 45 LTTV_STATS_EVENTS_COUNT,
46 LTTV_STATS_USE_COUNT,
47 LTTV_STATS,
48 LTTV_STATS_TRACEFILES,
49 LTTV_STATS_SUMMED;
b445142a 50
51static GQuark
52 LTTV_STATS_BEFORE_HOOKS,
53 LTTV_STATS_AFTER_HOOKS;
54
b445142a 55static void
00e74b69 56find_event_tree(LttvTracefileStats *tfcs, GQuark pid_time, GQuark cpu,
b445142a 57 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
58 LttvAttribute **event_types_tree);
59
60static void
61init(LttvTracesetStats *self, LttvTraceset *ts)
62{
dbb7bb09 63 guint i, j, nb_trace, nb_tracefile;
b445142a 64
65 LttvTraceContext *tc;
66
67 LttvTraceStats *tcs;
68
69 LttvTracefileContext *tfc;
70
3c9bb8b1 71 LttvTracefileContext **tfs;
b445142a 72 LttvTracefileStats *tfcs;
73
74 LttTime timestamp = {0,0};
75
f95bc830 76 LttvAttributeValue v;
77
78 LttvAttribute
79 *stats_tree,
80 *tracefiles_stats;
81
b445142a 82 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
83 init((LttvTracesetContext *)self, ts);
84
d3e01c7a 85 self->stats = lttv_attribute_find_subdir(
86 lttv_traceset_attribute(self->parent.parent.ts),
87 LTTV_STATS);
88 lttv_attribute_find(lttv_traceset_attribute(self->parent.parent.ts),
89 LTTV_STATS_USE_COUNT,
90 LTTV_UINT, &v);
f95bc830 91
92 *(v.v_uint)++;
93 if(*(v.v_uint) == 1) {
94 g_assert(lttv_attribute_get_number(self->stats) == 0);
95 }
96
b445142a 97 nb_trace = lttv_traceset_number(ts);
98
99 for(i = 0 ; i < nb_trace ; i++) {
359b2948 100 tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]);
101 tcs = (LttvTraceStats *)tc;
f95bc830 102
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,
107 LTTV_UINT, &v);
108
109 *(v.v_uint)++;
110 if(*(v.v_uint) == 1) {
111 g_assert(lttv_attribute_get_number(tcs->stats) == 0);
112 }
b445142a 113
eed2ef37 114 nb_tracefile = tc->tracefiles->len;
b445142a 115
dbb7bb09 116 for(j = 0 ; j < nb_tracefile ; j++) {
3c9bb8b1 117 tfs = &g_array_index(tc->tracefiles,
118 LttvTracefileContext*, j);
119 tfcs = LTTV_TRACEFILE_STATS(*tfs);
f95bc830 120 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
121 tfcs->parent.cpu_name);
b445142a 122 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
123 tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN,
124 LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
125 &tfcs->current_event_types_tree);
126 }
127 }
128}
129
b445142a 130static void
131fini(LttvTracesetStats *self)
132{
133 guint i, j, nb_trace, nb_tracefile;
134
135 LttvTraceset *ts;
136
137 LttvTraceContext *tc;
138
139 LttvTraceStats *tcs;
140
141 LttvTracefileContext *tfc;
142
143 LttvTracefileStats *tfcs;
144
145 LttTime timestamp = {0,0};
146
f95bc830 147 LttvAttributeValue v;
148
149 LttvAttribute *tracefiles_stats;
150
151 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
152 LTTV_UINT, &v);
153 *(v.v_uint)--;
154
155 if(*(v.v_uint) == 0) {
156 lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
f95bc830 157 }
158 self->stats = NULL;
159
b445142a 160 ts = self->parent.parent.ts;
161 nb_trace = lttv_traceset_number(ts);
162
163 for(i = 0 ; i < nb_trace ; i++) {
f95bc830 164 tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]));
165
166 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
167 LTTV_UINT, &v);
168 *(v.v_uint)--;
169
170 if(*(v.v_uint) == 0) {
171 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
f95bc830 172 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
173 LTTV_STATS_TRACEFILES);
174 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,
175 LTTV_STATS_TRACEFILES);
f95bc830 176 }
177 tcs->stats = NULL;
b445142a 178
eed2ef37 179 nb_tracefile = tc->tracefiles->len;
b445142a 180
b445142a 181 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 182 tfc = g_array_index(tc->tracefiles,
183 LttvTracefileContext*, j);
359b2948 184 tfcs = (LttvTracefileStats *)tfc;
f95bc830 185 tfcs->stats = NULL;
b445142a 186 tfcs->current_events_tree = NULL;
187 tfcs->current_event_types_tree = NULL;
188 }
189 }
190 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
191 fini((LttvTracesetContext *)self);
192}
193
194
195static LttvTracesetContext *
196new_traceset_context(LttvTracesetContext *self)
197{
198 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
199}
200
201
202static LttvTraceContext *
203new_trace_context(LttvTracesetContext *self)
204{
205 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
206}
207
208
209static LttvTracefileContext *
210new_tracefile_context(LttvTracesetContext *self)
211{
212 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
213}
214
215
216static void
217traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
218{
219}
220
221
222static void
223traceset_stats_finalize (LttvTracesetStats *self)
224{
225 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
226 finalize(G_OBJECT(self));
227}
228
229
230static void
231traceset_stats_class_init (LttvTracesetContextClass *klass)
232{
233 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
234
235 gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
236 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
237 klass->fini = (void (*)(LttvTracesetContext *self))fini;
238 klass->new_traceset_context = new_traceset_context;
239 klass->new_trace_context = new_trace_context;
240 klass->new_tracefile_context = new_tracefile_context;
241}
242
243
244GType
245lttv_traceset_stats_get_type(void)
246{
247 static GType type = 0;
248 if (type == 0) {
249 static const GTypeInfo info = {
250 sizeof (LttvTracesetStatsClass),
251 NULL, /* base_init */
252 NULL, /* base_finalize */
253 (GClassInitFunc) traceset_stats_class_init, /* class_init */
254 NULL, /* class_finalize */
255 NULL, /* class_data */
dbb7bb09 256 sizeof (LttvTracesetStats),
b445142a 257 0, /* n_preallocs */
00e74b69 258 (GInstanceInitFunc) traceset_stats_instance_init, /* instance_init */
259 NULL /* Value handling */
b445142a 260 };
261
00e74b69 262 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE,
263 "LttvTracesetStatsType",
264 &info, 0);
b445142a 265 }
266 return type;
267}
268
269
270static void
271trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
272{
273}
274
275
276static void
277trace_stats_finalize (LttvTraceStats *self)
278{
279 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
280 finalize(G_OBJECT(self));
281}
282
283
284static void
285trace_stats_class_init (LttvTraceContextClass *klass)
286{
287 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
288
289 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
290}
291
292
293GType
294lttv_trace_stats_get_type(void)
295{
296 static GType type = 0;
297 if (type == 0) {
298 static const GTypeInfo info = {
299 sizeof (LttvTraceStatsClass),
300 NULL, /* base_init */
301 NULL, /* base_finalize */
302 (GClassInitFunc) trace_stats_class_init, /* class_init */
303 NULL, /* class_finalize */
304 NULL, /* class_data */
305 sizeof (LttvTraceStats),
306 0, /* n_preallocs */
00e74b69 307 (GInstanceInitFunc) trace_stats_instance_init, /* instance_init */
308 NULL /* Value handling */
b445142a 309 };
310
311 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
312 "LttvTraceStatsType", &info, 0);
313 }
314 return type;
315}
316
317
318static void
319tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
320{
321}
322
323
324static void
325tracefile_stats_finalize (LttvTracefileStats *self)
326{
327 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
328 finalize(G_OBJECT(self));
329}
330
331
332static void
333tracefile_stats_class_init (LttvTracefileStatsClass *klass)
334{
335 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
336
337 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
338}
339
340
341GType
342lttv_tracefile_stats_get_type(void)
343{
344 static GType type = 0;
345 if (type == 0) {
346 static const GTypeInfo info = {
347 sizeof (LttvTracefileStatsClass),
348 NULL, /* base_init */
349 NULL, /* base_finalize */
350 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
351 NULL, /* class_finalize */
352 NULL, /* class_data */
353 sizeof (LttvTracefileStats),
354 0, /* n_preallocs */
00e74b69 355 (GInstanceInitFunc) tracefile_stats_instance_init, /* instance_init */
356 NULL /* Value handling */
b445142a 357 };
358
359 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
360 "LttvTracefileStatsType", &info, 0);
361 }
362 return type;
363}
364
365
366static void
00e74b69 367find_event_tree(LttvTracefileStats *tfcs,
368 GQuark pid_time,
369 GQuark cpu,
370 GQuark mode,
371 GQuark sub_mode,
372 LttvAttribute **events_tree,
373 LttvAttribute **event_types_tree)
b445142a 374{
375 LttvAttribute *a;
376
3c9bb8b1 377 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
b445142a 378 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
00e74b69 379 a = lttv_attribute_find_subdir(a, pid_time);
b445142a 380 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
00e74b69 381 a = lttv_attribute_find_subdir(a, cpu);
b445142a 382 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
00e74b69 383 a = lttv_attribute_find_subdir(a, mode);
b445142a 384 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
00e74b69 385 a = lttv_attribute_find_subdir(a, sub_mode);
b445142a 386 *events_tree = a;
387 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
388 *event_types_tree = a;
389}
390
391
392static void update_event_tree(LttvTracefileStats *tfcs)
393{
394 LttvExecutionState *es = tfcs->parent.process->state;
395
00e74b69 396 find_event_tree(tfcs, tfcs->parent.process->pid_time,
397 tfcs->parent.cpu_name,
b445142a 398 es->t, es->n, &(tfcs->current_events_tree),
399 &(tfcs->current_event_types_tree));
400}
401
402
403static void mode_change(LttvTracefileStats *tfcs)
404{
405 LttvAttributeValue cpu_time;
406
407 LttTime delta;
408
409 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
410 LTTV_TIME, &cpu_time);
308711e5 411 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 412 tfcs->parent.process->state->change);
308711e5 413 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 414}
415
416
417static void mode_end(LttvTracefileStats *tfcs)
418{
419 LttvAttributeValue elapsed_time, cpu_time;
420
421 LttTime delta;
422
423 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
424 LTTV_TIME, &elapsed_time);
308711e5 425 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 426 tfcs->parent.process->state->entry);
308711e5 427 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
b445142a 428
429 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
430 LTTV_TIME, &cpu_time);
308711e5 431 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 432 tfcs->parent.process->state->change);
308711e5 433 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 434}
435
436
437static gboolean before_syscall_entry(void *hook_data, void *call_data)
438{
439 mode_change((LttvTracefileStats *)call_data);
440 return FALSE;
441}
442
443
444static gboolean after_syscall_entry(void *hook_data, void *call_data)
445{
446 update_event_tree((LttvTracefileStats *)call_data);
447 return FALSE;
448}
449
450
451gboolean before_syscall_exit(void *hook_data, void *call_data)
452{
453 mode_end((LttvTracefileStats *)call_data);
454 return FALSE;
455}
456
457
458static gboolean after_syscall_exit(void *hook_data, void *call_data)
459{
460 update_event_tree((LttvTracefileStats *)call_data);
461 return FALSE;
462}
463
464
465gboolean before_trap_entry(void *hook_data, void *call_data)
466{
467 mode_change((LttvTracefileStats *)call_data);
468 return FALSE;
469}
470
471
472static gboolean after_trap_entry(void *hook_data, void *call_data)
473{
474 update_event_tree((LttvTracefileStats *)call_data);
475 return FALSE;
476}
477
478
479gboolean before_trap_exit(void *hook_data, void *call_data)
480{
481 mode_end((LttvTracefileStats *)call_data);
482 return FALSE;
483}
484
485
486gboolean after_trap_exit(void *hook_data, void *call_data)
487{
488 update_event_tree((LttvTracefileStats *)call_data);
489 return FALSE;
490}
491
492
493gboolean before_irq_entry(void *hook_data, void *call_data)
494{
495 mode_change((LttvTracefileStats *)call_data);
496 return FALSE;
497}
498
499
500gboolean after_irq_entry(void *hook_data, void *call_data)
501{
502 update_event_tree((LttvTracefileStats *)call_data);
503 return FALSE;
504}
505
506
507gboolean before_irq_exit(void *hook_data, void *call_data)
508{
509 mode_end((LttvTracefileStats *)call_data);
510 return FALSE;
511}
512
513
514gboolean after_irq_exit(void *hook_data, void *call_data)
515{
516 update_event_tree((LttvTracefileStats *)call_data);
517 return FALSE;
518}
519
520
521gboolean before_schedchange(void *hook_data, void *call_data)
522{
b445142a 523 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
524
eed2ef37 525 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
526
d052ffc3 527 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 528
d7cf605c 529 guint pid_in, pid_out;
530
531 gint state_out;
b445142a 532
533 LttvProcessState *process;
534
eed2ef37 535 pid_out = ltt_event_get_unsigned(e, thf->f1);
536 pid_in = ltt_event_get_unsigned(e, thf->f2);
d7cf605c 537 state_out = ltt_event_get_int(e, thf->f3);
b445142a 538
539 /* compute the time for the process to schedule out */
540
541 mode_change(tfcs);
542
543 /* get the information for the process scheduled in */
544
2a2fa4f0 545 process = lttv_state_find_process_or_create(&(tfcs->parent), pid_in);
b445142a 546
547 find_event_tree(tfcs, process->pid_time, tfcs->parent.cpu_name,
548 process->state->t, process->state->n, &(tfcs->current_events_tree),
549 &(tfcs->current_event_types_tree));
550
551 /* compute the time waiting for the process to schedule in */
552
553 mode_change(tfcs);
554 return FALSE;
555}
556
557
558gboolean process_fork(void *hook_data, void *call_data)
559{
560 /* nothing to do for now */
561 return FALSE;
562}
563
564
565gboolean process_exit(void *hook_data, void *call_data)
566{
567 /* We should probably exit all modes here or we could do that at
568 schedule out. */
569 return FALSE;
570}
571
eed2ef37 572gboolean process_free(void *hook_data, void *call_data)
573{
574 return FALSE;
575}
b445142a 576
577gboolean every_event(void *hook_data, void *call_data)
578{
579 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
580
eed2ef37 581 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
582
b445142a 583 LttvAttributeValue v;
584
585 /* The current branch corresponds to the tracefile/process/interrupt state.
586 Statistics are added within it, to count the number of events of this
587 type occuring in this context. A quark has been pre-allocated for each
588 event type and is used as name. */
589
590 lttv_attribute_find(tfcs->current_event_types_tree,
eed2ef37 591 ltt_eventtype_name(ltt_event_eventtype(e)),
b445142a 592 LTTV_UINT, &v);
593 (*(v.v_uint))++;
594 return FALSE;
595}
596
597
f95bc830 598void
599lttv_stats_sum_trace(LttvTraceStats *self)
b445142a 600{
d3e01c7a 601 LttvAttribute *sum_container = self->stats;
b445142a 602
b445142a 603 LttvAttributeType type;
604
605 LttvAttributeValue value;
606
607 LttvAttributeName name;
608
609 unsigned sum;
610
f95bc830 611 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
b445142a 612 nb_event_type;
613
614 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
615 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
616 *submode_tree, *event_types_tree, *mode_events_tree,
617 *cpu_events_tree, *process_modes_tree, *trace_cpu_tree,
f95bc830 618 *trace_modes_tree;
619
d3e01c7a 620 main_tree = sum_container;
f95bc830 621
d3e01c7a 622 lttv_attribute_find(sum_container,
623 LTTV_STATS_SUMMED,
624 LTTV_UINT, &value);
f95bc830 625 if(*(value.v_uint) != 0) return;
626 *(value.v_uint) = 1;
627
628 processes_tree = lttv_attribute_find_subdir(main_tree,
d3e01c7a 629 LTTV_STATS_PROCESSES);
630 trace_modes_tree = lttv_attribute_find_subdir(main_tree,
631 LTTV_STATS_MODES);
f95bc830 632 nb_process = lttv_attribute_get_number(processes_tree);
633
634 for(i = 0 ; i < nb_process ; i++) {
635 type = lttv_attribute_get(processes_tree, i, &name, &value);
636 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
637
638 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
639 process_modes_tree = lttv_attribute_find_subdir(process_tree,
640 LTTV_STATS_MODES);
641 nb_cpu = lttv_attribute_get_number(cpus_tree);
642
643 for(j = 0 ; j < nb_cpu ; j++) {
644 type = lttv_attribute_get(cpus_tree, j, &name, &value);
645 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
646
647 mode_types_tree = lttv_attribute_find_subdir(cpu_tree,
648 LTTV_STATS_MODE_TYPES);
649 cpu_events_tree = lttv_attribute_find_subdir(cpu_tree,
650 LTTV_STATS_EVENTS);
651 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
652 trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name);
653 nb_mode_type = lttv_attribute_get_number(mode_types_tree);
654
655 for(k = 0 ; k < nb_mode_type ; k++) {
656 type = lttv_attribute_get(mode_types_tree, k, &name, &value);
657 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
658
659 submodes_tree = lttv_attribute_find_subdir(mode_tree,
660 LTTV_STATS_SUBMODES);
661 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
662 LTTV_STATS_EVENTS);
663 nb_submode = lttv_attribute_get_number(submodes_tree);
b445142a 664
f95bc830 665 for(l = 0 ; l < nb_submode ; l++) {
666 type = lttv_attribute_get(submodes_tree, l, &name, &value);
667 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
b445142a 668
f95bc830 669 event_types_tree = lttv_attribute_find_subdir(submode_tree,
670 LTTV_STATS_EVENT_TYPES);
671 nb_event_type = lttv_attribute_get_number(event_types_tree);
b445142a 672
f95bc830 673 sum = 0;
674 for(m = 0 ; m < nb_event_type ; m++) {
675 type = lttv_attribute_get(event_types_tree, m, &name, &value);
676 sum += *(value.v_uint);
b445142a 677 }
f95bc830 678 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
679 LTTV_UINT, &value);
680 *(value.v_uint) = sum;
681 lttv_attribute_recursive_add(mode_events_tree, submode_tree);
b445142a 682 }
f95bc830 683 lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
b445142a 684 }
f95bc830 685 lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
686 lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
b445142a 687 }
f95bc830 688 lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
689 }
690}
691
692
d3e01c7a 693gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
694{
695 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
696 return 0;
697}
698
f95bc830 699void
700lttv_stats_sum_traceset(LttvTracesetStats *self)
701{
702 LttvTraceset *traceset = self->parent.parent.ts;
d3e01c7a 703 LttvAttribute *sum_container = self->stats;
f95bc830 704
705 LttvTraceStats *tcs;
706
707 int i, nb_trace;
708
709 LttvAttribute *main_tree, *trace_modes_tree, *traceset_modes_tree;
710
711 LttvAttributeValue value;
712
d3e01c7a 713 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
f95bc830 714 LTTV_UINT, &value);
715 if(*(value.v_uint) != 0) return;
716 *(value.v_uint) = 1;
717
d3e01c7a 718 traceset_modes_tree = lttv_attribute_find_subdir(sum_container,
f95bc830 719 LTTV_STATS_MODES);
720 nb_trace = lttv_traceset_number(traceset);
721
722 for(i = 0 ; i < nb_trace ; i++) {
723 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
724 lttv_stats_sum_trace(tcs);
725 main_tree = tcs->stats;
726 trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
b445142a 727 lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree);
728 }
b445142a 729}
730
731
d3e01c7a 732// Hook wrapper. call_data is a traceset context.
00e74b69 733gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
d3e01c7a 734{
735 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
736
737 lttv_stats_add_event_hooks(tss);
738
739 return 0;
740}
741
00e74b69 742void lttv_stats_add_event_hooks(LttvTracesetStats *self)
b445142a 743{
744 LttvTraceset *traceset = self->parent.parent.ts;
745
eed2ef37 746 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 747
748 LttFacility *f;
749
750 LttEventType *et;
751
752 LttvTraceStats *ts;
753
754 LttvTracefileStats *tfs;
755
756 void *hook_data;
757
758 GArray *hooks, *before_hooks, *after_hooks;
759
eed2ef37 760 LttvTraceHook *hook;
761
762 LttvTraceHookByFacility *thf;
b445142a 763
764 LttvAttributeValue val;
765
9d239bd9 766 gint ret;
767
b445142a 768 nb_trace = lttv_traceset_number(traceset);
769 for(i = 0 ; i < nb_trace ; i++) {
770 ts = (LttvTraceStats *)self->parent.parent.traces[i];
771
772 /* Find the eventtype id for the following events and register the
773 associated by id hooks. */
774
eed2ef37 775 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 7);
b445142a 776 g_array_set_size(hooks, 7);
777
9d239bd9 778 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 779 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
780 LTT_FIELD_SYSCALL_ID, 0, 0,
781 before_syscall_entry,
b445142a 782 &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 783 g_assert(!ret);
b445142a 784
9d239bd9 785 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 786 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
787 0, 0, 0,
788 before_syscall_exit,
b445142a 789 &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 790 g_assert(!ret);
b445142a 791
9d239bd9 792 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 793 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
794 LTT_FIELD_TRAP_ID, 0, 0,
795 before_trap_entry,
b445142a 796 &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 797 g_assert(!ret);
b445142a 798
9d239bd9 799 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 800 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
801 0, 0, 0,
802 before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 803 g_assert(!ret);
eed2ef37 804
9d239bd9 805 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 806 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
807 LTT_FIELD_IRQ_ID, 0, 0,
808 before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 809 g_assert(!ret);
eed2ef37 810
9d239bd9 811 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 812 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
813 0, 0, 0,
814 before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 815 g_assert(!ret);
eed2ef37 816
9d239bd9 817 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 818 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
819 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
820 before_schedchange,
821 &g_array_index(hooks, LttvTraceHook, 6));
9d239bd9 822 g_assert(!ret);
b445142a 823
824 before_hooks = hooks;
825
eed2ef37 826 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 9);
827 g_array_set_size(hooks, 9);
b445142a 828
9d239bd9 829 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 830 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_ENTRY,
831 LTT_FIELD_SYSCALL_ID, 0, 0,
832 after_syscall_entry,
b445142a 833 &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 834 g_assert(!ret);
b445142a 835
9d239bd9 836 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 837 LTT_FACILITY_KERNEL, LTT_EVENT_SYSCALL_EXIT,
838 0, 0, 0,
839 after_syscall_exit,
b445142a 840 &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 841 g_assert(!ret);
b445142a 842
9d239bd9 843 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 844 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
845 LTT_FIELD_TRAP_ID, 0, 0,
846 after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 847 g_assert(!ret);
eed2ef37 848
9d239bd9 849 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 850 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
851 0, 0, 0,
852 after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 853 g_assert(!ret);
b445142a 854
9d239bd9 855 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 856 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
857 LTT_FIELD_IRQ_ID, 0, 0,
858 after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 859 g_assert(!ret);
b445142a 860
9d239bd9 861 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 862 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
863 0, 0, 0,
864 after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 865 g_assert(!ret);
b445142a 866
b445142a 867
9d239bd9 868 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 869 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
870 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
871 process_fork,
b445142a 872 &g_array_index(hooks, LttvTraceHook, 6));
9d239bd9 873 g_assert(!ret);
b445142a 874
9d239bd9 875 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 876 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
877 LTT_FIELD_PID, 0, 0,
878 process_exit, &g_array_index(hooks, LttvTraceHook, 7));
9d239bd9 879 g_assert(!ret);
eed2ef37 880
9d239bd9 881 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 882 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
883 LTT_FIELD_PID, 0, 0,
d7cf605c 884 process_free, &g_array_index(hooks, LttvTraceHook, 8));
9d239bd9 885 g_assert(!ret);
eed2ef37 886
b445142a 887
888 after_hooks = hooks;
889
359b2948 890 /* Add these hooks to each event_by_id hooks list */
b445142a 891
eed2ef37 892 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 893
dbb7bb09 894 for(j = 0 ; j < nb_tracefile ; j++) {
d7cf605c 895 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
896 LttvTracefileContext*, j));
359b2948 897 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
898 LTTV_PRIO_DEFAULT);
b445142a 899
900 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 901 hook = &g_array_index(before_hooks, LttvTraceHook, k);
902 for(l = 0; l<hook->fac_list->len;l++) {
903 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
904 lttv_hooks_add(
905 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
906 thf->h,
d052ffc3 907 thf,
eed2ef37 908 LTTV_PRIO_STATS_BEFORE_STATE);
909 }
b445142a 910 }
911 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 912 hook = &g_array_index(after_hooks, LttvTraceHook, k);
913 for(l = 0; l<hook->fac_list->len;l++) {
914 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
915 lttv_hooks_add(
916 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
917 thf->h,
d052ffc3 918 thf,
eed2ef37 919 LTTV_PRIO_STATS_AFTER_STATE);
920 }
b445142a 921 }
922 }
923 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
924 LTTV_POINTER, &val);
925 *(val.v_pointer) = before_hooks;
926 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
927 LTTV_POINTER, &val);
928 *(val.v_pointer) = after_hooks;
929 }
b445142a 930}
931
d3e01c7a 932// Hook wrapper. call_data is a traceset context.
00e74b69 933gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 934{
935 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
936
937 lttv_stats_remove_event_hooks(tss);
938
939 return 0;
940}
b445142a 941
00e74b69 942void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 943{
944 LttvTraceset *traceset = self->parent.parent.ts;
945
eed2ef37 946 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 947
948 LttvTraceStats *ts;
949
950 LttvTracefileStats *tfs;
951
952 void *hook_data;
953
954 GArray *before_hooks, *after_hooks;
955
eed2ef37 956 LttvTraceHook *hook;
957
958 LttvTraceHookByFacility *thf;
b445142a 959
960 LttvAttributeValue val;
961
962 nb_trace = lttv_traceset_number(traceset);
963 for(i = 0 ; i < nb_trace ; i++) {
964 ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]);
965 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
966 LTTV_POINTER, &val);
967 before_hooks = *(val.v_pointer);
968 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
969 LTTV_POINTER, &val);
970 after_hooks = *(val.v_pointer);
971
359b2948 972 /* Remove these hooks from each event_by_id hooks list */
b445142a 973
eed2ef37 974 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 975
dbb7bb09 976 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 977 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
978 LttvTracefileContext*, j));
359b2948 979 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 980 NULL);
981
982 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 983 hook = &g_array_index(before_hooks, LttvTraceHook, k);
984 for(l = 0 ; l < hook->fac_list->len ; l++) {
985 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
986 lttv_hooks_remove_data(
987 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
988 thf->h,
d052ffc3 989 thf);
eed2ef37 990 }
b445142a 991 }
992 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 993 hook = &g_array_index(after_hooks, LttvTraceHook, k);
994 for(l = 0 ; l < hook->fac_list->len ; l++) {
995 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
996 lttv_hooks_remove_data(
997 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
998 thf->h,
d052ffc3 999 thf);
eed2ef37 1000 }
b445142a 1001 }
1002 }
2a2fa4f0 1003 g_debug("lttv_stats_remove_event_hooks()");
b445142a 1004 g_array_free(before_hooks, TRUE);
1005 g_array_free(after_hooks, TRUE);
1006 }
9f797243 1007}
08b1c66e 1008
1009
1010static void module_init()
1011{
1012 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1013 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1014 LTTV_STATS_CPU = g_quark_from_string("cpu");
1015 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1016 LTTV_STATS_MODES = g_quark_from_string("modes");
1017 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
1018 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1019 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1020 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
1021 LTTV_STATS_EVENTS = g_quark_from_string("events");
1022 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1023 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1024 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 1025 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1026 LTTV_STATS = g_quark_from_string("statistics");
1027 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1028 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 1029}
1030
1031static void module_destroy()
1032{
1033}
1034
1035
1036LTTV_MODULE("stats", "Compute processes statistics", \
1037 "Accumulate statistics for event types, processes and CPUs", \
1038 module_init, module_destroy, "state");
f95bc830 1039
1040/* Change the places where stats are called (create/read/write stats)
1041
1042 Check for options in batchtest.c to reduce writing and see what tests are
1043 best candidates for performance analysis. Once OK, commit, move to main
1044 and run tests. Update the gui for statistics. */
This page took 0.07724 seconds and 4 git commands to generate.