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