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