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