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