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