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