add usertrace support
[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;
ae3d0f50 420 guint cpu = tfcs->parent.cpu;
348c6ba8 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;
ae3d0f50 434 guint cpu = tfcs->parent.cpu;
348c6ba8 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;
ae3d0f50 451 guint cpu = tfcs->parent.cpu;
348c6ba8 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
b445142a 533gboolean after_irq_entry(void *hook_data, void *call_data)
534{
535 update_event_tree((LttvTracefileStats *)call_data);
536 return FALSE;
537}
538
539
540gboolean before_irq_exit(void *hook_data, void *call_data)
541{
542 mode_end((LttvTracefileStats *)call_data);
543 return FALSE;
544}
545
546
547gboolean after_irq_exit(void *hook_data, void *call_data)
548{
549 update_event_tree((LttvTracefileStats *)call_data);
550 return FALSE;
551}
552
553
faf074a3 554gboolean before_soft_irq_entry(void *hook_data, void *call_data)
555{
556 mode_change((LttvTracefileStats *)call_data);
557 return FALSE;
558}
559
560gboolean after_soft_irq_entry(void *hook_data, void *call_data)
561{
562 update_event_tree((LttvTracefileStats *)call_data);
563 return FALSE;
564}
565
566
567gboolean before_soft_irq_exit(void *hook_data, void *call_data)
568{
569 mode_end((LttvTracefileStats *)call_data);
570 return FALSE;
571}
572
573
574gboolean after_soft_irq_exit(void *hook_data, void *call_data)
575{
576 update_event_tree((LttvTracefileStats *)call_data);
577 return FALSE;
578}
579
580
b445142a 581gboolean before_schedchange(void *hook_data, void *call_data)
582{
b445142a 583 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
584
348c6ba8 585 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
586
eed2ef37 587 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
588
d052ffc3 589 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
eed2ef37 590
d7cf605c 591 guint pid_in, pid_out;
592
593 gint state_out;
b445142a 594
595 LttvProcessState *process;
596
eed2ef37 597 pid_out = ltt_event_get_unsigned(e, thf->f1);
598 pid_in = ltt_event_get_unsigned(e, thf->f2);
d7cf605c 599 state_out = ltt_event_get_int(e, thf->f3);
b445142a 600
601 /* compute the time for the process to schedule out */
602
603 mode_change(tfcs);
604
605 /* get the information for the process scheduled in */
606
348c6ba8 607 process = lttv_state_find_process_or_create(ts,
608 ANY_CPU, pid_in, &tfcs->parent.parent.timestamp);
b445142a 609
348c6ba8 610 find_event_tree(tfcs, process->pid_time,
611 ltt_tracefile_long_name(tfcs->parent.parent.tf),
b445142a 612 process->state->t, process->state->n, &(tfcs->current_events_tree),
613 &(tfcs->current_event_types_tree));
614
615 /* compute the time waiting for the process to schedule in */
616
617 mode_change(tfcs);
618 return FALSE;
619}
620
621
622gboolean process_fork(void *hook_data, void *call_data)
623{
624 /* nothing to do for now */
625 return FALSE;
626}
627
628
629gboolean process_exit(void *hook_data, void *call_data)
630{
631 /* We should probably exit all modes here or we could do that at
632 schedule out. */
633 return FALSE;
634}
635
eed2ef37 636gboolean process_free(void *hook_data, void *call_data)
637{
638 return FALSE;
639}
b445142a 640
641gboolean every_event(void *hook_data, void *call_data)
642{
643 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
644
eed2ef37 645 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
646
b445142a 647 LttvAttributeValue v;
648
649 /* The current branch corresponds to the tracefile/process/interrupt state.
650 Statistics are added within it, to count the number of events of this
651 type occuring in this context. A quark has been pre-allocated for each
652 event type and is used as name. */
653
654 lttv_attribute_find(tfcs->current_event_types_tree,
eed2ef37 655 ltt_eventtype_name(ltt_event_eventtype(e)),
b445142a 656 LTTV_UINT, &v);
657 (*(v.v_uint))++;
658 return FALSE;
659}
660
661
f95bc830 662void
663lttv_stats_sum_trace(LttvTraceStats *self)
b445142a 664{
d3e01c7a 665 LttvAttribute *sum_container = self->stats;
b445142a 666
b445142a 667 LttvAttributeType type;
668
669 LttvAttributeValue value;
670
671 LttvAttributeName name;
672
673 unsigned sum;
674
f95bc830 675 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
b445142a 676 nb_event_type;
677
678 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
679 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
680 *submode_tree, *event_types_tree, *mode_events_tree,
681 *cpu_events_tree, *process_modes_tree, *trace_cpu_tree,
f95bc830 682 *trace_modes_tree;
683
d3e01c7a 684 main_tree = sum_container;
f95bc830 685
d3e01c7a 686 lttv_attribute_find(sum_container,
687 LTTV_STATS_SUMMED,
688 LTTV_UINT, &value);
f95bc830 689 if(*(value.v_uint) != 0) return;
690 *(value.v_uint) = 1;
691
692 processes_tree = lttv_attribute_find_subdir(main_tree,
d3e01c7a 693 LTTV_STATS_PROCESSES);
694 trace_modes_tree = lttv_attribute_find_subdir(main_tree,
695 LTTV_STATS_MODES);
f95bc830 696 nb_process = lttv_attribute_get_number(processes_tree);
697
698 for(i = 0 ; i < nb_process ; i++) {
699 type = lttv_attribute_get(processes_tree, i, &name, &value);
700 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
701
702 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
703 process_modes_tree = lttv_attribute_find_subdir(process_tree,
704 LTTV_STATS_MODES);
705 nb_cpu = lttv_attribute_get_number(cpus_tree);
706
707 for(j = 0 ; j < nb_cpu ; j++) {
708 type = lttv_attribute_get(cpus_tree, j, &name, &value);
709 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
710
711 mode_types_tree = lttv_attribute_find_subdir(cpu_tree,
712 LTTV_STATS_MODE_TYPES);
713 cpu_events_tree = lttv_attribute_find_subdir(cpu_tree,
714 LTTV_STATS_EVENTS);
715 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
716 trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name);
717 nb_mode_type = lttv_attribute_get_number(mode_types_tree);
718
719 for(k = 0 ; k < nb_mode_type ; k++) {
720 type = lttv_attribute_get(mode_types_tree, k, &name, &value);
721 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
722
723 submodes_tree = lttv_attribute_find_subdir(mode_tree,
724 LTTV_STATS_SUBMODES);
725 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
726 LTTV_STATS_EVENTS);
727 nb_submode = lttv_attribute_get_number(submodes_tree);
b445142a 728
f95bc830 729 for(l = 0 ; l < nb_submode ; l++) {
730 type = lttv_attribute_get(submodes_tree, l, &name, &value);
731 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
b445142a 732
f95bc830 733 event_types_tree = lttv_attribute_find_subdir(submode_tree,
734 LTTV_STATS_EVENT_TYPES);
735 nb_event_type = lttv_attribute_get_number(event_types_tree);
b445142a 736
f95bc830 737 sum = 0;
738 for(m = 0 ; m < nb_event_type ; m++) {
739 type = lttv_attribute_get(event_types_tree, m, &name, &value);
740 sum += *(value.v_uint);
b445142a 741 }
f95bc830 742 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
743 LTTV_UINT, &value);
744 *(value.v_uint) = sum;
745 lttv_attribute_recursive_add(mode_events_tree, submode_tree);
b445142a 746 }
f95bc830 747 lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
b445142a 748 }
f95bc830 749 lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
750 lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
b445142a 751 }
f95bc830 752 lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
753 }
754}
755
756
d3e01c7a 757gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
758{
759 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
760 return 0;
761}
762
f95bc830 763void
764lttv_stats_sum_traceset(LttvTracesetStats *self)
765{
766 LttvTraceset *traceset = self->parent.parent.ts;
d3e01c7a 767 LttvAttribute *sum_container = self->stats;
f95bc830 768
769 LttvTraceStats *tcs;
770
771 int i, nb_trace;
772
773 LttvAttribute *main_tree, *trace_modes_tree, *traceset_modes_tree;
774
775 LttvAttributeValue value;
776
d3e01c7a 777 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
f95bc830 778 LTTV_UINT, &value);
779 if(*(value.v_uint) != 0) return;
780 *(value.v_uint) = 1;
781
d3e01c7a 782 traceset_modes_tree = lttv_attribute_find_subdir(sum_container,
f95bc830 783 LTTV_STATS_MODES);
784 nb_trace = lttv_traceset_number(traceset);
785
786 for(i = 0 ; i < nb_trace ; i++) {
787 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
788 lttv_stats_sum_trace(tcs);
789 main_tree = tcs->stats;
790 trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
b445142a 791 lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree);
792 }
b445142a 793}
794
795
d3e01c7a 796// Hook wrapper. call_data is a traceset context.
00e74b69 797gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
d3e01c7a 798{
799 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
800
801 lttv_stats_add_event_hooks(tss);
802
803 return 0;
804}
805
00e74b69 806void lttv_stats_add_event_hooks(LttvTracesetStats *self)
b445142a 807{
808 LttvTraceset *traceset = self->parent.parent.ts;
809
eed2ef37 810 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 811
b445142a 812 LttvTraceStats *ts;
813
814 LttvTracefileStats *tfs;
815
b445142a 816 GArray *hooks, *before_hooks, *after_hooks;
817
eed2ef37 818 LttvTraceHook *hook;
819
820 LttvTraceHookByFacility *thf;
b445142a 821
822 LttvAttributeValue val;
823
9d239bd9 824 gint ret;
825
b445142a 826 nb_trace = lttv_traceset_number(traceset);
827 for(i = 0 ; i < nb_trace ; i++) {
828 ts = (LttvTraceStats *)self->parent.parent.traces[i];
829
830 /* Find the eventtype id for the following events and register the
831 associated by id hooks. */
832
faf074a3 833 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 9);
834 g_array_set_size(hooks, 9);
b445142a 835
9d239bd9 836 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 837 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 838 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 839 before_syscall_entry, NULL,
b445142a 840 &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 841 g_assert(!ret);
b445142a 842
9d239bd9 843 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 844 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 845 0, 0, 0,
2c82c4dc 846 before_syscall_exit, NULL,
b445142a 847 &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 848 g_assert(!ret);
b445142a 849
9d239bd9 850 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 851 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
852 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 853 before_trap_entry, NULL,
b445142a 854 &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 855 g_assert(!ret);
b445142a 856
9d239bd9 857 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 858 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
859 0, 0, 0,
2c82c4dc 860 before_trap_exit, NULL,
861 &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 862 g_assert(!ret);
eed2ef37 863
9d239bd9 864 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 865 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
866 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 867 before_irq_entry, NULL,
868 &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 869 g_assert(!ret);
eed2ef37 870
9d239bd9 871 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 872 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
873 0, 0, 0,
2c82c4dc 874 before_irq_exit, NULL,
875 &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 876 g_assert(!ret);
eed2ef37 877
faf074a3 878 ret = lttv_trace_find_hook(ts->parent.parent.t,
879 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
880 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
881 before_soft_irq_entry, NULL,
882 &g_array_index(hooks, LttvTraceHook, 6));
883 g_assert(!ret);
884
885 ret = lttv_trace_find_hook(ts->parent.parent.t,
886 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
887 0, 0, 0,
888 before_soft_irq_exit, NULL,
889 &g_array_index(hooks, LttvTraceHook, 7));
890 g_assert(!ret);
891
9d239bd9 892 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 893 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
894 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
2c82c4dc 895 before_schedchange, NULL,
faf074a3 896 &g_array_index(hooks, LttvTraceHook, 8));
9d239bd9 897 g_assert(!ret);
b445142a 898
899 before_hooks = hooks;
900
faf074a3 901 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 11);
902 g_array_set_size(hooks, 11);
b445142a 903
9d239bd9 904 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 905 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 906 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 907 after_syscall_entry, NULL,
b445142a 908 &g_array_index(hooks, LttvTraceHook, 0));
9d239bd9 909 g_assert(!ret);
b445142a 910
9d239bd9 911 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 912 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 913 0, 0, 0,
2c82c4dc 914 after_syscall_exit, NULL,
b445142a 915 &g_array_index(hooks, LttvTraceHook, 1));
9d239bd9 916 g_assert(!ret);
b445142a 917
9d239bd9 918 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 919 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
920 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 921 after_trap_entry, NULL,
922 &g_array_index(hooks, LttvTraceHook, 2));
9d239bd9 923 g_assert(!ret);
eed2ef37 924
9d239bd9 925 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 926 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
927 0, 0, 0,
2c82c4dc 928 after_trap_exit, NULL,
929 &g_array_index(hooks, LttvTraceHook, 3));
9d239bd9 930 g_assert(!ret);
b445142a 931
9d239bd9 932 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 933 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
934 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 935 after_irq_entry, NULL,
936 &g_array_index(hooks, LttvTraceHook, 4));
9d239bd9 937 g_assert(!ret);
b445142a 938
9d239bd9 939 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 940 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
941 0, 0, 0,
2c82c4dc 942 after_irq_exit, NULL,
943 &g_array_index(hooks, LttvTraceHook, 5));
9d239bd9 944 g_assert(!ret);
b445142a 945
faf074a3 946 ret = lttv_trace_find_hook(ts->parent.parent.t,
947 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
948 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
949 after_irq_entry, NULL,
950 &g_array_index(hooks, LttvTraceHook, 6));
951 g_assert(!ret);
952
953 ret = lttv_trace_find_hook(ts->parent.parent.t,
954 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
955 0, 0, 0,
956 after_soft_irq_exit, NULL,
957 &g_array_index(hooks, LttvTraceHook, 7));
958 g_assert(!ret);
b445142a 959
9d239bd9 960 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 961 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
962 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
2c82c4dc 963 process_fork, NULL,
faf074a3 964 &g_array_index(hooks, LttvTraceHook, 8));
9d239bd9 965 g_assert(!ret);
b445142a 966
9d239bd9 967 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 968 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
969 LTT_FIELD_PID, 0, 0,
2c82c4dc 970 process_exit, NULL,
faf074a3 971 &g_array_index(hooks, LttvTraceHook, 9));
9d239bd9 972 g_assert(!ret);
eed2ef37 973
9d239bd9 974 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 975 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
976 LTT_FIELD_PID, 0, 0,
2c82c4dc 977 process_free, NULL,
faf074a3 978 &g_array_index(hooks, LttvTraceHook, 10));
9d239bd9 979 g_assert(!ret);
eed2ef37 980
b445142a 981
982 after_hooks = hooks;
983
359b2948 984 /* Add these hooks to each event_by_id hooks list */
b445142a 985
eed2ef37 986 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 987
dbb7bb09 988 for(j = 0 ; j < nb_tracefile ; j++) {
d7cf605c 989 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
990 LttvTracefileContext*, j));
359b2948 991 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
992 LTTV_PRIO_DEFAULT);
b445142a 993
994 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 995 hook = &g_array_index(before_hooks, LttvTraceHook, k);
996 for(l = 0; l<hook->fac_list->len;l++) {
997 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
998 lttv_hooks_add(
999 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1000 thf->h,
d052ffc3 1001 thf,
eed2ef37 1002 LTTV_PRIO_STATS_BEFORE_STATE);
1003 }
b445142a 1004 }
1005 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1006 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1007 for(l = 0; l<hook->fac_list->len;l++) {
1008 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1009 lttv_hooks_add(
1010 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1011 thf->h,
d052ffc3 1012 thf,
eed2ef37 1013 LTTV_PRIO_STATS_AFTER_STATE);
1014 }
b445142a 1015 }
1016 }
1017 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1018 LTTV_POINTER, &val);
1019 *(val.v_pointer) = before_hooks;
1020 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1021 LTTV_POINTER, &val);
1022 *(val.v_pointer) = after_hooks;
1023 }
b445142a 1024}
1025
d3e01c7a 1026// Hook wrapper. call_data is a traceset context.
00e74b69 1027gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1028{
1029 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1030
1031 lttv_stats_remove_event_hooks(tss);
1032
1033 return 0;
1034}
b445142a 1035
00e74b69 1036void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 1037{
1038 LttvTraceset *traceset = self->parent.parent.ts;
1039
eed2ef37 1040 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 1041
1042 LttvTraceStats *ts;
1043
1044 LttvTracefileStats *tfs;
1045
1046 void *hook_data;
1047
1048 GArray *before_hooks, *after_hooks;
1049
eed2ef37 1050 LttvTraceHook *hook;
1051
1052 LttvTraceHookByFacility *thf;
b445142a 1053
1054 LttvAttributeValue val;
1055
1056 nb_trace = lttv_traceset_number(traceset);
1057 for(i = 0 ; i < nb_trace ; i++) {
ae80b609 1058 ts = (LttvTraceStats*)self->parent.parent.traces[i];
b445142a 1059 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1060 LTTV_POINTER, &val);
1061 before_hooks = *(val.v_pointer);
1062 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1063 LTTV_POINTER, &val);
1064 after_hooks = *(val.v_pointer);
1065
359b2948 1066 /* Remove these hooks from each event_by_id hooks list */
b445142a 1067
eed2ef37 1068 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 1069
dbb7bb09 1070 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 1071 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1072 LttvTracefileContext*, j));
359b2948 1073 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 1074 NULL);
1075
1076 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1077 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1078 for(l = 0 ; l < hook->fac_list->len ; l++) {
1079 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1080 lttv_hooks_remove_data(
1081 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1082 thf->h,
d052ffc3 1083 thf);
eed2ef37 1084 }
b445142a 1085 }
1086 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1087 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1088 for(l = 0 ; l < hook->fac_list->len ; l++) {
1089 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1090 lttv_hooks_remove_data(
1091 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1092 thf->h,
d052ffc3 1093 thf);
eed2ef37 1094 }
b445142a 1095 }
1096 }
2a2fa4f0 1097 g_debug("lttv_stats_remove_event_hooks()");
b445142a 1098 g_array_free(before_hooks, TRUE);
1099 g_array_free(after_hooks, TRUE);
1100 }
9f797243 1101}
08b1c66e 1102
1103
1104static void module_init()
1105{
1106 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1107 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1108 LTTV_STATS_CPU = g_quark_from_string("cpu");
1109 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1110 LTTV_STATS_MODES = g_quark_from_string("modes");
1111 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
1112 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1113 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1114 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
1115 LTTV_STATS_EVENTS = g_quark_from_string("events");
1116 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1117 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1118 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 1119 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1120 LTTV_STATS = g_quark_from_string("statistics");
1121 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1122 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 1123}
1124
1125static void module_destroy()
1126{
1127}
1128
1129
1130LTTV_MODULE("stats", "Compute processes statistics", \
1131 "Accumulate statistics for event types, processes and CPUs", \
1132 module_init, module_destroy, "state");
f95bc830 1133
1134/* Change the places where stats are called (create/read/write stats)
1135
1136 Check for options in batchtest.c to reduce writing and see what tests are
1137 best candidates for performance analysis. Once OK, commit, move to main
1138 and run tests. Update the gui for statistics. */
This page took 0.090181 seconds and 4 git commands to generate.