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