fix module unload oops
[lttv.git] / ltt / branches / poly / lttv / lttv / stats.c
CommitLineData
9c312311 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
b445142a 19
9f797243 20#include <stdio.h>
08b1c66e 21#include <lttv/module.h>
b445142a 22#include <lttv/stats.h>
2a2fa4f0 23#include <lttv/lttv.h>
f95bc830 24#include <lttv/attribute.h>
b445142a 25#include <ltt/facility.h>
26#include <ltt/trace.h>
27#include <ltt/event.h>
28
9f797243 29#define BUF_SIZE 256
30
b445142a 31GQuark
32 LTTV_STATS_PROCESS_UNKNOWN,
33 LTTV_STATS_PROCESSES,
34 LTTV_STATS_CPU,
35 LTTV_STATS_MODE_TYPES,
36 LTTV_STATS_MODES,
37 LTTV_STATS_SUBMODES,
38 LTTV_STATS_EVENT_TYPES,
39 LTTV_STATS_CPU_TIME,
40 LTTV_STATS_ELAPSED_TIME,
41 LTTV_STATS_EVENTS,
f95bc830 42 LTTV_STATS_EVENTS_COUNT,
43 LTTV_STATS_USE_COUNT,
44 LTTV_STATS,
45 LTTV_STATS_TRACEFILES,
46 LTTV_STATS_SUMMED;
b445142a 47
48static GQuark
49 LTTV_STATS_BEFORE_HOOKS,
50 LTTV_STATS_AFTER_HOOKS;
51
52static void remove_all_processes(GHashTable *processes);
53
54static void
55find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu,
56 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
57 LttvAttribute **event_types_tree);
58
59static void
60init(LttvTracesetStats *self, LttvTraceset *ts)
61{
dbb7bb09 62 guint i, j, nb_trace, nb_tracefile;
b445142a 63
64 LttvTraceContext *tc;
65
66 LttvTraceStats *tcs;
67
68 LttvTracefileContext *tfc;
69
70 LttvTracefileStats *tfcs;
71
72 LttTime timestamp = {0,0};
73
f95bc830 74 LttvAttributeValue v;
75
76 LttvAttribute
77 *stats_tree,
78 *tracefiles_stats;
79
b445142a 80 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
81 init((LttvTracesetContext *)self, ts);
82
f95bc830 83 self->stats =lttv_attribute_find_subdir(self->parent.parent.ts_a,LTTV_STATS);
84 lttv_attribute_find(self->parent.parent.ts_a, 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
b445142a 92 nb_trace = lttv_traceset_number(ts);
93
94 for(i = 0 ; i < nb_trace ; i++) {
359b2948 95 tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]);
96 tcs = (LttvTraceStats *)tc;
f95bc830 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 }
b445142a 108
dbb7bb09 109 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
110 ltt_trace_per_cpu_tracefile_number(tc->t);
b445142a 111
dbb7bb09 112 for(j = 0 ; j < nb_tracefile ; j++) {
113 tfcs = LTTV_TRACEFILE_STATS(tc->tracefiles[j]);
f95bc830 114 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
115 tfcs->parent.cpu_name);
b445142a 116 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
117 tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN,
118 LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
119 &tfcs->current_event_types_tree);
120 }
121 }
122}
123
124
125static void
126fini(LttvTracesetStats *self)
127{
128 guint i, j, nb_trace, nb_tracefile;
129
130 LttvTraceset *ts;
131
132 LttvTraceContext *tc;
133
134 LttvTraceStats *tcs;
135
136 LttvTracefileContext *tfc;
137
138 LttvTracefileStats *tfcs;
139
140 LttTime timestamp = {0,0};
141
f95bc830 142 LttvAttributeValue v;
143
144 LttvAttribute *tracefiles_stats;
145
146 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
147 LTTV_UINT, &v);
148 *(v.v_uint)--;
149
150 if(*(v.v_uint) == 0) {
151 lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
f95bc830 152 }
153 self->stats = NULL;
154
b445142a 155 ts = self->parent.parent.ts;
156 nb_trace = lttv_traceset_number(ts);
157
158 for(i = 0 ; i < nb_trace ; i++) {
f95bc830 159 tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]));
160
161 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
162 LTTV_UINT, &v);
163 *(v.v_uint)--;
164
165 if(*(v.v_uint) == 0) {
166 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
f95bc830 167 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
168 LTTV_STATS_TRACEFILES);
169 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,
170 LTTV_STATS_TRACEFILES);
f95bc830 171 }
172 tcs->stats = NULL;
b445142a 173
dbb7bb09 174 nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
175 ltt_trace_per_cpu_tracefile_number(tc->t);
b445142a 176
b445142a 177 for(j = 0 ; j < nb_tracefile ; j++) {
359b2948 178 tfc = tc->tracefiles[j];
179 tfcs = (LttvTracefileStats *)tfc;
f95bc830 180 tfcs->stats = NULL;
b445142a 181 tfcs->current_events_tree = NULL;
182 tfcs->current_event_types_tree = NULL;
183 }
184 }
185 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
186 fini((LttvTracesetContext *)self);
187}
188
189
190static LttvTracesetContext *
191new_traceset_context(LttvTracesetContext *self)
192{
193 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
194}
195
196
197static LttvTraceContext *
198new_trace_context(LttvTracesetContext *self)
199{
200 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
201}
202
203
204static LttvTracefileContext *
205new_tracefile_context(LttvTracesetContext *self)
206{
207 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
208}
209
210
211static void
212traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
213{
214}
215
216
217static void
218traceset_stats_finalize (LttvTracesetStats *self)
219{
220 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
221 finalize(G_OBJECT(self));
222}
223
224
225static void
226traceset_stats_class_init (LttvTracesetContextClass *klass)
227{
228 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
229
230 gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
231 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
232 klass->fini = (void (*)(LttvTracesetContext *self))fini;
233 klass->new_traceset_context = new_traceset_context;
234 klass->new_trace_context = new_trace_context;
235 klass->new_tracefile_context = new_tracefile_context;
236}
237
238
239GType
240lttv_traceset_stats_get_type(void)
241{
242 static GType type = 0;
243 if (type == 0) {
244 static const GTypeInfo info = {
245 sizeof (LttvTracesetStatsClass),
246 NULL, /* base_init */
247 NULL, /* base_finalize */
248 (GClassInitFunc) traceset_stats_class_init, /* class_init */
249 NULL, /* class_finalize */
250 NULL, /* class_data */
dbb7bb09 251 sizeof (LttvTracesetStats),
b445142a 252 0, /* n_preallocs */
253 (GInstanceInitFunc) traceset_stats_instance_init /* instance_init */
254 };
255
256 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE, "LttvTracesetStatsType",
257 &info, 0);
258 }
259 return type;
260}
261
262
263static void
264trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
265{
266}
267
268
269static void
270trace_stats_finalize (LttvTraceStats *self)
271{
272 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
273 finalize(G_OBJECT(self));
274}
275
276
277static void
278trace_stats_class_init (LttvTraceContextClass *klass)
279{
280 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
281
282 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
283}
284
285
286GType
287lttv_trace_stats_get_type(void)
288{
289 static GType type = 0;
290 if (type == 0) {
291 static const GTypeInfo info = {
292 sizeof (LttvTraceStatsClass),
293 NULL, /* base_init */
294 NULL, /* base_finalize */
295 (GClassInitFunc) trace_stats_class_init, /* class_init */
296 NULL, /* class_finalize */
297 NULL, /* class_data */
298 sizeof (LttvTraceStats),
299 0, /* n_preallocs */
300 (GInstanceInitFunc) trace_stats_instance_init /* instance_init */
301 };
302
303 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
304 "LttvTraceStatsType", &info, 0);
305 }
306 return type;
307}
308
309
310static void
311tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
312{
313}
314
315
316static void
317tracefile_stats_finalize (LttvTracefileStats *self)
318{
319 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
320 finalize(G_OBJECT(self));
321}
322
323
324static void
325tracefile_stats_class_init (LttvTracefileStatsClass *klass)
326{
327 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
328
329 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
330}
331
332
333GType
334lttv_tracefile_stats_get_type(void)
335{
336 static GType type = 0;
337 if (type == 0) {
338 static const GTypeInfo info = {
339 sizeof (LttvTracefileStatsClass),
340 NULL, /* base_init */
341 NULL, /* base_finalize */
342 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
343 NULL, /* class_finalize */
344 NULL, /* class_data */
345 sizeof (LttvTracefileStats),
346 0, /* n_preallocs */
347 (GInstanceInitFunc) tracefile_stats_instance_init /* instance_init */
348 };
349
350 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
351 "LttvTracefileStatsType", &info, 0);
352 }
353 return type;
354}
355
356
357static void
358find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu,
359 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
360 LttvAttribute **event_types_tree)
361{
362 LttvAttribute *a;
363
364 LttvTraceStats *tcs = LTTV_TRACE_STATS(tfcs->parent.parent.t_context);
365 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
366 a = lttv_attribute_find_subdir(a, tfcs->parent.process->pid_time);
367 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
368 a = lttv_attribute_find_subdir(a, tfcs->parent.cpu_name);
369 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
370 a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->t);
371 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
372 a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->n);
373 *events_tree = a;
374 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
375 *event_types_tree = a;
376}
377
378
379static void update_event_tree(LttvTracefileStats *tfcs)
380{
381 LttvExecutionState *es = tfcs->parent.process->state;
382
383 find_event_tree(tfcs, tfcs->parent.process->pid_time, tfcs->parent.cpu_name,
384 es->t, es->n, &(tfcs->current_events_tree),
385 &(tfcs->current_event_types_tree));
386}
387
388
389static void mode_change(LttvTracefileStats *tfcs)
390{
391 LttvAttributeValue cpu_time;
392
393 LttTime delta;
394
395 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
396 LTTV_TIME, &cpu_time);
308711e5 397 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 398 tfcs->parent.process->state->change);
308711e5 399 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 400}
401
402
403static void mode_end(LttvTracefileStats *tfcs)
404{
405 LttvAttributeValue elapsed_time, cpu_time;
406
407 LttTime delta;
408
409 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
410 LTTV_TIME, &elapsed_time);
308711e5 411 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 412 tfcs->parent.process->state->entry);
308711e5 413 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
b445142a 414
415 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
416 LTTV_TIME, &cpu_time);
308711e5 417 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
b445142a 418 tfcs->parent.process->state->change);
308711e5 419 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
b445142a 420}
421
422
423static gboolean before_syscall_entry(void *hook_data, void *call_data)
424{
425 mode_change((LttvTracefileStats *)call_data);
426 return FALSE;
427}
428
429
430static gboolean after_syscall_entry(void *hook_data, void *call_data)
431{
432 update_event_tree((LttvTracefileStats *)call_data);
433 return FALSE;
434}
435
436
437gboolean before_syscall_exit(void *hook_data, void *call_data)
438{
439 mode_end((LttvTracefileStats *)call_data);
440 return FALSE;
441}
442
443
444static gboolean after_syscall_exit(void *hook_data, void *call_data)
445{
446 update_event_tree((LttvTracefileStats *)call_data);
447 return FALSE;
448}
449
450
451gboolean before_trap_entry(void *hook_data, void *call_data)
452{
453 mode_change((LttvTracefileStats *)call_data);
454 return FALSE;
455}
456
457
458static gboolean after_trap_entry(void *hook_data, void *call_data)
459{
460 update_event_tree((LttvTracefileStats *)call_data);
461 return FALSE;
462}
463
464
465gboolean before_trap_exit(void *hook_data, void *call_data)
466{
467 mode_end((LttvTracefileStats *)call_data);
468 return FALSE;
469}
470
471
472gboolean after_trap_exit(void *hook_data, void *call_data)
473{
474 update_event_tree((LttvTracefileStats *)call_data);
475 return FALSE;
476}
477
478
479gboolean before_irq_entry(void *hook_data, void *call_data)
480{
481 mode_change((LttvTracefileStats *)call_data);
482 return FALSE;
483}
484
485
486gboolean after_irq_entry(void *hook_data, void *call_data)
487{
488 update_event_tree((LttvTracefileStats *)call_data);
489 return FALSE;
490}
491
492
493gboolean before_irq_exit(void *hook_data, void *call_data)
494{
495 mode_end((LttvTracefileStats *)call_data);
496 return FALSE;
497}
498
499
500gboolean after_irq_exit(void *hook_data, void *call_data)
501{
502 update_event_tree((LttvTracefileStats *)call_data);
503 return FALSE;
504}
505
506
507gboolean before_schedchange(void *hook_data, void *call_data)
508{
509 LttvTraceHook *h = (LttvTraceHook *)hook_data;
510
511 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
512
513 guint pid_in, pid_out, state_out;
514
515 LttvProcessState *process;
516
517 pid_in = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f1);
518 pid_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f2);
519 state_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f3);
520
521 /* compute the time for the process to schedule out */
522
523 mode_change(tfcs);
524
525 /* get the information for the process scheduled in */
526
2a2fa4f0 527 process = lttv_state_find_process_or_create(&(tfcs->parent), pid_in);
b445142a 528
529 find_event_tree(tfcs, process->pid_time, tfcs->parent.cpu_name,
530 process->state->t, process->state->n, &(tfcs->current_events_tree),
531 &(tfcs->current_event_types_tree));
532
533 /* compute the time waiting for the process to schedule in */
534
535 mode_change(tfcs);
536 return FALSE;
537}
538
539
540gboolean process_fork(void *hook_data, void *call_data)
541{
542 /* nothing to do for now */
543 return FALSE;
544}
545
546
547gboolean process_exit(void *hook_data, void *call_data)
548{
549 /* We should probably exit all modes here or we could do that at
550 schedule out. */
551 return FALSE;
552}
553
554
555gboolean every_event(void *hook_data, void *call_data)
556{
557 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
558
559 LttvAttributeValue v;
560
561 /* The current branch corresponds to the tracefile/process/interrupt state.
562 Statistics are added within it, to count the number of events of this
563 type occuring in this context. A quark has been pre-allocated for each
564 event type and is used as name. */
565
566 lttv_attribute_find(tfcs->current_event_types_tree,
567 ((LttvTraceState *)(tfcs->parent.parent.t_context))->
568 eventtype_names[ltt_event_eventtype_id(tfcs->parent.parent.e)],
569 LTTV_UINT, &v);
570 (*(v.v_uint))++;
571 return FALSE;
572}
573
574
f95bc830 575void
576lttv_stats_sum_trace(LttvTraceStats *self)
b445142a 577{
b445142a 578 LttvTraceStats *tcs;
579
b445142a 580 LttvAttributeType type;
581
582 LttvAttributeValue value;
583
584 LttvAttributeName name;
585
586 unsigned sum;
587
f95bc830 588 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
b445142a 589 nb_event_type;
590
591 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
592 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
593 *submode_tree, *event_types_tree, *mode_events_tree,
594 *cpu_events_tree, *process_modes_tree, *trace_cpu_tree,
f95bc830 595 *trace_modes_tree;
596
597 main_tree = self->stats;
598
599 lttv_attribute_find(self->parent.parent.t_a, LTTV_STATS_SUMMED,
600 LTTV_UINT, &value);
601 if(*(value.v_uint) != 0) return;
602 *(value.v_uint) = 1;
603
604 processes_tree = lttv_attribute_find_subdir(main_tree,
605 LTTV_STATS_PROCESSES);
606 trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
607 nb_process = lttv_attribute_get_number(processes_tree);
608
609 for(i = 0 ; i < nb_process ; i++) {
610 type = lttv_attribute_get(processes_tree, i, &name, &value);
611 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
612
613 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
614 process_modes_tree = lttv_attribute_find_subdir(process_tree,
615 LTTV_STATS_MODES);
616 nb_cpu = lttv_attribute_get_number(cpus_tree);
617
618 for(j = 0 ; j < nb_cpu ; j++) {
619 type = lttv_attribute_get(cpus_tree, j, &name, &value);
620 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
621
622 mode_types_tree = lttv_attribute_find_subdir(cpu_tree,
623 LTTV_STATS_MODE_TYPES);
624 cpu_events_tree = lttv_attribute_find_subdir(cpu_tree,
625 LTTV_STATS_EVENTS);
626 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
627 trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name);
628 nb_mode_type = lttv_attribute_get_number(mode_types_tree);
629
630 for(k = 0 ; k < nb_mode_type ; k++) {
631 type = lttv_attribute_get(mode_types_tree, k, &name, &value);
632 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
633
634 submodes_tree = lttv_attribute_find_subdir(mode_tree,
635 LTTV_STATS_SUBMODES);
636 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
637 LTTV_STATS_EVENTS);
638 nb_submode = lttv_attribute_get_number(submodes_tree);
b445142a 639
f95bc830 640 for(l = 0 ; l < nb_submode ; l++) {
641 type = lttv_attribute_get(submodes_tree, l, &name, &value);
642 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
b445142a 643
f95bc830 644 event_types_tree = lttv_attribute_find_subdir(submode_tree,
645 LTTV_STATS_EVENT_TYPES);
646 nb_event_type = lttv_attribute_get_number(event_types_tree);
b445142a 647
f95bc830 648 sum = 0;
649 for(m = 0 ; m < nb_event_type ; m++) {
650 type = lttv_attribute_get(event_types_tree, m, &name, &value);
651 sum += *(value.v_uint);
b445142a 652 }
f95bc830 653 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
654 LTTV_UINT, &value);
655 *(value.v_uint) = sum;
656 lttv_attribute_recursive_add(mode_events_tree, submode_tree);
b445142a 657 }
f95bc830 658 lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
b445142a 659 }
f95bc830 660 lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
661 lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
b445142a 662 }
f95bc830 663 lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
664 }
665}
666
667
668void
669lttv_stats_sum_traceset(LttvTracesetStats *self)
670{
671 LttvTraceset *traceset = self->parent.parent.ts;
672
673 LttvTraceStats *tcs;
674
675 int i, nb_trace;
676
677 LttvAttribute *main_tree, *trace_modes_tree, *traceset_modes_tree;
678
679 LttvAttributeValue value;
680
681 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_SUMMED,
682 LTTV_UINT, &value);
683 if(*(value.v_uint) != 0) return;
684 *(value.v_uint) = 1;
685
686 traceset_modes_tree = lttv_attribute_find_subdir(self->stats,
687 LTTV_STATS_MODES);
688 nb_trace = lttv_traceset_number(traceset);
689
690 for(i = 0 ; i < nb_trace ; i++) {
691 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
692 lttv_stats_sum_trace(tcs);
693 main_tree = tcs->stats;
694 trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
b445142a 695 lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree);
696 }
b445142a 697}
698
699
700lttv_stats_add_event_hooks(LttvTracesetStats *self)
701{
702 LttvTraceset *traceset = self->parent.parent.ts;
703
dbb7bb09 704 guint i, j, k, nb_trace, nb_tracefile;
b445142a 705
706 LttFacility *f;
707
708 LttEventType *et;
709
710 LttvTraceStats *ts;
711
712 LttvTracefileStats *tfs;
713
714 void *hook_data;
715
716 GArray *hooks, *before_hooks, *after_hooks;
717
718 LttvTraceHook hook;
719
720 LttvAttributeValue val;
721
722 nb_trace = lttv_traceset_number(traceset);
723 for(i = 0 ; i < nb_trace ; i++) {
724 ts = (LttvTraceStats *)self->parent.parent.traces[i];
725
726 /* Find the eventtype id for the following events and register the
727 associated by id hooks. */
728
729 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
730 g_array_set_size(hooks, 7);
731
732 lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry",
733 "syscall_id", NULL, NULL, before_syscall_entry,
734 &g_array_index(hooks, LttvTraceHook, 0));
735
736 lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL,
737 NULL, NULL, before_syscall_exit,
738 &g_array_index(hooks, LttvTraceHook, 1));
739
740 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id",
741 NULL, NULL, before_trap_entry,
742 &g_array_index(hooks, LttvTraceHook, 2));
743
744 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL,
745 NULL, before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
746
747 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id",
748 NULL, NULL, before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
749
750 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL,
751 NULL, before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
752
753 lttv_trace_find_hook(ts->parent.parent.t, "core", "schedchange", "in",
754 "out", "out_state", before_schedchange,
755 &g_array_index(hooks, LttvTraceHook, 6));
756
757 before_hooks = hooks;
758
759 hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
760 g_array_set_size(hooks, 8);
761
762 lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry",
763 "syscall_id", NULL, NULL, after_syscall_entry,
764 &g_array_index(hooks, LttvTraceHook, 0));
765
766 lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL,
767 NULL, NULL, after_syscall_exit,
768 &g_array_index(hooks, LttvTraceHook, 1));
769
770 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id",
771 NULL, NULL, after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
772
773 lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL,
774 NULL, after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
775
776 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id",
777 NULL, NULL, after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
778
779 lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL,
780 NULL, after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
781
782 lttv_trace_find_hook(ts->parent.parent.t, "core", "process_fork",
783 "child_pid", NULL, NULL, process_fork,
784 &g_array_index(hooks, LttvTraceHook, 6));
785
786 lttv_trace_find_hook(ts->parent.parent.t, "core", "process_exit", NULL,
787 NULL, NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 7));
788
789 after_hooks = hooks;
790
359b2948 791 /* Add these hooks to each event_by_id hooks list */
b445142a 792
dbb7bb09 793 nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
794 ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
b445142a 795
dbb7bb09 796 for(j = 0 ; j < nb_tracefile ; j++) {
797 tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
359b2948 798 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
799 LTTV_PRIO_DEFAULT);
b445142a 800
801 for(k = 0 ; k < before_hooks->len ; k++) {
802 hook = g_array_index(before_hooks, LttvTraceHook, k);
803 lttv_hooks_add(lttv_hooks_by_id_find(
359b2948 804 tfs->parent.parent.event_by_id,
805 hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k),
806 LTTV_PRIO_STATS_BEFORE_STATE);
b445142a 807 }
808 for(k = 0 ; k < after_hooks->len ; k++) {
809 hook = g_array_index(after_hooks, LttvTraceHook, k);
810 lttv_hooks_add(lttv_hooks_by_id_find(
359b2948 811 tfs->parent.parent.event_by_id,
812 hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k),
813 LTTV_PRIO_STATS_AFTER_STATE);
b445142a 814 }
815 }
816 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
817 LTTV_POINTER, &val);
818 *(val.v_pointer) = before_hooks;
819 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
820 LTTV_POINTER, &val);
821 *(val.v_pointer) = after_hooks;
822 }
b445142a 823}
824
825
826lttv_stats_remove_event_hooks(LttvTracesetStats *self)
827{
828 LttvTraceset *traceset = self->parent.parent.ts;
829
dbb7bb09 830 guint i, j, k, nb_trace, nb_tracefile;
b445142a 831
832 LttvTraceStats *ts;
833
834 LttvTracefileStats *tfs;
835
836 void *hook_data;
837
838 GArray *before_hooks, *after_hooks;
839
840 LttvTraceHook hook;
841
842 LttvAttributeValue val;
843
844 nb_trace = lttv_traceset_number(traceset);
845 for(i = 0 ; i < nb_trace ; i++) {
846 ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]);
847 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
848 LTTV_POINTER, &val);
849 before_hooks = *(val.v_pointer);
850 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
851 LTTV_POINTER, &val);
852 after_hooks = *(val.v_pointer);
853
359b2948 854 /* Remove these hooks from each event_by_id hooks list */
b445142a 855
dbb7bb09 856 nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
857 ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
b445142a 858
dbb7bb09 859 for(j = 0 ; j < nb_tracefile ; j++) {
860 tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
359b2948 861 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
b445142a 862 NULL);
863
864 for(k = 0 ; k < before_hooks->len ; k++) {
865 hook = g_array_index(before_hooks, LttvTraceHook, k);
866 lttv_hooks_remove_data(
359b2948 867 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id,
b445142a 868 hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k));
869 }
870 for(k = 0 ; k < after_hooks->len ; k++) {
871 hook = g_array_index(after_hooks, LttvTraceHook, k);
872 lttv_hooks_remove_data(
359b2948 873 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id,
b445142a 874 hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k));
875 }
876 }
2a2fa4f0 877 g_debug("lttv_stats_remove_event_hooks()");
b445142a 878 g_array_free(before_hooks, TRUE);
879 g_array_free(after_hooks, TRUE);
880 }
9f797243 881}
08b1c66e 882
883
884static void module_init()
885{
886 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
887 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
888 LTTV_STATS_CPU = g_quark_from_string("cpu");
889 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
890 LTTV_STATS_MODES = g_quark_from_string("modes");
891 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
892 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
893 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
894 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
895 LTTV_STATS_EVENTS = g_quark_from_string("events");
896 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
897 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
898 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
f95bc830 899 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
900 LTTV_STATS = g_quark_from_string("statistics");
901 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
902 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
08b1c66e 903}
904
905static void module_destroy()
906{
907}
908
909
910LTTV_MODULE("stats", "Compute processes statistics", \
911 "Accumulate statistics for event types, processes and CPUs", \
912 module_init, module_destroy, "state");
f95bc830 913
914/* Change the places where stats are called (create/read/write stats)
915
916 Check for options in batchtest.c to reduce writing and see what tests are
917 best candidates for performance analysis. Once OK, commit, move to main
918 and run tests. Update the gui for statistics. */
This page took 0.060835 seconds and 4 git commands to generate.