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