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