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