print current function
[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;
2501204d 826 gint hn;
9d239bd9 827
b445142a 828 nb_trace = lttv_traceset_number(traceset);
829 for(i = 0 ; i < nb_trace ; i++) {
830 ts = (LttvTraceStats *)self->parent.parent.traces[i];
831
832 /* Find the eventtype id for the following events and register the
833 associated by id hooks. */
834
faf074a3 835 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 9);
836 g_array_set_size(hooks, 9);
2501204d 837 hn=0;
b445142a 838
9d239bd9 839 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 840 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 841 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 842 before_syscall_entry, NULL,
2501204d 843 &g_array_index(hooks, LttvTraceHook, hn++));
844 if(ret) hn--;
b445142a 845
9d239bd9 846 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 847 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 848 0, 0, 0,
2c82c4dc 849 before_syscall_exit, NULL,
2501204d 850 &g_array_index(hooks, LttvTraceHook, hn++));
851 if(ret) hn--;
b445142a 852
9d239bd9 853 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 854 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
855 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 856 before_trap_entry, NULL,
2501204d 857 &g_array_index(hooks, LttvTraceHook, hn++));
858 if(ret) hn--;
b445142a 859
9d239bd9 860 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 861 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
862 0, 0, 0,
2c82c4dc 863 before_trap_exit, NULL,
2501204d 864 &g_array_index(hooks, LttvTraceHook, hn++));
865 if(ret) hn--;
eed2ef37 866
9d239bd9 867 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 868 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
869 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 870 before_irq_entry, NULL,
2501204d 871 &g_array_index(hooks, LttvTraceHook, hn++));
872 if(ret) hn--;
eed2ef37 873
9d239bd9 874 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 875 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
876 0, 0, 0,
2c82c4dc 877 before_irq_exit, NULL,
2501204d 878 &g_array_index(hooks, LttvTraceHook, hn++));
879 if(ret) hn--;
eed2ef37 880
faf074a3 881 ret = lttv_trace_find_hook(ts->parent.parent.t,
882 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
883 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
884 before_soft_irq_entry, NULL,
2501204d 885 &g_array_index(hooks, LttvTraceHook, hn++));
886 if(ret) hn--;
faf074a3 887
888 ret = lttv_trace_find_hook(ts->parent.parent.t,
889 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
890 0, 0, 0,
891 before_soft_irq_exit, NULL,
2501204d 892 &g_array_index(hooks, LttvTraceHook, hn++));
893 if(ret) hn--;
faf074a3 894
9d239bd9 895 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 896 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
897 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
2c82c4dc 898 before_schedchange, NULL,
2501204d 899 &g_array_index(hooks, LttvTraceHook, hn++));
900 if(ret) hn--;
901 g_array_set_size(hooks, hn);
b445142a 902
903 before_hooks = hooks;
904
faf074a3 905 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 11);
906 g_array_set_size(hooks, 11);
2501204d 907 hn=0;
b445142a 908
9d239bd9 909 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 910 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
eed2ef37 911 LTT_FIELD_SYSCALL_ID, 0, 0,
2c82c4dc 912 after_syscall_entry, NULL,
2501204d 913 &g_array_index(hooks, LttvTraceHook, hn++));
914 if(ret) hn--;
b445142a 915
9d239bd9 916 ret = lttv_trace_find_hook(ts->parent.parent.t,
f5d7967f 917 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
eed2ef37 918 0, 0, 0,
2c82c4dc 919 after_syscall_exit, NULL,
2501204d 920 &g_array_index(hooks, LttvTraceHook, hn++));
921 if(ret) hn--;
b445142a 922
9d239bd9 923 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 924 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
925 LTT_FIELD_TRAP_ID, 0, 0,
2c82c4dc 926 after_trap_entry, NULL,
2501204d 927 &g_array_index(hooks, LttvTraceHook, hn++));
928 if(ret) hn--;
eed2ef37 929
9d239bd9 930 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 931 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
932 0, 0, 0,
2c82c4dc 933 after_trap_exit, NULL,
2501204d 934 &g_array_index(hooks, LttvTraceHook, hn++));
935 if(ret) hn--;
b445142a 936
9d239bd9 937 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 938 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
939 LTT_FIELD_IRQ_ID, 0, 0,
2c82c4dc 940 after_irq_entry, NULL,
2501204d 941 &g_array_index(hooks, LttvTraceHook, hn++));
942 if(ret) hn--;
b445142a 943
9d239bd9 944 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 945 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
946 0, 0, 0,
2c82c4dc 947 after_irq_exit, NULL,
2501204d 948 &g_array_index(hooks, LttvTraceHook, hn++));
949 if(ret) hn--;
b445142a 950
faf074a3 951 ret = lttv_trace_find_hook(ts->parent.parent.t,
952 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
953 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
954 after_irq_entry, NULL,
2501204d 955 &g_array_index(hooks, LttvTraceHook, hn++));
956 if(ret) hn--;
faf074a3 957
958 ret = lttv_trace_find_hook(ts->parent.parent.t,
959 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
960 0, 0, 0,
961 after_soft_irq_exit, NULL,
2501204d 962 &g_array_index(hooks, LttvTraceHook, hn++));
963 if(ret) hn--;
b445142a 964
9d239bd9 965 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 966 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
967 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
2c82c4dc 968 process_fork, NULL,
2501204d 969 &g_array_index(hooks, LttvTraceHook, hn++));
970 if(ret) hn--;
b445142a 971
9d239bd9 972 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 973 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
974 LTT_FIELD_PID, 0, 0,
2c82c4dc 975 process_exit, NULL,
2501204d 976 &g_array_index(hooks, LttvTraceHook, hn++));
977 if(ret) hn--;
eed2ef37 978
9d239bd9 979 ret = lttv_trace_find_hook(ts->parent.parent.t,
eed2ef37 980 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
981 LTT_FIELD_PID, 0, 0,
2c82c4dc 982 process_free, NULL,
2501204d 983 &g_array_index(hooks, LttvTraceHook, hn++));
984 if(ret) hn--;
eed2ef37 985
2501204d 986 g_array_set_size(hooks, hn);
b445142a 987
988 after_hooks = hooks;
989
359b2948 990 /* Add these hooks to each event_by_id hooks list */
b445142a 991
eed2ef37 992 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 993
dbb7bb09 994 for(j = 0 ; j < nb_tracefile ; j++) {
d7cf605c 995 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
996 LttvTracefileContext*, j));
359b2948 997 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
998 LTTV_PRIO_DEFAULT);
b445142a 999
1000 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1001 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1002 for(l = 0; l<hook->fac_list->len;l++) {
1003 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1004 lttv_hooks_add(
1005 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1006 thf->h,
d052ffc3 1007 thf,
eed2ef37 1008 LTTV_PRIO_STATS_BEFORE_STATE);
1009 }
b445142a 1010 }
1011 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1012 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1013 for(l = 0; l<hook->fac_list->len;l++) {
1014 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1015 lttv_hooks_add(
1016 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1017 thf->h,
d052ffc3 1018 thf,
eed2ef37 1019 LTTV_PRIO_STATS_AFTER_STATE);
1020 }
b445142a 1021 }
1022 }
1023 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1024 LTTV_POINTER, &val);
1025 *(val.v_pointer) = before_hooks;
1026 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1027 LTTV_POINTER, &val);
1028 *(val.v_pointer) = after_hooks;
1029 }
b445142a 1030}
1031
d3e01c7a 1032// Hook wrapper. call_data is a traceset context.
00e74b69 1033gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
d3e01c7a 1034{
1035 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1036
1037 lttv_stats_remove_event_hooks(tss);
1038
1039 return 0;
1040}
b445142a 1041
00e74b69 1042void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
b445142a 1043{
1044 LttvTraceset *traceset = self->parent.parent.ts;
1045
eed2ef37 1046 guint i, j, k, l, nb_trace, nb_tracefile;
b445142a 1047
1048 LttvTraceStats *ts;
1049
1050 LttvTracefileStats *tfs;
1051
1052 void *hook_data;
1053
1054 GArray *before_hooks, *after_hooks;
1055
eed2ef37 1056 LttvTraceHook *hook;
1057
1058 LttvTraceHookByFacility *thf;
b445142a 1059
1060 LttvAttributeValue val;
1061
1062 nb_trace = lttv_traceset_number(traceset);
1063 for(i = 0 ; i < nb_trace ; i++) {
ae80b609 1064 ts = (LttvTraceStats*)self->parent.parent.traces[i];
b445142a 1065 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1066 LTTV_POINTER, &val);
1067 before_hooks = *(val.v_pointer);
1068 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1069 LTTV_POINTER, &val);
1070 after_hooks = *(val.v_pointer);
1071
359b2948 1072 /* Remove these hooks from each event_by_id hooks list */
b445142a 1073
eed2ef37 1074 nb_tracefile = ts->parent.parent.tracefiles->len;
b445142a 1075
dbb7bb09 1076 for(j = 0 ; j < nb_tracefile ; j++) {
cb03932a 1077 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1078 LttvTracefileContext*, j));
359b2948 1079 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 1080 NULL);
1081
1082 for(k = 0 ; k < before_hooks->len ; k++) {
eed2ef37 1083 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1084 for(l = 0 ; l < hook->fac_list->len ; l++) {
1085 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1086 lttv_hooks_remove_data(
1087 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1088 thf->h,
d052ffc3 1089 thf);
eed2ef37 1090 }
b445142a 1091 }
1092 for(k = 0 ; k < after_hooks->len ; k++) {
eed2ef37 1093 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1094 for(l = 0 ; l < hook->fac_list->len ; l++) {
1095 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1096 lttv_hooks_remove_data(
1097 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1098 thf->h,
d052ffc3 1099 thf);
eed2ef37 1100 }
b445142a 1101 }
1102 }
2a2fa4f0 1103 g_debug("lttv_stats_remove_event_hooks()");
b445142a 1104 g_array_free(before_hooks, TRUE);
1105 g_array_free(after_hooks, TRUE);
1106 }
9f797243 1107}
08b1c66e 1108
1109
1110static void module_init()
1111{
1112 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1113 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1114 LTTV_STATS_CPU = g_quark_from_string("cpu");
1115 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1116 LTTV_STATS_MODES = g_quark_from_string("modes");
1117 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
302efbad 1118 LTTV_STATS_SUBMODES = g_quark_from_string("functions");
08b1c66e 1119 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1120 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1121 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
1122 LTTV_STATS_EVENTS = g_quark_from_string("events");
1123 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1124 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1125 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 1126 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1127 LTTV_STATS = g_quark_from_string("statistics");
1128 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1129 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 1130}
1131
1132static void module_destroy()
1133{
1134}
1135
1136
1137LTTV_MODULE("stats", "Compute processes statistics", \
1138 "Accumulate statistics for event types, processes and CPUs", \
1139 module_init, module_destroy, "state");
f95bc830 1140
1141/* Change the places where stats are called (create/read/write stats)
1142
1143 Check for options in batchtest.c to reduce writing and see what tests are
1144 best candidates for performance analysis. Once OK, commit, move to main
1145 and run tests. Update the gui for statistics. */
This page took 0.088564 seconds and 4 git commands to generate.