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