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