fix the unknown time at beginning of trace : the world should turn round now
[lttv.git] / ltt / branches / poly / lttv / lttv / stats.c
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
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <lttv/module.h>
25 #include <lttv/stats.h>
26 #include <lttv/lttv.h>
27 #include <lttv/attribute.h>
28 #include <ltt/facility.h>
29 #include <ltt/trace.h>
30 #include <ltt/event.h>
31 #include <ltt/type.h>
32
33 #define BUF_SIZE 256
34 #define MAX_64_HEX_STRING_LEN 19
35
36 GQuark
37 LTTV_STATS_PROCESS_UNKNOWN,
38 LTTV_STATS_PROCESSES,
39 LTTV_STATS_CPU,
40 LTTV_STATS_MODE_TYPES,
41 LTTV_STATS_MODES,
42 LTTV_STATS_SUBMODES,
43 LTTV_STATS_FUNCTIONS,
44 LTTV_STATS_EVENT_TYPES,
45 LTTV_STATS_CPU_TIME,
46 LTTV_STATS_CUMULATIVE_CPU_TIME,
47 LTTV_STATS_ELAPSED_TIME,
48 LTTV_STATS_EVENTS,
49 LTTV_STATS_EVENTS_COUNT,
50 LTTV_STATS_USE_COUNT,
51 LTTV_STATS,
52 LTTV_STATS_TRACEFILES,
53 LTTV_STATS_SUMMED,
54 LTTV_STATS_BEFORE_HOOKS,
55 LTTV_STATS_AFTER_HOOKS;
56
57 static void
58 find_event_tree(LttvTracefileStats *tfcs, GQuark pid_time, guint cpu,
59 guint64 function,
60 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
61 LttvAttribute **event_types_tree);
62
63
64 static void lttv_stats_init(LttvTracesetStats *self)
65 {
66 guint i, j, nb_trace, nb_tracefile;
67
68 LttvTraceContext *tc;
69
70 LttvTraceStats *tcs;
71
72 LttvTracefileContext *tfc;
73
74 LttvTracefileContext **tfs;
75 LttvTracefileStats *tfcs;
76
77 LttTime timestamp = {0,0};
78
79 LttvAttributeValue v;
80
81 LttvAttribute
82 *stats_tree,
83 *tracefiles_stats;
84
85 LttvTraceset *ts = self->parent.parent.ts;
86
87 self->stats = lttv_attribute_find_subdir(
88 lttv_traceset_attribute(self->parent.parent.ts),
89 LTTV_STATS);
90 lttv_attribute_find(lttv_traceset_attribute(self->parent.parent.ts),
91 LTTV_STATS_USE_COUNT,
92 LTTV_UINT, &v);
93
94 (*(v.v_uint))++;
95 if(*(v.v_uint) == 1) {
96 g_assert(lttv_attribute_get_number(self->stats) == 0);
97 }
98
99 nb_trace = lttv_traceset_number(ts);
100
101 for(i = 0 ; i < nb_trace ; i++) {
102 tc = self->parent.parent.traces[i];
103 tcs = LTTV_TRACE_STATS(tc);
104
105 tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
106 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
107 LTTV_STATS_TRACEFILES);
108 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
109 LTTV_UINT, &v);
110
111 (*(v.v_uint))++;
112 if(*(v.v_uint) == 1) {
113 g_assert(lttv_attribute_get_number(tcs->stats) == 0);
114 }
115
116 nb_tracefile = tc->tracefiles->len;
117
118 for(j = 0 ; j < nb_tracefile ; j++) {
119 tfs = &g_array_index(tc->tracefiles,
120 LttvTracefileContext*, j);
121 tfcs = LTTV_TRACEFILE_STATS(*tfs);
122 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
123 ltt_tracefile_long_name(tfcs->parent.parent.tf));
124 guint cpu = tfcs->parent.cpu;
125 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
126 cpu,
127 0x0ULL,
128 LTTV_STATE_MODE_UNKNOWN,
129 LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
130 &tfcs->current_event_types_tree);
131 }
132 }
133
134 }
135
136 static void lttv_stats_fini(LttvTracesetStats *self)
137 {
138 guint i, j, nb_trace, nb_tracefile;
139
140 LttvTraceset *ts;
141
142 LttvTraceContext *tc;
143
144 LttvTraceStats *tcs;
145
146 LttvTracefileContext *tfc;
147
148 LttvTracefileStats *tfcs;
149
150 LttTime timestamp = {0,0};
151
152 LttvAttributeValue v;
153
154 LttvAttribute *tracefiles_stats;
155
156 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
157 LTTV_UINT, &v);
158 (*(v.v_uint))--;
159
160 if(*(v.v_uint) == 0) {
161 lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
162 }
163 self->stats = NULL;
164
165 ts = self->parent.parent.ts;
166 nb_trace = lttv_traceset_number(ts);
167
168 for(i = 0 ; i < nb_trace ; i++) {
169 tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]));
170
171 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
172 LTTV_UINT, &v);
173 (*(v.v_uint))--;
174
175 if(*(v.v_uint) == 0) {
176 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
177 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
178 LTTV_STATS_TRACEFILES);
179 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,
180 LTTV_STATS_TRACEFILES);
181 }
182 tcs->stats = NULL;
183
184 nb_tracefile = tc->tracefiles->len;
185
186 for(j = 0 ; j < nb_tracefile ; j++) {
187 tfc = g_array_index(tc->tracefiles,
188 LttvTracefileContext*, j);
189 tfcs = (LttvTracefileStats *)tfc;
190 tfcs->stats = NULL;
191 tfcs->current_events_tree = NULL;
192 tfcs->current_event_types_tree = NULL;
193 }
194 }
195 }
196
197
198 void lttv_stats_reset(LttvTracesetStats *self)
199 {
200 lttv_stats_fini(self);
201 lttv_stats_init(self);
202 }
203
204
205
206 static void
207 init(LttvTracesetStats *self, LttvTraceset *ts)
208 {
209 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
210 init((LttvTracesetContext *)self, ts);
211
212 lttv_stats_init(self);
213 }
214
215
216 static void
217 fini(LttvTracesetStats *self)
218 {
219 lttv_stats_fini(self);
220
221 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
222 fini((LttvTracesetContext *)self);
223 }
224
225
226 static LttvTracesetContext *
227 new_traceset_context(LttvTracesetContext *self)
228 {
229 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
230 }
231
232
233 static LttvTraceContext *
234 new_trace_context(LttvTracesetContext *self)
235 {
236 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
237 }
238
239
240 static LttvTracefileContext *
241 new_tracefile_context(LttvTracesetContext *self)
242 {
243 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
244 }
245
246
247 static void
248 traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
249 {
250 }
251
252
253 static void
254 traceset_stats_finalize (LttvTracesetStats *self)
255 {
256 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
257 finalize(G_OBJECT(self));
258 }
259
260
261 static void
262 traceset_stats_class_init (LttvTracesetContextClass *klass)
263 {
264 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
265
266 gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
267 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
268 klass->fini = (void (*)(LttvTracesetContext *self))fini;
269 klass->new_traceset_context = new_traceset_context;
270 klass->new_trace_context = new_trace_context;
271 klass->new_tracefile_context = new_tracefile_context;
272 }
273
274
275 GType
276 lttv_traceset_stats_get_type(void)
277 {
278 static GType type = 0;
279 if (type == 0) {
280 static const GTypeInfo info = {
281 sizeof (LttvTracesetStatsClass),
282 NULL, /* base_init */
283 NULL, /* base_finalize */
284 (GClassInitFunc) traceset_stats_class_init, /* class_init */
285 NULL, /* class_finalize */
286 NULL, /* class_data */
287 sizeof (LttvTracesetStats),
288 0, /* n_preallocs */
289 (GInstanceInitFunc) traceset_stats_instance_init, /* instance_init */
290 NULL /* Value handling */
291 };
292
293 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE,
294 "LttvTracesetStatsType",
295 &info, 0);
296 }
297 return type;
298 }
299
300
301 static void
302 trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
303 {
304 }
305
306
307 static void
308 trace_stats_finalize (LttvTraceStats *self)
309 {
310 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
311 finalize(G_OBJECT(self));
312 }
313
314
315 static void
316 trace_stats_class_init (LttvTraceContextClass *klass)
317 {
318 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
319
320 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
321 }
322
323
324 GType
325 lttv_trace_stats_get_type(void)
326 {
327 static GType type = 0;
328 if (type == 0) {
329 static const GTypeInfo info = {
330 sizeof (LttvTraceStatsClass),
331 NULL, /* base_init */
332 NULL, /* base_finalize */
333 (GClassInitFunc) trace_stats_class_init, /* class_init */
334 NULL, /* class_finalize */
335 NULL, /* class_data */
336 sizeof (LttvTraceStats),
337 0, /* n_preallocs */
338 (GInstanceInitFunc) trace_stats_instance_init, /* instance_init */
339 NULL /* Value handling */
340 };
341
342 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
343 "LttvTraceStatsType", &info, 0);
344 }
345 return type;
346 }
347
348
349 static void
350 tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
351 {
352 }
353
354
355 static void
356 tracefile_stats_finalize (LttvTracefileStats *self)
357 {
358 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
359 finalize(G_OBJECT(self));
360 }
361
362
363 static void
364 tracefile_stats_class_init (LttvTracefileStatsClass *klass)
365 {
366 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
367
368 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
369 }
370
371
372 GType
373 lttv_tracefile_stats_get_type(void)
374 {
375 static GType type = 0;
376 if (type == 0) {
377 static const GTypeInfo info = {
378 sizeof (LttvTracefileStatsClass),
379 NULL, /* base_init */
380 NULL, /* base_finalize */
381 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
382 NULL, /* class_finalize */
383 NULL, /* class_data */
384 sizeof (LttvTracefileStats),
385 0, /* n_preallocs */
386 (GInstanceInitFunc) tracefile_stats_instance_init, /* instance_init */
387 NULL /* Value handling */
388 };
389
390 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
391 "LttvTracefileStatsType", &info, 0);
392 }
393 return type;
394 }
395
396
397 static void
398 find_event_tree(LttvTracefileStats *tfcs,
399 GQuark pid_time,
400 guint cpu,
401 guint64 function,
402 GQuark mode,
403 GQuark sub_mode,
404 LttvAttribute **events_tree,
405 LttvAttribute **event_types_tree)
406 {
407 LttvAttribute *a, *prev_a;
408 gchar fstring[MAX_64_HEX_STRING_LEN];
409 gint ret;
410
411 ret = snprintf(fstring, MAX_64_HEX_STRING_LEN-1,
412 "0x%llX", function) > 0;
413 g_assert(ret > 0);
414 fstring[MAX_64_HEX_STRING_LEN-1] = '\0';
415
416 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
417 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
418 a = lttv_attribute_find_subdir(a, pid_time);
419 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
420 a = lttv_attribute_find_subdir_unnamed(a, cpu);
421 a = lttv_attribute_find_subdir(a, LTTV_STATS_FUNCTIONS);
422 a = lttv_attribute_find_subdir(a, g_quark_from_string(fstring));
423 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
424 a = lttv_attribute_find_subdir(a, mode);
425 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
426 a = lttv_attribute_find_subdir(a, sub_mode);
427 *events_tree = a;
428 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
429 *event_types_tree = a;
430 }
431
432
433 static void update_event_tree(LttvTracefileStats *tfcs)
434 {
435 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
436 guint cpu = tfcs->parent.cpu;
437 LttvProcessState *process = ts->running_process[cpu];
438 LttvExecutionState *es = process->state;
439
440 find_event_tree(tfcs, process->pid_time,
441 cpu,
442 process->current_function,
443 es->t, es->n, &(tfcs->current_events_tree),
444 &(tfcs->current_event_types_tree));
445 }
446
447
448 static void mode_change(LttvTracefileStats *tfcs)
449 {
450 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
451 guint cpu = tfcs->parent.cpu;
452 LttvProcessState *process = ts->running_process[cpu];
453 LttvAttributeValue cpu_time, cum_cpu_time;
454
455 LttTime delta;
456
457 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
458 process->state->change);
459
460 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
461 LTTV_TIME, &cpu_time);
462 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
463
464 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
465 delta);
466 }
467
468 /* Note : every mode_end must come with a cumulative cpu time update in the
469 * after hook */
470 static void mode_end(LttvTracefileStats *tfcs)
471 {
472 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
473 guint cpu = tfcs->parent.cpu;
474 LttvProcessState *process = ts->running_process[cpu];
475 LttvAttributeValue elapsed_time, cpu_time, cum_cpu_time;
476
477 LttTime delta;
478
479 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
480 LTTV_TIME, &elapsed_time);
481 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
482 process->state->entry);
483 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
484
485 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
486 LTTV_TIME, &cpu_time);
487 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
488 process->state->change);
489 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
490 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
491 delta);
492
493 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CUMULATIVE_CPU_TIME,
494 LTTV_TIME, &cum_cpu_time);
495 *(cum_cpu_time.v_time) = ltt_time_add(*(cum_cpu_time.v_time),
496 process->state->cum_cpu_time);
497 }
498
499
500 static void after_mode_end(LttvTracefileStats *tfcs)
501 {
502 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
503 guint cpu = tfcs->parent.cpu;
504 LttvProcessState *process = ts->running_process[cpu];
505 LttvAttributeValue cum_cpu_time;
506
507 LttTime nested_delta;
508
509 nested_delta = process->state->cum_cpu_time;
510 process->state->cum_cpu_time = ltt_time_zero; /* For after traceset hook */
511
512 update_event_tree(tfcs);
513
514 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
515 nested_delta);
516 }
517
518 static gboolean before_syscall_entry(void *hook_data, void *call_data)
519 {
520 mode_change((LttvTracefileStats *)call_data);
521 return FALSE;
522 }
523
524
525 static gboolean after_syscall_entry(void *hook_data, void *call_data)
526 {
527 update_event_tree((LttvTracefileStats *)call_data);
528 return FALSE;
529 }
530
531
532 gboolean before_syscall_exit(void *hook_data, void *call_data)
533 {
534 mode_end((LttvTracefileStats *)call_data);
535 return FALSE;
536 }
537
538
539 static gboolean after_syscall_exit(void *hook_data, void *call_data)
540 {
541 after_mode_end((LttvTracefileStats *)call_data);
542 return FALSE;
543 }
544
545
546 gboolean before_trap_entry(void *hook_data, void *call_data)
547 {
548 mode_change((LttvTracefileStats *)call_data);
549 return FALSE;
550 }
551
552
553 static gboolean after_trap_entry(void *hook_data, void *call_data)
554 {
555 update_event_tree((LttvTracefileStats *)call_data);
556 return FALSE;
557 }
558
559
560 gboolean before_trap_exit(void *hook_data, void *call_data)
561 {
562 mode_end((LttvTracefileStats *)call_data);
563 return FALSE;
564 }
565
566
567 gboolean after_trap_exit(void *hook_data, void *call_data)
568 {
569 after_mode_end((LttvTracefileStats *)call_data);
570 return FALSE;
571 }
572
573
574 gboolean before_irq_entry(void *hook_data, void *call_data)
575 {
576 mode_change((LttvTracefileStats *)call_data);
577 return FALSE;
578 }
579
580 gboolean after_irq_entry(void *hook_data, void *call_data)
581 {
582 update_event_tree((LttvTracefileStats *)call_data);
583 return FALSE;
584 }
585
586
587 gboolean before_irq_exit(void *hook_data, void *call_data)
588 {
589 mode_end((LttvTracefileStats *)call_data);
590 return FALSE;
591 }
592
593
594 gboolean after_irq_exit(void *hook_data, void *call_data)
595 {
596 after_mode_end((LttvTracefileStats *)call_data);
597 return FALSE;
598 }
599
600
601 gboolean before_soft_irq_entry(void *hook_data, void *call_data)
602 {
603 mode_change((LttvTracefileStats *)call_data);
604 return FALSE;
605 }
606
607 gboolean after_soft_irq_entry(void *hook_data, void *call_data)
608 {
609 update_event_tree((LttvTracefileStats *)call_data);
610 return FALSE;
611 }
612
613
614 gboolean before_soft_irq_exit(void *hook_data, void *call_data)
615 {
616 mode_end((LttvTracefileStats *)call_data);
617 return FALSE;
618 }
619
620
621 gboolean after_soft_irq_exit(void *hook_data, void *call_data)
622 {
623 after_mode_end((LttvTracefileStats *)call_data);
624 return FALSE;
625 }
626
627 gboolean before_function_entry(void *hook_data, void *call_data)
628 {
629 mode_change((LttvTracefileStats *)call_data);
630 return FALSE;
631 }
632
633 gboolean after_function_entry(void *hook_data, void *call_data)
634 {
635 update_event_tree((LttvTracefileStats *)call_data);
636 return FALSE;
637 }
638
639 gboolean before_function_exit(void *hook_data, void *call_data)
640 {
641 mode_end((LttvTracefileStats *)call_data);
642 return FALSE;
643 }
644
645 gboolean after_function_exit(void *hook_data, void *call_data)
646 {
647 after_mode_end((LttvTracefileStats *)call_data);
648 return FALSE;
649 }
650
651
652 gboolean before_schedchange(void *hook_data, void *call_data)
653 {
654 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
655
656 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
657
658 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
659
660 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
661
662 guint pid_in, pid_out;
663
664 gint state_out;
665
666 pid_out = ltt_event_get_unsigned(e, thf->f1);
667 pid_in = ltt_event_get_unsigned(e, thf->f2);
668 state_out = ltt_event_get_int(e, thf->f3);
669
670 /* compute the time for the process to schedule out */
671
672 mode_change(tfcs);
673
674 return FALSE;
675 }
676
677 gboolean after_schedchange(void *hook_data, void *call_data)
678 {
679 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
680
681 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
682
683 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
684
685 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
686
687 guint pid_in, pid_out;
688
689 gint state_out;
690
691 LttvProcessState *process;
692
693 pid_out = ltt_event_get_unsigned(e, thf->f1);
694 pid_in = ltt_event_get_unsigned(e, thf->f2);
695 state_out = ltt_event_get_int(e, thf->f3);
696
697 /* get the information for the process scheduled in */
698 guint cpu = tfcs->parent.cpu;
699 process = ts->running_process[cpu];
700
701 find_event_tree(tfcs, process->pid_time,
702 cpu,
703 process->current_function,
704 process->state->t, process->state->n, &(tfcs->current_events_tree),
705 &(tfcs->current_event_types_tree));
706
707 /* compute the time waiting for the process to schedule in */
708 mode_change(tfcs);
709
710 return FALSE;
711 }
712
713 gboolean process_fork(void *hook_data, void *call_data)
714 {
715 /* nothing to do for now */
716 return FALSE;
717 }
718
719
720 gboolean process_exit(void *hook_data, void *call_data)
721 {
722 /* We should probably exit all modes here or we could do that at
723 schedule out. */
724 return FALSE;
725 }
726
727 gboolean before_enum_process_state(void *hook_data, void *call_data)
728 {
729 mode_end((LttvTracefileStats *)call_data);
730 after_mode_end((LttvTracefileStats *)call_data);
731 mode_change((LttvTracefileStats *)call_data);
732 return FALSE;
733 }
734
735 gboolean after_enum_process_state(void *hook_data, void *call_data)
736 {
737 update_event_tree((LttvTracefileStats *)call_data);
738 return FALSE;
739 }
740
741 gboolean process_free(void *hook_data, void *call_data)
742 {
743 return FALSE;
744 }
745
746 gboolean every_event(void *hook_data, void *call_data)
747 {
748 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
749
750 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
751
752 LttvAttributeValue v;
753
754 /* The current branch corresponds to the tracefile/process/interrupt state.
755 Statistics are added within it, to count the number of events of this
756 type occuring in this context. A quark has been pre-allocated for each
757 event type and is used as name. */
758
759 lttv_attribute_find(tfcs->current_event_types_tree,
760 ltt_eventtype_name(ltt_event_eventtype(e)),
761 LTTV_UINT, &v);
762 (*(v.v_uint))++;
763 return FALSE;
764 }
765
766 static void lttv_stats_cleanup_process_state(gpointer key, gpointer value,
767 gpointer user_data)
768 {
769 LttvTraceStats *tcs = (LttvTraceStats *)user_data;
770 LttvTraceState *ts = (LttvTraceState *)user_data;
771 LttvTracesetContext *tsc = ts->parent.ts_context;
772 LttvProcessState *process = (LttvProcessState *)value;
773 int i;
774 LttvTracefileStats **tfs = (LttvTracefileStats **)
775 &g_array_index(ts->parent.tracefiles, LttvTracefileContext*,
776 process->cpu);
777 int cleanup_empty = 0;
778 LttTime nested_delta = ltt_time_zero;
779 /* FIXME : ok, this is a hack. The time is infinite here :( */
780 LttTime save_time = (*tfs)->parent.parent.timestamp;
781 LttTime start, end;
782 ltt_trace_time_span_get(ts->parent.t, &start, &end);
783 (*tfs)->parent.parent.timestamp = end;
784
785 do {
786 if(ltt_time_compare(process->state->cum_cpu_time, ltt_time_zero) != 0) {
787 find_event_tree(*tfs, process->pid_time,
788 process->cpu,
789 process->current_function,
790 process->state->t, process->state->n, &((*tfs)->current_events_tree),
791 &((*tfs)->current_event_types_tree));
792 mode_end(*tfs);
793 nested_delta = process->state->cum_cpu_time;
794 }
795 cleanup_empty = lttv_state_pop_state_cleanup(process,
796 (LttvTracefileState *)*tfs);
797 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
798 nested_delta);
799
800 } while(cleanup_empty != 1);
801
802 (*tfs)->parent.parent.timestamp = save_time;
803 }
804
805 /* For each process in the state, for each of their stacked states,
806 * perform sum of needed values. */
807 static void lttv_stats_cleanup_state(LttvTraceStats *tcs)
808 {
809 LttvTraceState *ts = (LttvTraceState *)tcs;
810
811 /* Does not work correctly FIXME. */
812 g_hash_table_foreach(ts->processes, lttv_stats_cleanup_process_state,
813 tcs);
814 }
815
816 void
817 lttv_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats)
818 {
819 LttvAttribute *sum_container = self->stats;
820
821 LttvAttributeType type;
822
823 LttvAttributeValue value;
824
825 LttvAttributeName name;
826
827 gboolean is_named;
828
829 unsigned sum;
830
831 int trace_is_summed;
832
833 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
834 nb_event_type, nf, nb_functions;
835
836 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
837 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
838 *submode_tree, *event_types_tree, *mode_events_tree,
839 *cpu_functions_tree,
840 *function_tree,
841 *function_mode_types_tree,
842 *trace_cpu_tree;
843
844
845 main_tree = sum_container;
846
847 lttv_attribute_find(sum_container,
848 LTTV_STATS_SUMMED,
849 LTTV_UINT, &value);
850 trace_is_summed = *(value.v_uint);
851 *(value.v_uint) = 1;
852
853 /* First cleanup the state : sum all stalled information (never ending
854 * states). */
855 if(!trace_is_summed)
856 lttv_stats_cleanup_state(self);
857
858 processes_tree = lttv_attribute_find_subdir(main_tree,
859 LTTV_STATS_PROCESSES);
860 nb_process = lttv_attribute_get_number(processes_tree);
861
862 for(i = 0 ; i < nb_process ; i++) {
863 type = lttv_attribute_get(processes_tree, i, &name, &value, &is_named);
864 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
865
866 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
867 nb_cpu = lttv_attribute_get_number(cpus_tree);
868
869 for(j = 0 ; j < nb_cpu ; j++) {
870 type = lttv_attribute_get(cpus_tree, j, &name, &value, &is_named);
871 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
872
873 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
874 trace_cpu_tree = lttv_attribute_find_subdir_unnamed(trace_cpu_tree, name);
875 cpu_functions_tree = lttv_attribute_find_subdir(cpu_tree,
876 LTTV_STATS_FUNCTIONS);
877 nb_functions = lttv_attribute_get_number(cpu_functions_tree);
878
879 for(nf=0; nf < nb_functions; nf++) {
880 type = lttv_attribute_get(cpu_functions_tree, nf, &name, &value,
881 &is_named);
882 function_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
883 function_mode_types_tree = lttv_attribute_find_subdir(function_tree,
884 LTTV_STATS_MODE_TYPES);
885 nb_mode_type = lttv_attribute_get_number(function_mode_types_tree);
886 for(k = 0 ; k < nb_mode_type ; k++) {
887 type = lttv_attribute_get(function_mode_types_tree, k, &name, &value,
888 &is_named);
889 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
890
891 submodes_tree = lttv_attribute_find_subdir(mode_tree,
892 LTTV_STATS_SUBMODES);
893 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
894 LTTV_STATS_EVENTS);
895 mode_types_tree = lttv_attribute_find_subdir(mode_tree,
896 LTTV_STATS_MODE_TYPES);
897
898 nb_submode = lttv_attribute_get_number(submodes_tree);
899
900 for(l = 0 ; l < nb_submode ; l++) {
901 type = lttv_attribute_get(submodes_tree, l, &name, &value,
902 &is_named);
903 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
904
905 event_types_tree = lttv_attribute_find_subdir(submode_tree,
906 LTTV_STATS_EVENT_TYPES);
907 nb_event_type = lttv_attribute_get_number(event_types_tree);
908
909 sum = 0;
910 for(m = 0 ; m < nb_event_type ; m++) {
911 type = lttv_attribute_get(event_types_tree, m, &name, &value,
912 &is_named);
913 sum += *(value.v_uint);
914 }
915 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
916 LTTV_UINT, &value);
917 *(value.v_uint) = sum;
918
919 type = lttv_attribute_get(submodes_tree, l, &name, &value,
920 &is_named);
921 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
922 if(!trace_is_summed) {
923 lttv_attribute_recursive_add(mode_events_tree, event_types_tree);
924 lttv_attribute_recursive_add(mode_types_tree, submode_tree);
925 }
926 }
927 if(!trace_is_summed) {
928 lttv_attribute_recursive_add(function_tree, mode_types_tree);
929 }
930 }
931 if(!trace_is_summed) {
932 lttv_attribute_recursive_add(cpu_tree, function_tree);
933 lttv_attribute_recursive_add(process_tree, function_tree);
934 lttv_attribute_recursive_add(trace_cpu_tree, function_tree);
935 lttv_attribute_recursive_add(main_tree, function_tree);
936 }
937 lttv_attribute_recursive_add(ts_stats, function_tree);
938 }
939 }
940 }
941 }
942
943
944 gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
945 {
946 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
947 return 0;
948 }
949
950 void
951 lttv_stats_sum_traceset(LttvTracesetStats *self)
952 {
953 LttvTraceset *traceset = self->parent.parent.ts;
954 LttvAttribute *sum_container = self->stats;
955
956 LttvTraceStats *tcs;
957
958 int i, nb_trace;
959
960 LttvAttribute *main_tree;
961
962 LttvAttributeValue value;
963
964 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
965 LTTV_UINT, &value);
966 if(*(value.v_uint) != 0) return;
967 *(value.v_uint) = 1;
968
969 nb_trace = lttv_traceset_number(traceset);
970
971 for(i = 0 ; i < nb_trace ; i++) {
972 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
973 lttv_stats_sum_trace(tcs, self->stats);
974 // lttv_attribute_recursive_add(sum_container, tcs->stats);
975 }
976 }
977
978
979 // Hook wrapper. call_data is a traceset context.
980 gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
981 {
982 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
983
984 lttv_stats_add_event_hooks(tss);
985
986 return 0;
987 }
988
989 void lttv_stats_add_event_hooks(LttvTracesetStats *self)
990 {
991 LttvTraceset *traceset = self->parent.parent.ts;
992
993 guint i, j, k, l, nb_trace, nb_tracefile;
994
995 LttvTraceStats *ts;
996
997 LttvTracefileStats *tfs;
998
999 GArray *hooks, *before_hooks, *after_hooks;
1000
1001 LttvTraceHook *hook;
1002
1003 LttvTraceHookByFacility *thf;
1004
1005 LttvAttributeValue val;
1006
1007 gint ret;
1008 gint hn;
1009
1010 nb_trace = lttv_traceset_number(traceset);
1011 for(i = 0 ; i < nb_trace ; i++) {
1012 ts = (LttvTraceStats *)self->parent.parent.traces[i];
1013
1014 /* Find the eventtype id for the following events and register the
1015 associated by id hooks. */
1016
1017 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 12);
1018 g_array_set_size(hooks, 12);
1019 hn=0;
1020
1021 ret = lttv_trace_find_hook(ts->parent.parent.t,
1022 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
1023 LTT_FIELD_SYSCALL_ID, 0, 0,
1024 before_syscall_entry, NULL,
1025 &g_array_index(hooks, LttvTraceHook, hn++));
1026 if(ret) hn--;
1027
1028 ret = lttv_trace_find_hook(ts->parent.parent.t,
1029 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
1030 0, 0, 0,
1031 before_syscall_exit, NULL,
1032 &g_array_index(hooks, LttvTraceHook, hn++));
1033 if(ret) hn--;
1034
1035 ret = lttv_trace_find_hook(ts->parent.parent.t,
1036 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1037 LTT_FIELD_TRAP_ID, 0, 0,
1038 before_trap_entry, NULL,
1039 &g_array_index(hooks, LttvTraceHook, hn++));
1040 if(ret) hn--;
1041
1042 ret = lttv_trace_find_hook(ts->parent.parent.t,
1043 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1044 0, 0, 0,
1045 before_trap_exit, NULL,
1046 &g_array_index(hooks, LttvTraceHook, hn++));
1047 if(ret) hn--;
1048
1049 ret = lttv_trace_find_hook(ts->parent.parent.t,
1050 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1051 LTT_FIELD_IRQ_ID, 0, 0,
1052 before_irq_entry, NULL,
1053 &g_array_index(hooks, LttvTraceHook, hn++));
1054 if(ret) hn--;
1055
1056 ret = lttv_trace_find_hook(ts->parent.parent.t,
1057 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1058 0, 0, 0,
1059 before_irq_exit, NULL,
1060 &g_array_index(hooks, LttvTraceHook, hn++));
1061 if(ret) hn--;
1062
1063 ret = lttv_trace_find_hook(ts->parent.parent.t,
1064 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1065 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1066 before_soft_irq_entry, NULL,
1067 &g_array_index(hooks, LttvTraceHook, hn++));
1068 if(ret) hn--;
1069
1070 ret = lttv_trace_find_hook(ts->parent.parent.t,
1071 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1072 0, 0, 0,
1073 before_soft_irq_exit, NULL,
1074 &g_array_index(hooks, LttvTraceHook, hn++));
1075 if(ret) hn--;
1076
1077 ret = lttv_trace_find_hook(ts->parent.parent.t,
1078 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1079 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1080 before_schedchange, NULL,
1081 &g_array_index(hooks, LttvTraceHook, hn++));
1082 if(ret) hn--;
1083
1084 ret = lttv_trace_find_hook(ts->parent.parent.t,
1085 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1086 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1087 before_function_entry, NULL,
1088 &g_array_index(hooks, LttvTraceHook, hn++));
1089 if(ret) hn--;
1090
1091 ret = lttv_trace_find_hook(ts->parent.parent.t,
1092 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1093 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1094 before_function_exit, NULL,
1095 &g_array_index(hooks, LttvTraceHook, hn++));
1096 if(ret) hn--;
1097
1098 /* statedump-related hooks */
1099 ret = lttv_trace_find_hook(ts->parent.parent.t,
1100 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1101 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1102 before_enum_process_state, NULL,
1103 &g_array_index(hooks, LttvTraceHook, hn++));
1104 if(ret) hn--;
1105
1106 g_array_set_size(hooks, hn);
1107
1108 before_hooks = hooks;
1109
1110 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 15);
1111 g_array_set_size(hooks, 15);
1112 hn=0;
1113
1114 ret = lttv_trace_find_hook(ts->parent.parent.t,
1115 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
1116 LTT_FIELD_SYSCALL_ID, 0, 0,
1117 after_syscall_entry, NULL,
1118 &g_array_index(hooks, LttvTraceHook, hn++));
1119 if(ret) hn--;
1120
1121 ret = lttv_trace_find_hook(ts->parent.parent.t,
1122 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
1123 0, 0, 0,
1124 after_syscall_exit, NULL,
1125 &g_array_index(hooks, LttvTraceHook, hn++));
1126 if(ret) hn--;
1127
1128 ret = lttv_trace_find_hook(ts->parent.parent.t,
1129 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1130 LTT_FIELD_TRAP_ID, 0, 0,
1131 after_trap_entry, NULL,
1132 &g_array_index(hooks, LttvTraceHook, hn++));
1133 if(ret) hn--;
1134
1135 ret = lttv_trace_find_hook(ts->parent.parent.t,
1136 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1137 0, 0, 0,
1138 after_trap_exit, NULL,
1139 &g_array_index(hooks, LttvTraceHook, hn++));
1140 if(ret) hn--;
1141
1142 ret = lttv_trace_find_hook(ts->parent.parent.t,
1143 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1144 LTT_FIELD_IRQ_ID, 0, 0,
1145 after_irq_entry, NULL,
1146 &g_array_index(hooks, LttvTraceHook, hn++));
1147 if(ret) hn--;
1148
1149 ret = lttv_trace_find_hook(ts->parent.parent.t,
1150 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1151 0, 0, 0,
1152 after_irq_exit, NULL,
1153 &g_array_index(hooks, LttvTraceHook, hn++));
1154 if(ret) hn--;
1155
1156 ret = lttv_trace_find_hook(ts->parent.parent.t,
1157 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1158 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1159 after_irq_entry, NULL,
1160 &g_array_index(hooks, LttvTraceHook, hn++));
1161 if(ret) hn--;
1162
1163 ret = lttv_trace_find_hook(ts->parent.parent.t,
1164 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1165 0, 0, 0,
1166 after_soft_irq_exit, NULL,
1167 &g_array_index(hooks, LttvTraceHook, hn++));
1168 if(ret) hn--;
1169
1170 ret = lttv_trace_find_hook(ts->parent.parent.t,
1171 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1172 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1173 after_schedchange, NULL,
1174 &g_array_index(hooks, LttvTraceHook, hn++));
1175 if(ret) hn--;
1176
1177 ret = lttv_trace_find_hook(ts->parent.parent.t,
1178 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1179 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
1180 process_fork, NULL,
1181 &g_array_index(hooks, LttvTraceHook, hn++));
1182 if(ret) hn--;
1183
1184 ret = lttv_trace_find_hook(ts->parent.parent.t,
1185 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1186 LTT_FIELD_PID, 0, 0,
1187 process_exit, NULL,
1188 &g_array_index(hooks, LttvTraceHook, hn++));
1189 if(ret) hn--;
1190
1191 ret = lttv_trace_find_hook(ts->parent.parent.t,
1192 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1193 LTT_FIELD_PID, 0, 0,
1194 process_free, NULL,
1195 &g_array_index(hooks, LttvTraceHook, hn++));
1196 if(ret) hn--;
1197
1198 ret = lttv_trace_find_hook(ts->parent.parent.t,
1199 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1200 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1201 after_function_entry, NULL,
1202 &g_array_index(hooks, LttvTraceHook, hn++));
1203 if(ret) hn--;
1204
1205 ret = lttv_trace_find_hook(ts->parent.parent.t,
1206 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1207 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1208 after_function_exit, NULL,
1209 &g_array_index(hooks, LttvTraceHook, hn++));
1210 if(ret) hn--;
1211
1212 /* statedump-related hooks */
1213 ret = lttv_trace_find_hook(ts->parent.parent.t,
1214 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1215 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1216 after_enum_process_state, NULL,
1217 &g_array_index(hooks, LttvTraceHook, hn++));
1218 if(ret) hn--;
1219
1220 g_array_set_size(hooks, hn);
1221
1222 after_hooks = hooks;
1223
1224 /* Add these hooks to each event_by_id hooks list */
1225
1226 nb_tracefile = ts->parent.parent.tracefiles->len;
1227
1228 for(j = 0 ; j < nb_tracefile ; j++) {
1229 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1230 LttvTracefileContext*, j));
1231 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
1232 LTTV_PRIO_DEFAULT);
1233
1234 for(k = 0 ; k < before_hooks->len ; k++) {
1235 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1236 for(l = 0; l<hook->fac_list->len;l++) {
1237 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1238 lttv_hooks_add(
1239 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1240 thf->h,
1241 thf,
1242 LTTV_PRIO_STATS_BEFORE_STATE);
1243 }
1244 }
1245 for(k = 0 ; k < after_hooks->len ; k++) {
1246 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1247 for(l = 0; l<hook->fac_list->len;l++) {
1248 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1249 lttv_hooks_add(
1250 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1251 thf->h,
1252 thf,
1253 LTTV_PRIO_STATS_AFTER_STATE);
1254 }
1255 }
1256 }
1257 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1258 LTTV_POINTER, &val);
1259 *(val.v_pointer) = before_hooks;
1260 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1261 LTTV_POINTER, &val);
1262 *(val.v_pointer) = after_hooks;
1263 }
1264 }
1265
1266 // Hook wrapper. call_data is a traceset context.
1267 gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
1268 {
1269 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1270
1271 lttv_stats_remove_event_hooks(tss);
1272
1273 return 0;
1274 }
1275
1276 void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
1277 {
1278 LttvTraceset *traceset = self->parent.parent.ts;
1279
1280 guint i, j, k, l, nb_trace, nb_tracefile;
1281
1282 LttvTraceStats *ts;
1283
1284 LttvTracefileStats *tfs;
1285
1286 void *hook_data;
1287
1288 GArray *before_hooks, *after_hooks;
1289
1290 LttvTraceHook *hook;
1291
1292 LttvTraceHookByFacility *thf;
1293
1294 LttvAttributeValue val;
1295
1296 nb_trace = lttv_traceset_number(traceset);
1297 for(i = 0 ; i < nb_trace ; i++) {
1298 ts = (LttvTraceStats*)self->parent.parent.traces[i];
1299 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1300 LTTV_POINTER, &val);
1301 before_hooks = *(val.v_pointer);
1302 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1303 LTTV_POINTER, &val);
1304 after_hooks = *(val.v_pointer);
1305
1306 /* Remove these hooks from each event_by_id hooks list */
1307
1308 nb_tracefile = ts->parent.parent.tracefiles->len;
1309
1310 for(j = 0 ; j < nb_tracefile ; j++) {
1311 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1312 LttvTracefileContext*, j));
1313 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
1314 NULL);
1315
1316 for(k = 0 ; k < before_hooks->len ; k++) {
1317 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1318 for(l = 0 ; l < hook->fac_list->len ; l++) {
1319 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1320 lttv_hooks_remove_data(
1321 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1322 thf->h,
1323 thf);
1324 }
1325 }
1326 for(k = 0 ; k < after_hooks->len ; k++) {
1327 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1328 for(l = 0 ; l < hook->fac_list->len ; l++) {
1329 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1330 lttv_hooks_remove_data(
1331 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1332 thf->h,
1333 thf);
1334 }
1335 }
1336 }
1337 g_debug("lttv_stats_remove_event_hooks()");
1338 g_array_free(before_hooks, TRUE);
1339 g_array_free(after_hooks, TRUE);
1340 }
1341 }
1342
1343
1344 static void module_init()
1345 {
1346 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1347 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1348 LTTV_STATS_CPU = g_quark_from_string("cpu");
1349 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1350 LTTV_STATS_MODES = g_quark_from_string("modes");
1351 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
1352 LTTV_STATS_FUNCTIONS = g_quark_from_string("functions");
1353 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1354 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1355 LTTV_STATS_CUMULATIVE_CPU_TIME = g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1356 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time (includes per process waiting time)");
1357 LTTV_STATS_EVENTS = g_quark_from_string("events");
1358 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1359 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1360 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
1361 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1362 LTTV_STATS = g_quark_from_string("statistics");
1363 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1364 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
1365 }
1366
1367 static void module_destroy()
1368 {
1369 }
1370
1371
1372 LTTV_MODULE("stats", "Compute processes statistics", \
1373 "Accumulate statistics for event types, processes and CPUs", \
1374 module_init, module_destroy, "state");
1375
1376 /* Change the places where stats are called (create/read/write stats)
1377
1378 Check for options in batchtest.c to reduce writing and see what tests are
1379 best candidates for performance analysis. Once OK, commit, move to main
1380 and run tests. Update the gui for statistics. */
This page took 0.058067 seconds and 4 git commands to generate.