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