fix unknown mode elapsed time
[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 static void
397 find_event_tree(LttvTracefileStats *tfcs,
398 GQuark pid_time,
399 guint cpu,
400 guint64 function,
401 GQuark mode,
402 GQuark sub_mode,
403 LttvAttribute **events_tree,
404 LttvAttribute **event_types_tree)
405 {
406 LttvAttribute *a, *prev_a;
407 gchar fstring[MAX_64_HEX_STRING_LEN];
408 gint ret;
409
410 ret = snprintf(fstring, MAX_64_HEX_STRING_LEN-1,
411 "0x%llX", function) > 0;
412 g_assert(ret > 0);
413 fstring[MAX_64_HEX_STRING_LEN-1] = '\0';
414
415 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
416 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
417 a = lttv_attribute_find_subdir(a, pid_time);
418 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
419 a = lttv_attribute_find_subdir_unnamed(a, cpu);
420 a = lttv_attribute_find_subdir(a, LTTV_STATS_FUNCTIONS);
421 a = lttv_attribute_find_subdir(a, g_quark_from_string(fstring));
422 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
423 a = lttv_attribute_find_subdir(a, mode);
424 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
425 a = lttv_attribute_find_subdir(a, sub_mode);
426 *events_tree = a;
427 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
428 *event_types_tree = a;
429 }
430
431 static void update_event_tree(LttvTracefileStats *tfcs)
432 {
433 guint cpu = tfcs->parent.cpu;
434 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
435 LttvProcessState *process = ts->running_process[cpu];
436 LttvExecutionState *es = process->state;
437
438 find_event_tree(tfcs, process->pid_time,
439 cpu,
440 process->current_function,
441 es->t, es->n, &(tfcs->current_events_tree),
442 &(tfcs->current_event_types_tree));
443 }
444
445
446 /* Update the trace event tree for the specified cpu */
447 static void update_trace_event_tree(LttvTraceStats *tcs)
448 {
449 LttvTracefileStats *tfcs;
450 LttvTraceContext *tc = (LttvTraceContext*)tcs;
451 guint j, nb_tracefile;
452
453 /* For each tracefile, update the event tree */
454 nb_tracefile = tc->tracefiles->len;
455 for(j = 0; j < nb_tracefile; j++) {
456 tfcs = LTTV_TRACEFILE_STATS(g_array_index(tc->tracefiles,
457 LttvTracefileContext*, j));
458 update_event_tree(tfcs);
459 }
460 }
461
462 static void mode_change(LttvTracefileStats *tfcs)
463 {
464 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
465 guint cpu = tfcs->parent.cpu;
466 LttvProcessState *process = ts->running_process[cpu];
467 LttvAttributeValue cpu_time, cum_cpu_time;
468
469 LttTime delta;
470
471 if(process->state->s == LTTV_STATE_RUN &&
472 process->state->t != LTTV_STATE_MODE_UNKNOWN)
473 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
474 process->state->change);
475 else
476 delta = ltt_time_zero;
477
478 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
479 LTTV_TIME, &cpu_time);
480 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
481
482 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
483 delta);
484 }
485
486 /* Note : every mode_end must come with a cumulative cpu time update in the
487 * after hook. */
488 static void mode_end(LttvTracefileStats *tfcs)
489 {
490 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
491 guint cpu = tfcs->parent.cpu;
492 LttvProcessState *process = ts->running_process[cpu];
493 LttvAttributeValue elapsed_time, cpu_time, cum_cpu_time;
494
495 LttTime delta;
496
497 /* FIXME put there in case of a missing update after a state modification */
498 //void *lasttree = tfcs->current_events_tree;
499 //update_event_tree(tfcs);
500 //g_assert (lasttree == tfcs->current_events_tree);
501 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
502 LTTV_TIME, &elapsed_time);
503
504 if(process->state->t != LTTV_STATE_MODE_UNKNOWN) {
505 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
506 process->state->entry);
507 } else
508 delta = ltt_time_zero;
509
510 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
511
512 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
513 LTTV_TIME, &cpu_time);
514
515 /* if it is a running mode, we must count its cpu time */
516 if(process->state->s == LTTV_STATE_RUN &&
517 process->state->t != LTTV_STATE_MODE_UNKNOWN)
518 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
519 process->state->change);
520 else
521 delta = ltt_time_zero;
522
523 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
524 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
525 delta);
526
527 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CUMULATIVE_CPU_TIME,
528 LTTV_TIME, &cum_cpu_time);
529 *(cum_cpu_time.v_time) = ltt_time_add(*(cum_cpu_time.v_time),
530 process->state->cum_cpu_time);
531 }
532
533
534 static void after_mode_end(LttvTracefileStats *tfcs)
535 {
536 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
537 guint cpu = tfcs->parent.cpu;
538 LttvProcessState *process = ts->running_process[cpu];
539 LttvAttributeValue cum_cpu_time;
540
541 LttTime nested_delta;
542
543 nested_delta = process->state->cum_cpu_time;
544 process->state->cum_cpu_time = ltt_time_zero; /* For after traceset hook */
545
546 update_event_tree(tfcs);
547
548 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
549 nested_delta);
550 }
551
552 static gboolean before_syscall_entry(void *hook_data, void *call_data)
553 {
554 mode_change((LttvTracefileStats *)call_data);
555 return FALSE;
556 }
557
558
559 static gboolean after_syscall_entry(void *hook_data, void *call_data)
560 {
561 update_event_tree((LttvTracefileStats *)call_data);
562 return FALSE;
563 }
564
565
566 static gboolean before_syscall_exit(void *hook_data, void *call_data)
567 {
568 mode_end((LttvTracefileStats *)call_data);
569 return FALSE;
570 }
571
572
573 static gboolean after_syscall_exit(void *hook_data, void *call_data)
574 {
575 after_mode_end((LttvTracefileStats *)call_data);
576 return FALSE;
577 }
578
579
580 static gboolean before_trap_entry(void *hook_data, void *call_data)
581 {
582 mode_change((LttvTracefileStats *)call_data);
583 return FALSE;
584 }
585
586
587 static gboolean after_trap_entry(void *hook_data, void *call_data)
588 {
589 update_event_tree((LttvTracefileStats *)call_data);
590 return FALSE;
591 }
592
593
594 static gboolean before_trap_exit(void *hook_data, void *call_data)
595 {
596 mode_end((LttvTracefileStats *)call_data);
597 return FALSE;
598 }
599
600
601 static gboolean after_trap_exit(void *hook_data, void *call_data)
602 {
603 after_mode_end((LttvTracefileStats *)call_data);
604 return FALSE;
605 }
606
607
608 static gboolean before_irq_entry(void *hook_data, void *call_data)
609 {
610 mode_change((LttvTracefileStats *)call_data);
611 return FALSE;
612 }
613
614 static gboolean after_irq_entry(void *hook_data, void *call_data)
615 {
616 update_event_tree((LttvTracefileStats *)call_data);
617 return FALSE;
618 }
619
620
621 static gboolean before_irq_exit(void *hook_data, void *call_data)
622 {
623 mode_end((LttvTracefileStats *)call_data);
624 return FALSE;
625 }
626
627
628 static gboolean after_irq_exit(void *hook_data, void *call_data)
629 {
630 after_mode_end((LttvTracefileStats *)call_data);
631 return FALSE;
632 }
633
634
635 static gboolean before_soft_irq_entry(void *hook_data, void *call_data)
636 {
637 mode_change((LttvTracefileStats *)call_data);
638 return FALSE;
639 }
640
641 static gboolean after_soft_irq_entry(void *hook_data, void *call_data)
642 {
643 update_event_tree((LttvTracefileStats *)call_data);
644 return FALSE;
645 }
646
647 static gboolean before_soft_irq_exit(void *hook_data, void *call_data)
648 {
649 mode_end((LttvTracefileStats *)call_data);
650 return FALSE;
651 }
652
653
654 static gboolean after_soft_irq_exit(void *hook_data, void *call_data)
655 {
656 after_mode_end((LttvTracefileStats *)call_data);
657 return FALSE;
658 }
659
660 static gboolean before_function_entry(void *hook_data, void *call_data)
661 {
662 mode_change((LttvTracefileStats *)call_data);
663 return FALSE;
664 }
665
666 static gboolean after_function_entry(void *hook_data, void *call_data)
667 {
668 update_event_tree((LttvTracefileStats *)call_data);
669 return FALSE;
670 }
671
672 static gboolean before_function_exit(void *hook_data, void *call_data)
673 {
674 mode_end((LttvTracefileStats *)call_data);
675 return FALSE;
676 }
677
678 static gboolean after_function_exit(void *hook_data, void *call_data)
679 {
680 after_mode_end((LttvTracefileStats *)call_data);
681 return FALSE;
682 }
683
684
685 static gboolean before_schedchange(void *hook_data, void *call_data)
686 {
687 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
688
689 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
690
691 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
692
693 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
694
695 guint pid_in, pid_out;
696
697 gint state_out;
698
699 pid_out = ltt_event_get_unsigned(e, thf->f1);
700 pid_in = ltt_event_get_unsigned(e, thf->f2);
701 state_out = ltt_event_get_int(e, thf->f3);
702
703 /* compute the time for the process to schedule out */
704 mode_change(tfcs);
705
706 return FALSE;
707 }
708
709 static gboolean after_schedchange(void *hook_data, void *call_data)
710 {
711 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
712
713 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
714
715 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
716
717 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
718
719 guint pid_in, pid_out;
720
721 gint state_out;
722
723 LttvProcessState *process;
724
725 pid_out = ltt_event_get_unsigned(e, thf->f1);
726 pid_in = ltt_event_get_unsigned(e, thf->f2);
727 state_out = ltt_event_get_int(e, thf->f3);
728
729 /* get the information for the process scheduled in */
730 guint cpu = tfcs->parent.cpu;
731 process = ts->running_process[cpu];
732
733 find_event_tree(tfcs, process->pid_time,
734 cpu,
735 process->current_function,
736 process->state->t, process->state->n, &(tfcs->current_events_tree),
737 &(tfcs->current_event_types_tree));
738
739 /* compute the time waiting for the process to schedule in */
740 mode_change(tfcs);
741
742 return FALSE;
743 }
744
745 static gboolean process_fork(void *hook_data, void *call_data)
746 {
747 return FALSE;
748 }
749
750 static gboolean process_exit(void *hook_data, void *call_data)
751 {
752 update_event_tree((LttvTracefileStats *)call_data);
753 return FALSE;
754 }
755
756 static gboolean before_enum_process_state(void *hook_data, void *call_data)
757 {
758 #if 0
759 /* Broken : adds up time in the current process doing the dump */
760 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
761 mode_end(tfcs);
762 after_mode_end(tfcs);
763 mode_change(tfcs);
764 #endif //0
765 return FALSE;
766 }
767
768 static gboolean after_enum_process_state(void *hook_data, void *call_data)
769 {
770 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
771 LttvTraceStats *tcs = (LttvTraceStats*)tfc->t_context;
772 update_trace_event_tree(tcs);
773 return FALSE;
774 }
775
776 static gboolean after_statedump_end(void *hook_data, void *call_data)
777 {
778 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
779 LttvTraceStats *tcs = (LttvTraceStats*)tfc->t_context;
780 update_trace_event_tree(tcs);
781 return FALSE;
782 }
783
784 static gboolean process_free(void *hook_data, void *call_data)
785 {
786 return FALSE;
787 }
788
789 static gboolean every_event(void *hook_data, void *call_data)
790 {
791 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
792
793 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
794
795 LttvAttributeValue v;
796
797 /* The current branch corresponds to the tracefile/process/interrupt state.
798 Statistics are added within it, to count the number of events of this
799 type occuring in this context. A quark has been pre-allocated for each
800 event type and is used as name. */
801
802 lttv_attribute_find(tfcs->current_event_types_tree,
803 ltt_eventtype_name(ltt_event_eventtype(e)),
804 LTTV_UINT, &v);
805 (*(v.v_uint))++;
806 return FALSE;
807 }
808
809 static void lttv_stats_cleanup_process_state(LttvTraceState *ts,
810 LttvProcessState *process)
811 {
812 LttvTraceStats *tcs = (LttvTraceStats *)ts;
813 LttvTracesetContext *tsc = ts->parent.ts_context;
814 int i;
815 LttvTracefileStats **tfs = (LttvTracefileStats **)
816 &g_array_index(ts->parent.tracefiles, LttvTracefileContext*,
817 process->cpu);
818 int cleanup_empty = 0;
819 LttTime nested_delta = ltt_time_zero;
820 /* FIXME : ok, this is a hack. The time is infinite here :( */
821 LttTime save_time = (*tfs)->parent.parent.timestamp;
822 LttTime start, end;
823 ltt_trace_time_span_get(ts->parent.t, &start, &end);
824 (*tfs)->parent.parent.timestamp = end;
825
826 do {
827 if(ltt_time_compare(process->state->cum_cpu_time, ltt_time_zero) != 0) {
828 find_event_tree(*tfs, process->pid_time,
829 process->cpu,
830 process->current_function,
831 process->state->t, process->state->n, &((*tfs)->current_events_tree),
832 &((*tfs)->current_event_types_tree));
833 mode_end(*tfs);
834 nested_delta = process->state->cum_cpu_time;
835 }
836 cleanup_empty = lttv_state_pop_state_cleanup(process,
837 (LttvTracefileState *)*tfs);
838 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
839 nested_delta);
840
841 } while(cleanup_empty != 1);
842
843 (*tfs)->parent.parent.timestamp = save_time;
844 }
845
846 /* For each cpu, for each of their stacked states,
847 * perform sum of needed values. */
848 static void lttv_stats_cleanup_state(LttvTraceStats *tcs)
849 {
850 LttvTraceState *ts = (LttvTraceState *)tcs;
851 guint nb_cpus, i;
852
853 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
854
855 for(i=0; i<nb_cpus; i++) {
856 lttv_stats_cleanup_process_state(ts, ts->running_process[i]);
857 }
858 }
859
860 void
861 lttv_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats)
862 {
863 LttvAttribute *sum_container = self->stats;
864
865 LttvAttributeType type;
866
867 LttvAttributeValue value;
868
869 LttvAttributeName name;
870
871 gboolean is_named;
872
873 unsigned sum;
874
875 int trace_is_summed;
876
877 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
878 nb_event_type, nf, nb_functions;
879
880 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
881 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
882 *submode_tree, *event_types_tree, *mode_events_tree,
883 *cpu_functions_tree,
884 *function_tree,
885 *function_mode_types_tree,
886 *trace_cpu_tree;
887
888
889 main_tree = sum_container;
890
891 lttv_attribute_find(sum_container,
892 LTTV_STATS_SUMMED,
893 LTTV_UINT, &value);
894 trace_is_summed = *(value.v_uint);
895 *(value.v_uint) = 1;
896
897 /* First cleanup the state : sum all stalled information (never ending
898 * states). */
899 if(!trace_is_summed)
900 lttv_stats_cleanup_state(self);
901
902 processes_tree = lttv_attribute_find_subdir(main_tree,
903 LTTV_STATS_PROCESSES);
904 nb_process = lttv_attribute_get_number(processes_tree);
905
906 for(i = 0 ; i < nb_process ; i++) {
907 type = lttv_attribute_get(processes_tree, i, &name, &value, &is_named);
908 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
909
910 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
911 nb_cpu = lttv_attribute_get_number(cpus_tree);
912
913 for(j = 0 ; j < nb_cpu ; j++) {
914 type = lttv_attribute_get(cpus_tree, j, &name, &value, &is_named);
915 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
916
917 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
918 trace_cpu_tree = lttv_attribute_find_subdir_unnamed(trace_cpu_tree, name);
919 cpu_functions_tree = lttv_attribute_find_subdir(cpu_tree,
920 LTTV_STATS_FUNCTIONS);
921 nb_functions = lttv_attribute_get_number(cpu_functions_tree);
922
923 for(nf=0; nf < nb_functions; nf++) {
924 type = lttv_attribute_get(cpu_functions_tree, nf, &name, &value,
925 &is_named);
926 function_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
927 function_mode_types_tree = lttv_attribute_find_subdir(function_tree,
928 LTTV_STATS_MODE_TYPES);
929 nb_mode_type = lttv_attribute_get_number(function_mode_types_tree);
930 for(k = 0 ; k < nb_mode_type ; k++) {
931 type = lttv_attribute_get(function_mode_types_tree, k, &name, &value,
932 &is_named);
933 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
934
935 submodes_tree = lttv_attribute_find_subdir(mode_tree,
936 LTTV_STATS_SUBMODES);
937 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
938 LTTV_STATS_EVENTS);
939 mode_types_tree = lttv_attribute_find_subdir(mode_tree,
940 LTTV_STATS_MODE_TYPES);
941
942 nb_submode = lttv_attribute_get_number(submodes_tree);
943
944 for(l = 0 ; l < nb_submode ; l++) {
945 type = lttv_attribute_get(submodes_tree, l, &name, &value,
946 &is_named);
947 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
948
949 event_types_tree = lttv_attribute_find_subdir(submode_tree,
950 LTTV_STATS_EVENT_TYPES);
951 nb_event_type = lttv_attribute_get_number(event_types_tree);
952
953 sum = 0;
954 for(m = 0 ; m < nb_event_type ; m++) {
955 type = lttv_attribute_get(event_types_tree, m, &name, &value,
956 &is_named);
957 sum += *(value.v_uint);
958 }
959 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
960 LTTV_UINT, &value);
961 *(value.v_uint) = sum;
962
963 type = lttv_attribute_get(submodes_tree, l, &name, &value,
964 &is_named);
965 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
966 if(!trace_is_summed) {
967 lttv_attribute_recursive_add(mode_events_tree, event_types_tree);
968 lttv_attribute_recursive_add(mode_types_tree, submode_tree);
969 }
970 }
971 if(!trace_is_summed) {
972 lttv_attribute_recursive_add(function_tree, mode_types_tree);
973 }
974 }
975 if(!trace_is_summed) {
976 lttv_attribute_recursive_add(cpu_tree, function_tree);
977 lttv_attribute_recursive_add(process_tree, function_tree);
978 lttv_attribute_recursive_add(trace_cpu_tree, function_tree);
979 lttv_attribute_recursive_add(main_tree, function_tree);
980 }
981 lttv_attribute_recursive_add(ts_stats, function_tree);
982 }
983 }
984 }
985 }
986
987
988 gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
989 {
990 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
991 return 0;
992 }
993
994 void
995 lttv_stats_sum_traceset(LttvTracesetStats *self)
996 {
997 LttvTraceset *traceset = self->parent.parent.ts;
998 LttvAttribute *sum_container = self->stats;
999
1000 LttvTraceStats *tcs;
1001
1002 int i, nb_trace;
1003
1004 LttvAttribute *main_tree;
1005
1006 LttvAttributeValue value;
1007
1008 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
1009 LTTV_UINT, &value);
1010 if(*(value.v_uint) != 0) return;
1011 *(value.v_uint) = 1;
1012
1013 nb_trace = lttv_traceset_number(traceset);
1014
1015 for(i = 0 ; i < nb_trace ; i++) {
1016 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
1017 lttv_stats_sum_trace(tcs, self->stats);
1018 // lttv_attribute_recursive_add(sum_container, tcs->stats);
1019 }
1020 }
1021
1022
1023 // Hook wrapper. call_data is a traceset context.
1024 gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
1025 {
1026 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1027
1028 lttv_stats_add_event_hooks(tss);
1029
1030 return 0;
1031 }
1032
1033 void lttv_stats_add_event_hooks(LttvTracesetStats *self)
1034 {
1035 LttvTraceset *traceset = self->parent.parent.ts;
1036
1037 guint i, j, k, l, nb_trace, nb_tracefile;
1038
1039 LttvTraceStats *ts;
1040
1041 LttvTracefileStats *tfs;
1042
1043 GArray *hooks, *before_hooks, *after_hooks;
1044
1045 LttvTraceHook *hook;
1046
1047 LttvTraceHookByFacility *thf;
1048
1049 LttvAttributeValue val;
1050
1051 gint ret;
1052 gint hn;
1053
1054 nb_trace = lttv_traceset_number(traceset);
1055 for(i = 0 ; i < nb_trace ; i++) {
1056 ts = (LttvTraceStats *)self->parent.parent.traces[i];
1057
1058 /* Find the eventtype id for the following events and register the
1059 associated by id hooks. */
1060
1061 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 12);
1062 g_array_set_size(hooks, 12);
1063 hn=0;
1064
1065 ret = lttv_trace_find_hook(ts->parent.parent.t,
1066 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
1067 LTT_FIELD_SYSCALL_ID, 0, 0,
1068 before_syscall_entry, NULL,
1069 &g_array_index(hooks, LttvTraceHook, hn++));
1070 if(ret) hn--;
1071
1072 ret = lttv_trace_find_hook(ts->parent.parent.t,
1073 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
1074 0, 0, 0,
1075 before_syscall_exit, NULL,
1076 &g_array_index(hooks, LttvTraceHook, hn++));
1077 if(ret) hn--;
1078
1079 ret = lttv_trace_find_hook(ts->parent.parent.t,
1080 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1081 LTT_FIELD_TRAP_ID, 0, 0,
1082 before_trap_entry, NULL,
1083 &g_array_index(hooks, LttvTraceHook, hn++));
1084 if(ret) hn--;
1085
1086 ret = lttv_trace_find_hook(ts->parent.parent.t,
1087 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1088 0, 0, 0,
1089 before_trap_exit, NULL,
1090 &g_array_index(hooks, LttvTraceHook, hn++));
1091 if(ret) hn--;
1092
1093 ret = lttv_trace_find_hook(ts->parent.parent.t,
1094 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1095 LTT_FIELD_IRQ_ID, 0, 0,
1096 before_irq_entry, NULL,
1097 &g_array_index(hooks, LttvTraceHook, hn++));
1098 if(ret) hn--;
1099
1100 ret = lttv_trace_find_hook(ts->parent.parent.t,
1101 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1102 0, 0, 0,
1103 before_irq_exit, NULL,
1104 &g_array_index(hooks, LttvTraceHook, hn++));
1105 if(ret) hn--;
1106
1107 ret = lttv_trace_find_hook(ts->parent.parent.t,
1108 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1109 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1110 before_soft_irq_entry, NULL,
1111 &g_array_index(hooks, LttvTraceHook, hn++));
1112 if(ret) hn--;
1113
1114 ret = lttv_trace_find_hook(ts->parent.parent.t,
1115 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1116 0, 0, 0,
1117 before_soft_irq_exit, 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_PROCESS, LTT_EVENT_SCHEDCHANGE,
1123 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1124 before_schedchange, 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_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1130 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1131 before_function_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_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1137 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1138 before_function_exit, NULL,
1139 &g_array_index(hooks, LttvTraceHook, hn++));
1140 if(ret) hn--;
1141
1142 /* statedump-related hooks */
1143 ret = lttv_trace_find_hook(ts->parent.parent.t,
1144 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1145 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1146 before_enum_process_state, NULL,
1147 &g_array_index(hooks, LttvTraceHook, hn++));
1148 if(ret) hn--;
1149
1150 g_array_set_size(hooks, hn);
1151
1152 before_hooks = hooks;
1153
1154 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 16);
1155 g_array_set_size(hooks, 16);
1156 hn=0;
1157
1158 ret = lttv_trace_find_hook(ts->parent.parent.t,
1159 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
1160 LTT_FIELD_SYSCALL_ID, 0, 0,
1161 after_syscall_entry, NULL,
1162 &g_array_index(hooks, LttvTraceHook, hn++));
1163 if(ret) hn--;
1164
1165 ret = lttv_trace_find_hook(ts->parent.parent.t,
1166 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
1167 0, 0, 0,
1168 after_syscall_exit, NULL,
1169 &g_array_index(hooks, LttvTraceHook, hn++));
1170 if(ret) hn--;
1171
1172 ret = lttv_trace_find_hook(ts->parent.parent.t,
1173 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1174 LTT_FIELD_TRAP_ID, 0, 0,
1175 after_trap_entry, NULL,
1176 &g_array_index(hooks, LttvTraceHook, hn++));
1177 if(ret) hn--;
1178
1179 ret = lttv_trace_find_hook(ts->parent.parent.t,
1180 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1181 0, 0, 0,
1182 after_trap_exit, NULL,
1183 &g_array_index(hooks, LttvTraceHook, hn++));
1184 if(ret) hn--;
1185
1186 ret = lttv_trace_find_hook(ts->parent.parent.t,
1187 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1188 LTT_FIELD_IRQ_ID, 0, 0,
1189 after_irq_entry, NULL,
1190 &g_array_index(hooks, LttvTraceHook, hn++));
1191 if(ret) hn--;
1192
1193 ret = lttv_trace_find_hook(ts->parent.parent.t,
1194 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1195 0, 0, 0,
1196 after_irq_exit, NULL,
1197 &g_array_index(hooks, LttvTraceHook, hn++));
1198 if(ret) hn--;
1199
1200 ret = lttv_trace_find_hook(ts->parent.parent.t,
1201 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1202 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1203 after_irq_entry, NULL,
1204 &g_array_index(hooks, LttvTraceHook, hn++));
1205 if(ret) hn--;
1206
1207 ret = lttv_trace_find_hook(ts->parent.parent.t,
1208 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1209 0, 0, 0,
1210 after_soft_irq_exit, NULL,
1211 &g_array_index(hooks, LttvTraceHook, hn++));
1212 if(ret) hn--;
1213
1214 ret = lttv_trace_find_hook(ts->parent.parent.t,
1215 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1216 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1217 after_schedchange, NULL,
1218 &g_array_index(hooks, LttvTraceHook, hn++));
1219 if(ret) hn--;
1220
1221 ret = lttv_trace_find_hook(ts->parent.parent.t,
1222 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1223 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
1224 process_fork, NULL,
1225 &g_array_index(hooks, LttvTraceHook, hn++));
1226 if(ret) hn--;
1227
1228 ret = lttv_trace_find_hook(ts->parent.parent.t,
1229 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1230 LTT_FIELD_PID, 0, 0,
1231 process_exit, NULL,
1232 &g_array_index(hooks, LttvTraceHook, hn++));
1233 if(ret) hn--;
1234
1235 ret = lttv_trace_find_hook(ts->parent.parent.t,
1236 LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
1237 LTT_FIELD_PID, 0, 0,
1238 process_free, NULL,
1239 &g_array_index(hooks, LttvTraceHook, hn++));
1240 if(ret) hn--;
1241
1242 ret = lttv_trace_find_hook(ts->parent.parent.t,
1243 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1244 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1245 after_function_entry, NULL,
1246 &g_array_index(hooks, LttvTraceHook, hn++));
1247 if(ret) hn--;
1248
1249 ret = lttv_trace_find_hook(ts->parent.parent.t,
1250 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1251 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1252 after_function_exit, NULL,
1253 &g_array_index(hooks, LttvTraceHook, hn++));
1254 if(ret) hn--;
1255
1256 /* statedump-related hooks */
1257 ret = lttv_trace_find_hook(ts->parent.parent.t,
1258 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1259 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1260 after_enum_process_state, NULL,
1261 &g_array_index(hooks, LttvTraceHook, hn++));
1262 if(ret) hn--;
1263
1264 ret = lttv_trace_find_hook(ts->parent.parent.t,
1265 LTT_FACILITY_STATEDUMP, LTT_EVENT_STATEDUMP_END,
1266 0, 0, 0,
1267 after_statedump_end, NULL,
1268 &g_array_index(hooks, LttvTraceHook, hn++));
1269 if(ret) hn--;
1270
1271 g_array_set_size(hooks, hn);
1272
1273 after_hooks = hooks;
1274
1275 /* Add these hooks to each event_by_id hooks list */
1276
1277 nb_tracefile = ts->parent.parent.tracefiles->len;
1278
1279 for(j = 0 ; j < nb_tracefile ; j++) {
1280 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1281 LttvTracefileContext*, j));
1282 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
1283 LTTV_PRIO_DEFAULT);
1284
1285 for(k = 0 ; k < before_hooks->len ; k++) {
1286 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1287 for(l = 0; l<hook->fac_list->len;l++) {
1288 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1289 lttv_hooks_add(
1290 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1291 thf->h,
1292 thf,
1293 LTTV_PRIO_STATS_BEFORE_STATE);
1294 }
1295 }
1296 for(k = 0 ; k < after_hooks->len ; k++) {
1297 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1298 for(l = 0; l<hook->fac_list->len;l++) {
1299 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1300 lttv_hooks_add(
1301 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1302 thf->h,
1303 thf,
1304 LTTV_PRIO_STATS_AFTER_STATE);
1305 }
1306 }
1307 }
1308 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1309 LTTV_POINTER, &val);
1310 *(val.v_pointer) = before_hooks;
1311 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1312 LTTV_POINTER, &val);
1313 *(val.v_pointer) = after_hooks;
1314 }
1315 }
1316
1317 // Hook wrapper. call_data is a traceset context.
1318 gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
1319 {
1320 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1321
1322 lttv_stats_remove_event_hooks(tss);
1323
1324 return 0;
1325 }
1326
1327 void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
1328 {
1329 LttvTraceset *traceset = self->parent.parent.ts;
1330
1331 guint i, j, k, l, nb_trace, nb_tracefile;
1332
1333 LttvTraceStats *ts;
1334
1335 LttvTracefileStats *tfs;
1336
1337 void *hook_data;
1338
1339 GArray *before_hooks, *after_hooks;
1340
1341 LttvTraceHook *hook;
1342
1343 LttvTraceHookByFacility *thf;
1344
1345 LttvAttributeValue val;
1346
1347 nb_trace = lttv_traceset_number(traceset);
1348 for(i = 0 ; i < nb_trace ; i++) {
1349 ts = (LttvTraceStats*)self->parent.parent.traces[i];
1350 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1351 LTTV_POINTER, &val);
1352 before_hooks = *(val.v_pointer);
1353 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1354 LTTV_POINTER, &val);
1355 after_hooks = *(val.v_pointer);
1356
1357 /* Remove these hooks from each event_by_id hooks list */
1358
1359 nb_tracefile = ts->parent.parent.tracefiles->len;
1360
1361 for(j = 0 ; j < nb_tracefile ; j++) {
1362 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1363 LttvTracefileContext*, j));
1364 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
1365 NULL);
1366
1367 for(k = 0 ; k < before_hooks->len ; k++) {
1368 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1369 for(l = 0 ; l < hook->fac_list->len ; l++) {
1370 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1371 lttv_hooks_remove_data(
1372 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1373 thf->h,
1374 thf);
1375 }
1376 }
1377 for(k = 0 ; k < after_hooks->len ; k++) {
1378 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1379 for(l = 0 ; l < hook->fac_list->len ; l++) {
1380 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1381 lttv_hooks_remove_data(
1382 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1383 thf->h,
1384 thf);
1385 }
1386 }
1387 }
1388 g_debug("lttv_stats_remove_event_hooks()");
1389 g_array_free(before_hooks, TRUE);
1390 g_array_free(after_hooks, TRUE);
1391 }
1392 }
1393
1394
1395 static void module_init()
1396 {
1397 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
1398 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
1399 LTTV_STATS_CPU = g_quark_from_string("cpu");
1400 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
1401 LTTV_STATS_MODES = g_quark_from_string("modes");
1402 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
1403 LTTV_STATS_FUNCTIONS = g_quark_from_string("functions");
1404 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
1405 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
1406 LTTV_STATS_CUMULATIVE_CPU_TIME = g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
1407 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time (includes per process waiting time)");
1408 LTTV_STATS_EVENTS = g_quark_from_string("events");
1409 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
1410 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
1411 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
1412 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
1413 LTTV_STATS = g_quark_from_string("statistics");
1414 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
1415 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
1416 }
1417
1418 static void module_destroy()
1419 {
1420 }
1421
1422
1423 LTTV_MODULE("stats", "Compute processes statistics", \
1424 "Accumulate statistics for event types, processes and CPUs", \
1425 module_init, module_destroy, "state");
1426
1427 /* Change the places where stats are called (create/read/write stats)
1428
1429 Check for options in batchtest.c to reduce writing and see what tests are
1430 best candidates for performance analysis. Once OK, commit, move to main
1431 and run tests. Update the gui for statistics. */
This page took 0.060973 seconds and 4 git commands to generate.