move everything out of trunk
[lttv.git] / lttng-xenomai / LinuxTraceToolkitViewer-0.8.61-xenoltt / lttv / lttv / stats.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <lttv/module.h>
25 #include <lttv/stats.h>
26 #include <lttv/lttv.h>
27 #include <lttv/attribute.h>
28 #include <ltt/facility.h>
29 #include <ltt/trace.h>
30 #include <ltt/event.h>
31 #include <ltt/type.h>
32
33 #define BUF_SIZE 256
34 #define MAX_64_HEX_STRING_LEN 19
35
36 GQuark
37 LTTV_STATS_PROCESS_UNKNOWN,
38 LTTV_STATS_PROCESSES,
39 LTTV_STATS_CPU,
40 LTTV_STATS_MODE_TYPES,
41 LTTV_STATS_MODES,
42 LTTV_STATS_SUBMODES,
43 LTTV_STATS_FUNCTIONS,
44 LTTV_STATS_EVENT_TYPES,
45 LTTV_STATS_CPU_TIME,
46 LTTV_STATS_CUMULATIVE_CPU_TIME,
47 LTTV_STATS_ELAPSED_TIME,
48 LTTV_STATS_EVENTS,
49 LTTV_STATS_EVENTS_COUNT,
50 LTTV_STATS_USE_COUNT,
51 LTTV_STATS,
52 LTTV_STATS_TRACEFILES,
53 LTTV_STATS_SUMMED,
54 LTTV_STATS_BEFORE_HOOKS,
55 LTTV_STATS_AFTER_HOOKS,
56 /***********************************************************/
57 LTTV_XENO_STATS_THREADS,
58 LTTV_XENO_STATS_THREAD_PERIOD,
59 LTTV_XENO_STATS_THREAD_PRIO,
60 LTTV_XENO_STATS_STATE,
61 LTTV_XENO_STATS_SYNCH,
62 LTTV_XENO_STATS_PERIOD,
63 LTTV_XENO_STATS_PERIOD_OVERRUNS,
64 LTTV_XENO_STATS_TEXT_OVERRUNS,
65 LTTV_XENO_STATS_TEXT_TICKS,
66 LTTV_XENO_STATS_TEXT_TOTAL,
67 LTTV_XENO_STATS_TEXT_OWNER,
68 LTTV_XENO_STATS_TEXT_WAITING,
69 LTTV_XENO_STATS_TEXT_OWNER_TOTAL,
70 LTTV_XENO_STATS_TEXT_OWNER_MAX,
71 LTTV_XENO_STATS_TEXT_OWNER_MIN,
72 LTTV_XENO_STATS_TEXT_OWNER_AVG,
73 LTTV_XENO_STATS_TEXT_WAITING,
74 LTTV_XENO_STATS_TEXT_WAITING_TOTAL,
75 LTTV_XENO_STATS_TEXT_WAITING_MAX,
76 LTTV_XENO_STATS_TEXT_WAITING_MIN,
77 LTTV_XENO_STATS_TEXT_WAITING_AVG,
78 LTTV_XENO_STATS_TEXT_READY_MAX,
79 LTTV_XENO_STATS_TEXT_READY_MIN,
80 LTTV_XENO_STATS_TEXT_READY_AVG,
81 LTTV_XENO_STATS_TEXT_RUNNING_MAX,
82 LTTV_XENO_STATS_TEXT_RUNNING_MIN,
83 LTTV_XENO_STATS_TEXT_RUNNING_AVG,
84 LTTV_XENO_STATS_TEXT_SUSPEND_MAX,
85 LTTV_XENO_STATS_TEXT_SUSPEND_MIN,
86 LTTV_XENO_STATS_TEXT_SUSPEND_AVG,
87 LTTV_XENO_STATS_NB_PERIOD,
88 LTTV_XENO_STATS;
89 /***********************************************************/
90
91 /****************************************************************************************************************************/
92 static void xeno_find_task_tree(LttvTracefileStats *tfcs, GQuark name, gulong address, guint cpu, LttvAttribute **events_tree, LttvAttribute **event_types_tree);
93 gboolean xenoltt_thread_init(void *hook_data, void *call_data);
94 gboolean xenoltt_thread_set_period(void *hook_data, void *call_data);
95 gboolean xenoltt_thread_renice(void *hook_data, void *call_data);
96 gboolean xenoltt_before_change_state(void *hook_data, void *call_data);
97 gboolean xenoltt_after_change_state(void *hook_data, void *call_data);
98 gboolean xenoltt_thread_overruns(void *hook_data, void *call_data);
99 gboolean xenoltt_synch_owner(void *hook_data, void *call_data);
100 gboolean xenoltt_synch_wait(void *hook_data, void *call_data);
101 gboolean xenoltt_synch_unblock(void *hook_data, void *call_data);
102 gboolean xenoltt_synch_wakeup(void *hook_data, void *call_data);
103 gboolean xenoltt_synch_flush(void *hook_data, void *call_data);
104 /****************************************************************************************************************************/
105 static void
106 find_event_tree(LttvTracefileStats *tfcs, GQuark pid_time, guint cpu,
107 guint64 function,
108 GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
109 LttvAttribute **event_types_tree);
110
111
112 static void lttv_stats_init(LttvTracesetStats *self)
113 {
114 guint i, j, nb_trace, nb_tracefile;
115
116 LttvTraceContext *tc;
117
118 LttvTraceStats *tcs;
119
120 LttvTracefileContext **tfs;
121 LttvTracefileStats *tfcs;
122
123 LttvAttributeValue v;
124
125 LttvAttribute *tracefiles_stats;
126
127 LttvTraceset *ts = self->parent.parent.ts;
128
129 self->stats = lttv_attribute_find_subdir(
130 lttv_traceset_attribute(self->parent.parent.ts),
131 LTTV_STATS);
132 lttv_attribute_find(lttv_traceset_attribute(self->parent.parent.ts),
133 LTTV_STATS_USE_COUNT,
134 LTTV_UINT, &v);
135
136 self->xenoltt_stats = lttv_attribute_find_subdir(
137 lttv_traceset_attribute(self->parent.parent.ts),
138 LTTV_STATS);
139
140 (*(v.v_uint))++;
141 if(*(v.v_uint) == 1) {
142 g_assert(lttv_attribute_get_number(self->stats) == 0);
143 }
144
145 nb_trace = lttv_traceset_number(ts);
146
147 for(i = 0 ; i < nb_trace ; i++) {
148 tc = self->parent.parent.traces[i];
149 tcs = LTTV_TRACE_STATS(tc);
150
151 tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
152
153 tcs->xenoltt_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
154
155 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
156 LTTV_STATS_TRACEFILES);
157 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
158 LTTV_UINT, &v);
159
160 (*(v.v_uint))++;
161 if(*(v.v_uint) == 1) {
162 g_assert(lttv_attribute_get_number(tcs->stats) == 0);
163 }
164
165 nb_tracefile = tc->tracefiles->len;
166
167 for(j = 0 ; j < nb_tracefile ; j++) {
168 tfs = &g_array_index(tc->tracefiles,
169 LttvTracefileContext*, j);
170 tfcs = LTTV_TRACEFILE_STATS(*tfs);
171 tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
172 ltt_tracefile_long_name(tfcs->parent.parent.tf));
173 guint cpu = tfcs->parent.cpu;
174 find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
175 cpu,
176 0x0ULL,
177 LTTV_STATE_MODE_UNKNOWN,
178 LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
179 &tfcs->current_event_types_tree);
180 }
181 }
182 }
183
184 static void lttv_stats_fini(LttvTracesetStats *self)
185 {
186 guint i, j, nb_trace, nb_tracefile;
187
188 LttvTraceset *ts;
189
190 LttvTraceContext *tc;
191
192 LttvTraceStats *tcs;
193
194 LttvTracefileContext *tfc;
195
196 LttvTracefileStats *tfcs;
197
198 LttvAttributeValue v;
199
200 LttvAttribute *tracefiles_stats;
201
202 lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
203 LTTV_UINT, &v);
204 (*(v.v_uint))--;
205
206 if(*(v.v_uint) == 0) {
207 lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
208 }
209 self->stats = NULL;
210
211 ts = self->parent.parent.ts;
212 nb_trace = lttv_traceset_number(ts);
213
214 for(i = 0 ; i < nb_trace ; i++) {
215 tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]));
216
217 lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
218 LTTV_UINT, &v);
219 (*(v.v_uint))--;
220
221 if(*(v.v_uint) == 0) {
222 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
223 tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
224 LTTV_STATS_TRACEFILES);
225 lttv_attribute_remove_by_name(tcs->parent.parent.t_a,
226 LTTV_STATS_TRACEFILES);
227 }
228 tcs->stats = NULL;
229
230 nb_tracefile = tc->tracefiles->len;
231
232 for(j = 0 ; j < nb_tracefile ; j++) {
233 tfc = g_array_index(tc->tracefiles,
234 LttvTracefileContext*, j);
235 tfcs = (LttvTracefileStats *)tfc;
236 tfcs->stats = NULL;
237 tfcs->current_events_tree = NULL;
238 tfcs->current_event_types_tree = NULL;
239 }
240 }
241 }
242
243
244 void lttv_stats_reset(LttvTracesetStats *self)
245 {
246 lttv_stats_fini(self);
247 lttv_stats_init(self);
248 }
249
250
251
252 static void
253 init(LttvTracesetStats *self, LttvTraceset *ts)
254 {
255 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
256 init((LttvTracesetContext *)self, ts);
257
258 lttv_stats_init(self);
259 }
260
261
262 static void
263 fini(LttvTracesetStats *self)
264 {
265 lttv_stats_fini(self);
266
267 LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
268 fini((LttvTracesetContext *)self);
269 }
270
271
272 static LttvTracesetContext *
273 new_traceset_context(LttvTracesetContext *self)
274 {
275 return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
276 }
277
278
279 static LttvTraceContext *
280 new_trace_context(LttvTracesetContext *self)
281 {
282 return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
283 }
284
285
286 static LttvTracefileContext *
287 new_tracefile_context(LttvTracesetContext *self)
288 {
289 return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
290 }
291
292
293 static void
294 traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
295 {
296 }
297
298
299 static void
300 traceset_stats_finalize (LttvTracesetStats *self)
301 {
302 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
303 finalize(G_OBJECT(self));
304 }
305
306
307 static void
308 traceset_stats_class_init (LttvTracesetContextClass *klass)
309 {
310 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
311
312 gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
313 klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
314 klass->fini = (void (*)(LttvTracesetContext *self))fini;
315 klass->new_traceset_context = new_traceset_context;
316 klass->new_trace_context = new_trace_context;
317 klass->new_tracefile_context = new_tracefile_context;
318 }
319
320
321 GType
322 lttv_traceset_stats_get_type(void)
323 {
324 static GType type = 0;
325 if (type == 0) {
326 static const GTypeInfo info = {
327 sizeof (LttvTracesetStatsClass),
328 NULL, /* base_init */
329 NULL, /* base_finalize */
330 (GClassInitFunc) traceset_stats_class_init, /* class_init */
331 NULL, /* class_finalize */
332 NULL, /* class_data */
333 sizeof (LttvTracesetStats),
334 0, /* n_preallocs */
335 (GInstanceInitFunc) traceset_stats_instance_init, /* instance_init */
336 NULL /* Value handling */
337 };
338
339 type = g_type_register_static (LTTV_TRACESET_STATE_TYPE,
340 "LttvTracesetStatsType",
341 &info, 0);
342 }
343 return type;
344 }
345
346
347 static void
348 trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
349 {
350 }
351
352
353 static void
354 trace_stats_finalize (LttvTraceStats *self)
355 {
356 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
357 finalize(G_OBJECT(self));
358 }
359
360
361 static void
362 trace_stats_class_init (LttvTraceContextClass *klass)
363 {
364 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
365
366 gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
367 }
368
369
370 GType
371 lttv_trace_stats_get_type(void)
372 {
373 static GType type = 0;
374 if (type == 0) {
375 static const GTypeInfo info = {
376 sizeof (LttvTraceStatsClass),
377 NULL, /* base_init */
378 NULL, /* base_finalize */
379 (GClassInitFunc) trace_stats_class_init, /* class_init */
380 NULL, /* class_finalize */
381 NULL, /* class_data */
382 sizeof (LttvTraceStats),
383 0, /* n_preallocs */
384 (GInstanceInitFunc) trace_stats_instance_init, /* instance_init */
385 NULL /* Value handling */
386 };
387
388 type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
389 "LttvTraceStatsType", &info, 0);
390 }
391 return type;
392 }
393
394
395 static void
396 tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
397 {
398 }
399
400
401 static void
402 tracefile_stats_finalize (LttvTracefileStats *self)
403 {
404 G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
405 finalize(G_OBJECT(self));
406 }
407
408
409 static void
410 tracefile_stats_class_init (LttvTracefileStatsClass *klass)
411 {
412 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
413
414 gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
415 }
416
417
418 GType
419 lttv_tracefile_stats_get_type(void)
420 {
421 static GType type = 0;
422 if (type == 0) {
423 static const GTypeInfo info = {
424 sizeof (LttvTracefileStatsClass),
425 NULL, /* base_init */
426 NULL, /* base_finalize */
427 (GClassInitFunc) tracefile_stats_class_init, /* class_init */
428 NULL, /* class_finalize */
429 NULL, /* class_data */
430 sizeof (LttvTracefileStats),
431 0, /* n_preallocs */
432 (GInstanceInitFunc) tracefile_stats_instance_init, /* instance_init */
433 NULL /* Value handling */
434 };
435
436 type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
437 "LttvTracefileStatsType", &info, 0);
438 }
439 return type;
440 }
441
442
443 static void
444 find_event_tree(LttvTracefileStats *tfcs,
445 GQuark pid_time,
446 guint cpu,
447 guint64 function,
448 GQuark mode,
449 GQuark sub_mode,
450 LttvAttribute **events_tree,
451 LttvAttribute **event_types_tree)
452 {
453 LttvAttribute *a;
454 gchar fstring[MAX_64_HEX_STRING_LEN];
455 gint ret;
456
457 ret = snprintf(fstring, MAX_64_HEX_STRING_LEN-1,
458 "0x%llX", function) > 0;
459 g_assert(ret > 0);
460 fstring[MAX_64_HEX_STRING_LEN-1] = '\0';
461
462 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
463 a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
464 a = lttv_attribute_find_subdir(a, pid_time);
465 a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
466 a = lttv_attribute_find_subdir_unnamed(a, cpu);
467 a = lttv_attribute_find_subdir(a, LTTV_STATS_FUNCTIONS);
468 a = lttv_attribute_find_subdir(a, g_quark_from_string(fstring));
469 a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
470 a = lttv_attribute_find_subdir(a, mode);
471 a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
472 a = lttv_attribute_find_subdir(a, sub_mode);
473 *events_tree = a;
474 a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
475 *event_types_tree = a;
476 }
477
478
479 static void update_event_tree(LttvTracefileStats *tfcs)
480 {
481 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
482 guint cpu = tfcs->parent.cpu;
483 LttvProcessState *process = ts->running_process[cpu];
484 LttvExecutionState *es = process->state;
485
486 find_event_tree(tfcs, process->pid_time,
487 cpu,
488 process->current_function,
489 es->t, es->n, &(tfcs->current_events_tree),
490 &(tfcs->current_event_types_tree));
491 }
492
493
494 static void mode_change(LttvTracefileStats *tfcs)
495 {
496 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
497 guint cpu = tfcs->parent.cpu;
498 LttvProcessState *process = ts->running_process[cpu];
499 LttvAttributeValue cpu_time;
500 LttTime delta;
501
502 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
503 process->state->change);
504
505 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, LTTV_TIME, &cpu_time);
506 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
507
508 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
509 delta);
510 }
511
512 /* Note : every mode_end must come with a cumulative cpu time update in the
513 * after hook */
514 static void mode_end(LttvTracefileStats *tfcs)
515 {
516 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
517 guint cpu = tfcs->parent.cpu;
518 LttvProcessState *process = ts->running_process[cpu];
519 LttvAttributeValue elapsed_time, cpu_time, cum_cpu_time;
520
521 LttTime delta;
522
523 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
524 LTTV_TIME, &elapsed_time);
525 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
526 process->state->entry);
527 *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
528
529 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
530 LTTV_TIME, &cpu_time);
531 delta = ltt_time_sub(tfcs->parent.parent.timestamp,
532 process->state->change);
533 *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
534 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
535 delta);
536
537 lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CUMULATIVE_CPU_TIME,
538 LTTV_TIME, &cum_cpu_time);
539 *(cum_cpu_time.v_time) = ltt_time_add(*(cum_cpu_time.v_time),
540 process->state->cum_cpu_time);
541 }
542
543
544 static void after_mode_end(LttvTracefileStats *tfcs)
545 {
546 LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
547 guint cpu = tfcs->parent.cpu;
548 LttvProcessState *process = ts->running_process[cpu];
549
550 LttTime nested_delta;
551
552 nested_delta = process->state->cum_cpu_time;
553 process->state->cum_cpu_time = ltt_time_zero; /* For after traceset hook */
554
555 update_event_tree(tfcs);
556
557 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
558 nested_delta);
559 }
560
561 static gboolean before_syscall_entry(void *hook_data, void *call_data)
562 {
563 mode_change((LttvTracefileStats *)call_data);
564 return FALSE;
565 }
566
567
568 static gboolean after_syscall_entry(void *hook_data, void *call_data)
569 {
570 update_event_tree((LttvTracefileStats *)call_data);
571 return FALSE;
572 }
573
574
575 gboolean before_syscall_exit(void *hook_data, void *call_data)
576 {
577 mode_end((LttvTracefileStats *)call_data);
578 return FALSE;
579 }
580
581
582 static gboolean after_syscall_exit(void *hook_data, void *call_data)
583 {
584 after_mode_end((LttvTracefileStats *)call_data);
585 return FALSE;
586 }
587
588
589 gboolean before_trap_entry(void *hook_data, void *call_data)
590 {
591 mode_change((LttvTracefileStats *)call_data);
592 return FALSE;
593 }
594
595
596 static gboolean after_trap_entry(void *hook_data, void *call_data)
597 {
598 update_event_tree((LttvTracefileStats *)call_data);
599 return FALSE;
600 }
601
602
603 gboolean before_trap_exit(void *hook_data, void *call_data)
604 {
605 mode_end((LttvTracefileStats *)call_data);
606 return FALSE;
607 }
608
609
610 gboolean after_trap_exit(void *hook_data, void *call_data)
611 {
612 after_mode_end((LttvTracefileStats *)call_data);
613 return FALSE;
614 }
615
616
617 gboolean before_irq_entry(void *hook_data, void *call_data)
618 {
619 mode_change((LttvTracefileStats *)call_data);
620 return FALSE;
621 }
622
623 gboolean after_irq_entry(void *hook_data, void *call_data)
624 {
625 update_event_tree((LttvTracefileStats *)call_data);
626 return FALSE;
627 }
628
629
630 gboolean before_irq_exit(void *hook_data, void *call_data)
631 {
632 mode_end((LttvTracefileStats *)call_data);
633 return FALSE;
634 }
635
636
637 gboolean after_irq_exit(void *hook_data, void *call_data)
638 {
639 after_mode_end((LttvTracefileStats *)call_data);
640 return FALSE;
641 }
642
643
644 gboolean before_soft_irq_entry(void *hook_data, void *call_data)
645 {
646 mode_change((LttvTracefileStats *)call_data);
647 return FALSE;
648 }
649
650 gboolean after_soft_irq_entry(void *hook_data, void *call_data)
651 {
652 update_event_tree((LttvTracefileStats *)call_data);
653 return FALSE;
654 }
655
656
657 gboolean before_soft_irq_exit(void *hook_data, void *call_data)
658 {
659 mode_end((LttvTracefileStats *)call_data);
660 return FALSE;
661 }
662
663
664 gboolean after_soft_irq_exit(void *hook_data, void *call_data)
665 {
666 after_mode_end((LttvTracefileStats *)call_data);
667 return FALSE;
668 }
669
670 gboolean before_function_entry(void *hook_data, void *call_data)
671 {
672 mode_change((LttvTracefileStats *)call_data);
673 return FALSE;
674 }
675
676 gboolean after_function_entry(void *hook_data, void *call_data)
677 {
678 update_event_tree((LttvTracefileStats *)call_data);
679 return FALSE;
680 }
681
682 gboolean before_function_exit(void *hook_data, void *call_data)
683 {
684 mode_end((LttvTracefileStats *)call_data);
685 return FALSE;
686 }
687
688 gboolean after_function_exit(void *hook_data, void *call_data)
689 {
690 after_mode_end((LttvTracefileStats *)call_data);
691 return FALSE;
692 }
693
694
695 gboolean before_schedchange(void *hook_data, void *call_data)
696 {
697 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
698
699 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
700
701 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
702
703 guint pid_in, pid_out;
704
705 gint state_out;
706
707 pid_out = ltt_event_get_unsigned(e, thf->f1);
708 pid_in = ltt_event_get_unsigned(e, thf->f2);
709 state_out = ltt_event_get_int(e, thf->f3);
710
711 /* compute the time for the process to schedule out */
712
713 mode_change(tfcs);
714
715 return FALSE;
716 }
717
718 gboolean after_schedchange(void *hook_data, void *call_data)
719 {
720 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
721
722 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
723
724 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
725
726 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
727
728 guint pid_in, pid_out;
729
730 gint state_out;
731
732 LttvProcessState *process;
733
734 pid_out = ltt_event_get_unsigned(e, thf->f1);
735 pid_in = ltt_event_get_unsigned(e, thf->f2);
736 state_out = ltt_event_get_int(e, thf->f3);
737
738 /* get the information for the process scheduled in */
739 guint cpu = tfcs->parent.cpu;
740 process = ts->running_process[cpu];
741
742 find_event_tree(tfcs, process->pid_time,
743 cpu,
744 process->current_function,
745 process->state->t, process->state->n, &(tfcs->current_events_tree),
746 &(tfcs->current_event_types_tree));
747
748 /* compute the time waiting for the process to schedule in */
749 mode_change(tfcs);
750
751 return FALSE;
752 }
753
754 gboolean process_fork(void *hook_data, void *call_data)
755 {
756 /* nothing to do for now */
757 return FALSE;
758 }
759
760
761 gboolean process_exit(void *hook_data, void *call_data)
762 {
763 /* We should probably exit all modes here or we could do that at
764 schedule out. */
765 return FALSE;
766 }
767
768 gboolean before_enum_process_state(void *hook_data, void *call_data)
769 {
770 mode_end((LttvTracefileStats *)call_data);
771 after_mode_end((LttvTracefileStats *)call_data);
772 mode_change((LttvTracefileStats *)call_data);
773 return FALSE;
774 }
775
776 gboolean after_enum_process_state(void *hook_data, void *call_data)
777 {
778 update_event_tree((LttvTracefileStats *)call_data);
779 return FALSE;
780 }
781
782 gboolean process_free(void *hook_data, void *call_data)
783 {
784 return FALSE;
785 }
786
787 gboolean every_event(void *hook_data, void *call_data)
788 {
789 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
790
791 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
792
793 LttvAttributeValue v;
794
795 /* The current branch corresponds to the tracefile/process/interrupt state.
796 Statistics are added within it, to count the number of events of this
797 type occuring in this context. A quark has been pre-allocated for each
798 event type and is used as name. */
799
800 lttv_attribute_find(tfcs->current_event_types_tree,
801 ltt_eventtype_name(ltt_event_eventtype(e)),
802 LTTV_UINT, &v);
803 (*(v.v_uint))++;
804 return FALSE;
805 }
806
807 static void lttv_stats_cleanup_process_state(gpointer key, gpointer value,
808 gpointer user_data)
809 {
810 LttvTraceState *ts = (LttvTraceState *)user_data;
811 LttvProcessState *process = (LttvProcessState *)value;
812 LttvTracefileStats **tfs = (LttvTracefileStats **)
813 &g_array_index(ts->parent.tracefiles, LttvTracefileContext*,
814 process->cpu);
815 int cleanup_empty = 0;
816 LttTime nested_delta = ltt_time_zero;
817 /* FIXME : ok, this is a hack. The time is infinite here :( */
818 LttTime save_time = (*tfs)->parent.parent.timestamp;
819 LttTime start, end;
820 ltt_trace_time_span_get(ts->parent.t, &start, &end);
821 (*tfs)->parent.parent.timestamp = end;
822
823 do {
824 if(ltt_time_compare(process->state->cum_cpu_time, ltt_time_zero) != 0) {
825 find_event_tree(*tfs, process->pid_time,
826 process->cpu,
827 process->current_function,
828 process->state->t, process->state->n, &((*tfs)->current_events_tree),
829 &((*tfs)->current_event_types_tree));
830 mode_end(*tfs);
831 nested_delta = process->state->cum_cpu_time;
832 }
833 cleanup_empty = lttv_state_pop_state_cleanup(process,
834 (LttvTracefileState *)*tfs);
835 process->state->cum_cpu_time = ltt_time_add(process->state->cum_cpu_time,
836 nested_delta);
837
838 } while(cleanup_empty != 1);
839
840 (*tfs)->parent.parent.timestamp = save_time;
841 }
842
843 /* For each process in the state, for each of their stacked states,
844 * perform sum of needed values. */
845 static void lttv_stats_cleanup_state(LttvTraceStats *tcs)
846 {
847 LttvTraceState *ts = (LttvTraceState *)tcs;
848
849 /* Does not work correctly FIXME. */
850 g_hash_table_foreach(ts->processes, lttv_stats_cleanup_process_state,
851 tcs);
852 }
853
854 void
855 lttv_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats)
856 {
857 LttvAttribute *sum_container = self->stats;
858
859 LttvAttributeType type;
860
861 LttvAttributeValue value;
862
863 LttvAttributeName name;
864
865 gboolean is_named;
866
867 unsigned sum;
868
869 int trace_is_summed;
870
871 int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
872 nb_event_type, nf, nb_functions;
873
874 LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
875 *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
876 *submode_tree, *event_types_tree, *mode_events_tree,
877 *cpu_functions_tree,
878 *function_tree,
879 *function_mode_types_tree,
880 *trace_cpu_tree;
881
882
883 main_tree = sum_container;
884
885 lttv_attribute_find(sum_container,
886 LTTV_STATS_SUMMED,
887 LTTV_UINT, &value);
888 trace_is_summed = *(value.v_uint);
889 *(value.v_uint) = 1;
890
891 /* First cleanup the state : sum all stalled information (never ending
892 * states). */
893 if(!trace_is_summed)
894 lttv_stats_cleanup_state(self);
895
896 processes_tree = lttv_attribute_find_subdir(main_tree,
897 LTTV_STATS_PROCESSES);
898 nb_process = lttv_attribute_get_number(processes_tree);
899
900 for(i = 0 ; i < nb_process ; i++) {
901 type = lttv_attribute_get(processes_tree, i, &name, &value, &is_named);
902 process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
903
904 cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
905 nb_cpu = lttv_attribute_get_number(cpus_tree);
906
907 for(j = 0 ; j < nb_cpu ; j++) {
908 type = lttv_attribute_get(cpus_tree, j, &name, &value, &is_named);
909 cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
910
911 trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
912 trace_cpu_tree = lttv_attribute_find_subdir_unnamed(trace_cpu_tree, name);
913 cpu_functions_tree = lttv_attribute_find_subdir(cpu_tree,
914 LTTV_STATS_FUNCTIONS);
915 nb_functions = lttv_attribute_get_number(cpu_functions_tree);
916
917 for(nf=0; nf < nb_functions; nf++) {
918 type = lttv_attribute_get(cpu_functions_tree, nf, &name, &value,
919 &is_named);
920 function_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
921 function_mode_types_tree = lttv_attribute_find_subdir(function_tree,
922 LTTV_STATS_MODE_TYPES);
923 nb_mode_type = lttv_attribute_get_number(function_mode_types_tree);
924 for(k = 0 ; k < nb_mode_type ; k++) {
925 type = lttv_attribute_get(function_mode_types_tree, k, &name, &value,
926 &is_named);
927 mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
928
929 submodes_tree = lttv_attribute_find_subdir(mode_tree,
930 LTTV_STATS_SUBMODES);
931 mode_events_tree = lttv_attribute_find_subdir(mode_tree,
932 LTTV_STATS_EVENTS);
933 mode_types_tree = lttv_attribute_find_subdir(mode_tree,
934 LTTV_STATS_MODE_TYPES);
935
936 nb_submode = lttv_attribute_get_number(submodes_tree);
937
938 for(l = 0 ; l < nb_submode ; l++) {
939 type = lttv_attribute_get(submodes_tree, l, &name, &value,
940 &is_named);
941 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
942
943 event_types_tree = lttv_attribute_find_subdir(submode_tree,
944 LTTV_STATS_EVENT_TYPES);
945 nb_event_type = lttv_attribute_get_number(event_types_tree);
946
947 sum = 0;
948 for(m = 0 ; m < nb_event_type ; m++) {
949 type = lttv_attribute_get(event_types_tree, m, &name, &value,
950 &is_named);
951 sum += *(value.v_uint);
952 }
953 lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
954 LTTV_UINT, &value);
955 *(value.v_uint) = sum;
956
957 type = lttv_attribute_get(submodes_tree, l, &name, &value,
958 &is_named);
959 submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
960 if(!trace_is_summed) {
961 lttv_attribute_recursive_add(mode_events_tree, event_types_tree);
962 lttv_attribute_recursive_add(mode_types_tree, submode_tree);
963 }
964 }
965 if(!trace_is_summed) {
966 lttv_attribute_recursive_add(function_tree, mode_types_tree);
967 }
968 }
969 if(!trace_is_summed) {
970 lttv_attribute_recursive_add(cpu_tree, function_tree);
971 lttv_attribute_recursive_add(process_tree, function_tree);
972 lttv_attribute_recursive_add(trace_cpu_tree, function_tree);
973 lttv_attribute_recursive_add(main_tree, function_tree);
974 }
975 lttv_attribute_recursive_add(ts_stats, function_tree);
976 }
977 }
978 }
979 }
980
981
982 gboolean lttv_stats_sum_traceset_hook(void *hook_data, void *call_data)
983 {
984 lttv_stats_sum_traceset((LttvTracesetStats *)call_data);
985 return 0;
986 }
987
988 void
989 lttv_stats_sum_traceset(LttvTracesetStats *self)
990 {
991 LttvTraceset *traceset = self->parent.parent.ts;
992 LttvAttribute *sum_container = self->stats;
993
994 LttvTraceStats *tcs;
995
996 int i, nb_trace;
997
998 LttvAttributeValue value;
999
1000 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
1001 LTTV_UINT, &value);
1002 if(*(value.v_uint) != 0) return;
1003 *(value.v_uint) = 1;
1004
1005 nb_trace = lttv_traceset_number(traceset);
1006
1007 for(i = 0 ; i < nb_trace ; i++) {
1008 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
1009 lttv_stats_sum_trace(tcs, self->stats);
1010 // lttv_attribute_recursive_add(sum_container, tcs->stats);
1011 }
1012 }
1013
1014
1015 // Hook wrapper. call_data is a traceset context.
1016 gboolean lttv_stats_hook_add_event_hooks(void *hook_data, void *call_data)
1017 {
1018 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1019
1020 lttv_stats_add_event_hooks(tss);
1021
1022 return 0;
1023 }
1024
1025 void lttv_stats_add_event_hooks(LttvTracesetStats *self)
1026 {
1027 LttvTraceset *traceset = self->parent.parent.ts;
1028
1029 guint i, j, k, l, nb_trace, nb_tracefile;
1030
1031 LttvTraceStats *ts;
1032
1033 LttvTracefileStats *tfs;
1034
1035 GArray *hooks, *before_hooks, *after_hooks;
1036
1037 LttvTraceHook *hook;
1038
1039 LttvTraceHookByFacility *thf;
1040
1041 LttvAttributeValue val;
1042
1043 gint ret;
1044 gint hn;
1045
1046 nb_trace = lttv_traceset_number(traceset);
1047 for(i = 0 ; i < nb_trace ; i++) {
1048 ts = (LttvTraceStats *)self->parent.parent.traces[i];
1049
1050 /* Find the eventtype id for the following events and register the
1051 associated by id hooks. */
1052
1053 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 16);
1054 g_array_set_size(hooks, 16);
1055 hn=0;
1056
1057 ret = lttv_trace_find_hook(ts->parent.parent.t,
1058 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
1059 LTT_FIELD_SYSCALL_ID, 0, 0,
1060 before_syscall_entry, NULL,
1061 &g_array_index(hooks, LttvTraceHook, hn++));
1062 if(ret) hn--;
1063
1064 ret = lttv_trace_find_hook(ts->parent.parent.t,
1065 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
1066 0, 0, 0,
1067 before_syscall_exit, NULL,
1068 &g_array_index(hooks, LttvTraceHook, hn++));
1069 if(ret) hn--;
1070
1071 ret = lttv_trace_find_hook(ts->parent.parent.t,
1072 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1073 LTT_FIELD_TRAP_ID, 0, 0,
1074 before_trap_entry, NULL,
1075 &g_array_index(hooks, LttvTraceHook, hn++));
1076 if(ret) hn--;
1077
1078 ret = lttv_trace_find_hook(ts->parent.parent.t,
1079 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1080 0, 0, 0,
1081 before_trap_exit, NULL,
1082 &g_array_index(hooks, LttvTraceHook, hn++));
1083 if(ret) hn--;
1084
1085 ret = lttv_trace_find_hook(ts->parent.parent.t,
1086 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1087 LTT_FIELD_IRQ_ID, 0, 0,
1088 before_irq_entry, NULL,
1089 &g_array_index(hooks, LttvTraceHook, hn++));
1090 if(ret) hn--;
1091
1092 ret = lttv_trace_find_hook(ts->parent.parent.t,
1093 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1094 0, 0, 0,
1095 before_irq_exit, NULL,
1096 &g_array_index(hooks, LttvTraceHook, hn++));
1097 if(ret) hn--;
1098
1099 ret = lttv_trace_find_hook(ts->parent.parent.t,
1100 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1101 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1102 before_soft_irq_entry, NULL,
1103 &g_array_index(hooks, LttvTraceHook, hn++));
1104 if(ret) hn--;
1105
1106 ret = lttv_trace_find_hook(ts->parent.parent.t,
1107 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1108 0, 0, 0,
1109 before_soft_irq_exit, NULL,
1110 &g_array_index(hooks, LttvTraceHook, hn++));
1111 if(ret) hn--;
1112
1113 ret = lttv_trace_find_hook(ts->parent.parent.t,
1114 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1115 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1116 before_schedchange, NULL,
1117 &g_array_index(hooks, LttvTraceHook, hn++));
1118 if(ret) hn--;
1119
1120 ret = lttv_trace_find_hook(ts->parent.parent.t,
1121 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1122 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1123 before_function_entry, NULL,
1124 &g_array_index(hooks, LttvTraceHook, hn++));
1125 if(ret) hn--;
1126
1127 ret = lttv_trace_find_hook(ts->parent.parent.t,
1128 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1129 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1130 before_function_exit, NULL,
1131 &g_array_index(hooks, LttvTraceHook, hn++));
1132 if(ret) hn--;
1133
1134 /* statedump-related hooks */
1135 ret = lttv_trace_find_hook(ts->parent.parent.t,
1136 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1137 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1138 before_enum_process_state, NULL,
1139 &g_array_index(hooks, LttvTraceHook, hn++));
1140 if(ret) hn--;
1141
1142 ret = lttv_trace_find_hook(ts->parent.parent.t,
1143 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_START,
1144 0, 0, 0,
1145 xenoltt_before_change_state, NULL,
1146 &g_array_index(hooks, LttvTraceHook, hn++));
1147 if(ret) hn--;
1148
1149 ret = lttv_trace_find_hook(ts->parent.parent.t,
1150 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_RESUME,
1151 0, 0, 0,
1152 xenoltt_before_change_state, NULL,
1153 &g_array_index(hooks, LttvTraceHook, hn++));
1154 if(ret) hn--;
1155
1156 ret = lttv_trace_find_hook(ts->parent.parent.t,
1157 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_WAIT_PERIOD,
1158 0, 0, 0,
1159 xenoltt_before_change_state, NULL,
1160 &g_array_index(hooks, LttvTraceHook, hn++));
1161 if(ret) hn--;
1162
1163 ret = lttv_trace_find_hook(ts->parent.parent.t,
1164 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SUSPEND,
1165 0, 0, 0,
1166 xenoltt_before_change_state, 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_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SWITCH,
1172 0, 0, 0,
1173 xenoltt_before_change_state, 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_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_UNLOCK,
1179 LTT_FIELD_XENOLTT_SYNCH, 0, 0,
1180 xenoltt_synch_unblock, NULL,
1181 &g_array_index(hooks, LttvTraceHook, hn++));
1182 if(ret) hn--;
1183
1184 g_array_set_size(hooks, hn);
1185
1186 before_hooks = hooks;
1187
1188 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 24);
1189 g_array_set_size(hooks, 24);
1190 hn=0;
1191
1192 ret = lttv_trace_find_hook(ts->parent.parent.t,
1193 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
1194 LTT_FIELD_SYSCALL_ID, 0, 0,
1195 after_syscall_entry, NULL,
1196 &g_array_index(hooks, LttvTraceHook, hn++));
1197 if(ret) hn--;
1198
1199 ret = lttv_trace_find_hook(ts->parent.parent.t,
1200 LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_EXIT,
1201 0, 0, 0,
1202 after_syscall_exit, NULL,
1203 &g_array_index(hooks, LttvTraceHook, hn++));
1204 if(ret) hn--;
1205
1206 ret = lttv_trace_find_hook(ts->parent.parent.t,
1207 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_ENTRY,
1208 LTT_FIELD_TRAP_ID, 0, 0,
1209 after_trap_entry, NULL,
1210 &g_array_index(hooks, LttvTraceHook, hn++));
1211 if(ret) hn--;
1212
1213 ret = lttv_trace_find_hook(ts->parent.parent.t,
1214 LTT_FACILITY_KERNEL, LTT_EVENT_TRAP_EXIT,
1215 0, 0, 0,
1216 after_trap_exit, NULL,
1217 &g_array_index(hooks, LttvTraceHook, hn++));
1218 if(ret) hn--;
1219
1220 ret = lttv_trace_find_hook(ts->parent.parent.t,
1221 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY,
1222 LTT_FIELD_IRQ_ID, 0, 0,
1223 after_irq_entry, NULL,
1224 &g_array_index(hooks, LttvTraceHook, hn++));
1225 if(ret) hn--;
1226
1227 ret = lttv_trace_find_hook(ts->parent.parent.t,
1228 LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT,
1229 0, 0, 0,
1230 after_irq_exit, NULL,
1231 &g_array_index(hooks, LttvTraceHook, hn++));
1232 if(ret) hn--;
1233
1234 ret = lttv_trace_find_hook(ts->parent.parent.t,
1235 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY,
1236 LTT_FIELD_SOFT_IRQ_ID, 0, 0,
1237 after_irq_entry, NULL,
1238 &g_array_index(hooks, LttvTraceHook, hn++));
1239 if(ret) hn--;
1240
1241 ret = lttv_trace_find_hook(ts->parent.parent.t,
1242 LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT,
1243 0, 0, 0,
1244 after_soft_irq_exit, NULL,
1245 &g_array_index(hooks, LttvTraceHook, hn++));
1246 if(ret) hn--;
1247
1248 ret = lttv_trace_find_hook(ts->parent.parent.t,
1249 LTT_FACILITY_PROCESS, LTT_EVENT_SCHEDCHANGE,
1250 LTT_FIELD_OUT, LTT_FIELD_IN, LTT_FIELD_OUT_STATE,
1251 after_schedchange, NULL,
1252 &g_array_index(hooks, LttvTraceHook, hn++));
1253 if(ret) hn--;
1254
1255 ret = lttv_trace_find_hook(ts->parent.parent.t,
1256 LTT_FACILITY_PROCESS, LTT_EVENT_FORK,
1257 LTT_FIELD_PARENT_PID, LTT_FIELD_CHILD_PID, 0,
1258 process_fork, NULL,
1259 &g_array_index(hooks, LttvTraceHook, hn++));
1260 if(ret) hn--;
1261
1262 ret = lttv_trace_find_hook(ts->parent.parent.t,
1263 LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
1264 LTT_FIELD_PID, 0, 0,
1265 process_exit, 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_PROCESS, LTT_EVENT_FREE,
1271 LTT_FIELD_PID, 0, 0,
1272 process_free, NULL,
1273 &g_array_index(hooks, LttvTraceHook, hn++));
1274 if(ret) hn--;
1275
1276 ret = lttv_trace_find_hook(ts->parent.parent.t,
1277 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_ENTRY,
1278 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1279 after_function_entry, NULL,
1280 &g_array_index(hooks, LttvTraceHook, hn++));
1281 if(ret) hn--;
1282
1283 ret = lttv_trace_find_hook(ts->parent.parent.t,
1284 LTT_FACILITY_USER_GENERIC, LTT_EVENT_FUNCTION_EXIT,
1285 LTT_FIELD_THIS_FN, LTT_FIELD_CALL_SITE, 0,
1286 after_function_exit, NULL,
1287 &g_array_index(hooks, LttvTraceHook, hn++));
1288 if(ret) hn--;
1289
1290 /* statedump-related hooks */
1291 ret = lttv_trace_find_hook(ts->parent.parent.t,
1292 LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
1293 LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
1294 after_enum_process_state, NULL,
1295 &g_array_index(hooks, LttvTraceHook, hn++));
1296 if(ret) hn--;
1297
1298
1299 /* xenoltt-related hooks */
1300 ret = lttv_trace_find_hook(ts->parent.parent.t,
1301 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_INIT,
1302 LTT_FIELD_XENOLTT_NAME, 0, 0,
1303 xenoltt_thread_init, NULL,
1304 &g_array_index(hooks, LttvTraceHook, hn++));
1305 if(ret) hn--;
1306
1307 ret = lttv_trace_find_hook(ts->parent.parent.t,
1308 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SET_PERIOD,
1309 0, 0, 0,
1310 xenoltt_thread_set_period, NULL,
1311 &g_array_index(hooks, LttvTraceHook, hn++));
1312 if(ret) hn--;
1313
1314 ret = lttv_trace_find_hook(ts->parent.parent.t,
1315 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_RENICE,
1316 0, 0, 0,
1317 xenoltt_thread_renice, NULL,
1318 &g_array_index(hooks, LttvTraceHook, hn++));
1319 if(ret) hn--;
1320
1321 ret = lttv_trace_find_hook(ts->parent.parent.t,
1322 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_MISSED_PERIOD,
1323 LTT_FIELD_XENOLTT_NAME, LTT_FIELD_XENOLTT_ADDRESS, LTT_FIELD_XENOLTT_OVERRUNS,
1324 xenoltt_thread_overruns, NULL,
1325 &g_array_index(hooks, LttvTraceHook, hn++));
1326 if(ret) hn--;
1327
1328 ret = lttv_trace_find_hook(ts->parent.parent.t,
1329 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_SET_OWNER,
1330 LTT_FIELD_XENOLTT_SYNCH, 0, 0,
1331 xenoltt_synch_owner, NULL,
1332 &g_array_index(hooks, LttvTraceHook, hn++));
1333 if(ret) hn--;
1334
1335 ret = lttv_trace_find_hook(ts->parent.parent.t,
1336 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_WAKEUPX,
1337 LTT_FIELD_XENOLTT_SYNCH, LTT_FIELD_XENOLTT_NAME, LTT_FIELD_XENOLTT_ADDRESS,
1338 xenoltt_synch_wakeup, NULL,
1339 &g_array_index(hooks, LttvTraceHook, hn++));
1340 if(ret) hn--;
1341
1342 ret = lttv_trace_find_hook(ts->parent.parent.t,
1343 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_WAKEUP1,
1344 LTT_FIELD_XENOLTT_SYNCH, LTT_FIELD_XENOLTT_NAME, LTT_FIELD_XENOLTT_ADDRESS,
1345 xenoltt_synch_wakeup, NULL,
1346 &g_array_index(hooks, LttvTraceHook, hn++));
1347 if(ret) hn--;
1348
1349 ret = lttv_trace_find_hook(ts->parent.parent.t,
1350 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_SLEEP_ON,
1351 LTT_FIELD_XENOLTT_SYNCH, LTT_FIELD_XENOLTT_NAME, LTT_FIELD_XENOLTT_ADDRESS,
1352 xenoltt_synch_wait, NULL,
1353 &g_array_index(hooks, LttvTraceHook, hn++));
1354 if(ret) hn--;
1355
1356 //SYNCH FLUSH
1357 ret = lttv_trace_find_hook(ts->parent.parent.t,
1358 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_FLUSH,
1359 LTT_FIELD_XENOLTT_SYNCH, 0, 0,
1360 xenoltt_synch_flush, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1361 if(ret) hn--;
1362
1363 //SYNCH FORGET
1364 ret = lttv_trace_find_hook(ts->parent.parent.t,
1365 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_SYNCH_FORGET,
1366 LTT_FIELD_XENOLTT_SYNCH, LTT_FIELD_XENOLTT_NAME, LTT_FIELD_XENOLTT_ADDRESS,
1367 xenoltt_synch_wakeup, NULL, &g_array_index(hooks, LttvTraceHook, hn++));
1368 if(ret) hn--;
1369
1370 ret = lttv_trace_find_hook(ts->parent.parent.t,
1371 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_START,
1372 0, 0, 0,
1373 xenoltt_after_change_state, NULL,
1374 &g_array_index(hooks, LttvTraceHook, hn++));
1375 if(ret) hn--;
1376
1377 ret = lttv_trace_find_hook(ts->parent.parent.t,
1378 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_RESUME,
1379 0, 0, 0,
1380 xenoltt_after_change_state, NULL,
1381 &g_array_index(hooks, LttvTraceHook, hn++));
1382 if(ret) hn--;
1383
1384 ret = lttv_trace_find_hook(ts->parent.parent.t,
1385 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_WAIT_PERIOD,
1386 0, 0, 0,
1387 xenoltt_after_change_state, NULL,
1388 &g_array_index(hooks, LttvTraceHook, hn++));
1389 if(ret) hn--;
1390
1391 ret = lttv_trace_find_hook(ts->parent.parent.t,
1392 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SUSPEND,
1393 0, 0, 0,
1394 xenoltt_after_change_state, NULL,
1395 &g_array_index(hooks, LttvTraceHook, hn++));
1396 if(ret) hn--;
1397
1398 ret = lttv_trace_find_hook(ts->parent.parent.t,
1399 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SWITCH,
1400 0, 0, 0,
1401 xenoltt_after_change_state, NULL,
1402 &g_array_index(hooks, LttvTraceHook, hn++));
1403 if(ret) hn--;
1404
1405 g_array_set_size(hooks, hn);
1406
1407 after_hooks = hooks;
1408
1409 /* Add these hooks to each event_by_id hooks list */
1410
1411 nb_tracefile = ts->parent.parent.tracefiles->len;
1412
1413 for(j = 0 ; j < nb_tracefile ; j++) {
1414 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1415 LttvTracefileContext*, j));
1416 lttv_hooks_add(tfs->parent.parent.event, every_event, NULL,
1417 LTTV_PRIO_DEFAULT);
1418
1419 for(k = 0 ; k < before_hooks->len ; k++) {
1420 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1421 for(l = 0; l<hook->fac_list->len;l++) {
1422 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1423 lttv_hooks_add(
1424 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1425 thf->h,
1426 thf,
1427 LTTV_PRIO_STATS_BEFORE_STATE);
1428 }
1429 }
1430 for(k = 0 ; k < after_hooks->len ; k++) {
1431 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1432 for(l = 0; l<hook->fac_list->len;l++) {
1433 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1434 lttv_hooks_add(
1435 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1436 thf->h,
1437 thf,
1438 LTTV_PRIO_STATS_AFTER_STATE);
1439 }
1440 }
1441 }
1442 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1443 LTTV_POINTER, &val);
1444 *(val.v_pointer) = before_hooks;
1445 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1446 LTTV_POINTER, &val);
1447 *(val.v_pointer) = after_hooks;
1448 }
1449 }
1450
1451 // Hook wrapper. call_data is a traceset context.
1452 gboolean lttv_stats_hook_remove_event_hooks(void *hook_data, void *call_data)
1453 {
1454 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
1455
1456 lttv_stats_remove_event_hooks(tss);
1457
1458 return 0;
1459 }
1460
1461 void lttv_stats_remove_event_hooks(LttvTracesetStats *self)
1462 {
1463 LttvTraceset *traceset = self->parent.parent.ts;
1464
1465 guint i, j, k, l, nb_trace, nb_tracefile;
1466
1467 LttvTraceStats *ts;
1468
1469 LttvTracefileStats *tfs;
1470
1471 GArray *before_hooks, *after_hooks;
1472
1473 LttvTraceHook *hook;
1474
1475 LttvTraceHookByFacility *thf;
1476
1477 LttvAttributeValue val;
1478
1479 nb_trace = lttv_traceset_number(traceset);
1480 for(i = 0 ; i < nb_trace ; i++) {
1481 ts = (LttvTraceStats*)self->parent.parent.traces[i];
1482 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
1483 LTTV_POINTER, &val);
1484 before_hooks = *(val.v_pointer);
1485 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
1486 LTTV_POINTER, &val);
1487 after_hooks = *(val.v_pointer);
1488
1489 /* Remove these hooks from each event_by_id hooks list */
1490
1491 nb_tracefile = ts->parent.parent.tracefiles->len;
1492
1493 for(j = 0 ; j < nb_tracefile ; j++) {
1494 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
1495 LttvTracefileContext*, j));
1496 lttv_hooks_remove_data(tfs->parent.parent.event, every_event,
1497 NULL);
1498
1499 for(k = 0 ; k < before_hooks->len ; k++) {
1500 hook = &g_array_index(before_hooks, LttvTraceHook, k);
1501 for(l = 0 ; l < hook->fac_list->len ; l++) {
1502 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1503 lttv_hooks_remove_data(
1504 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1505 thf->h,
1506 thf);
1507 }
1508 }
1509 for(k = 0 ; k < after_hooks->len ; k++) {
1510 hook = &g_array_index(after_hooks, LttvTraceHook, k);
1511 for(l = 0 ; l < hook->fac_list->len ; l++) {
1512 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
1513 lttv_hooks_remove_data(
1514 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
1515 thf->h,
1516 thf);
1517 }
1518 }
1519 }
1520 g_debug("lttv_stats_remove_event_hooks()");
1521 g_array_free(before_hooks, TRUE);
1522 g_array_free(after_hooks, TRUE);
1523 }
1524 }
1525
1526
1527
1528 /****************************************************************************************************************************/
1529
1530 void lttv_xeno_stats_sum_trace(LttvTraceStats *self, LttvAttribute *ts_stats){
1531 LttvAttribute *sum_container = self->xenoltt_stats;
1532 LttvAttributeValue value;
1533 int trace_is_summed;
1534 int nb_threads;
1535
1536 LttvAttribute *main_tree, *threads_tree;
1537
1538 main_tree = sum_container;
1539
1540 lttv_attribute_find(sum_container,LTTV_STATS_SUMMED, LTTV_UINT, &value);
1541 trace_is_summed = *(value.v_uint);
1542 *(value.v_uint) = 1;
1543
1544 /* First cleanup the state : sum all stalled information (never ending
1545 * states). */
1546 if(!trace_is_summed) lttv_stats_cleanup_state(self);
1547
1548 // First level of Xenomai Tasks Statistics Tree
1549 threads_tree = lttv_attribute_find_subdir(main_tree, LTTV_XENO_STATS);
1550 nb_threads = lttv_attribute_get_number(threads_tree);
1551
1552 }
1553
1554
1555 void lttv_xeno_stats_sum_traceset(LttvTracesetStats *self){
1556 LttvTraceset *traceset = self->parent.parent.ts;
1557 LttvAttribute *sum_container = self->xenoltt_stats;
1558
1559 LttvTraceStats *tcs;
1560
1561 int i, nb_trace;
1562
1563 LttvAttributeValue value;
1564
1565 lttv_attribute_find(sum_container, LTTV_STATS_SUMMED,
1566 LTTV_UINT, &value);
1567 if(*(value.v_uint) != 0) return;
1568 *(value.v_uint) = 1;
1569
1570 nb_trace = lttv_traceset_number(traceset);
1571
1572 for(i = 0 ; i < nb_trace ; i++) {
1573 tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
1574 lttv_xeno_stats_sum_trace(tcs, self->xenoltt_stats);
1575 }
1576 }
1577
1578
1579 /****************************************************************************
1580 - Task Name ( Address, Priority, Period )
1581 - Periods
1582 * Running Avg, Max, Min
1583 * Suspend Avg, Max, Min
1584 * Ready Avg, Max, Min
1585 - Overruns
1586 - # ( ticks missed, time )
1587 - Status
1588 - Status name (#, total time, avg)
1589 - Ressources
1590 - Name
1591 - Possession (#, time, avg)
1592 - Waiting (#, time, avg)
1593 - Events
1594 - Ressources
1595 - Address
1596 - Possession (#, time, avg)
1597 - Waiting (#, time, avg)
1598 *****************************************************************************/
1599
1600 static void xeno_find_task_tree(LttvTracefileStats *tfcs, GQuark name, gulong address, guint cpu, LttvAttribute **events_tree, LttvAttribute **event_types_tree){
1601 LttvAttribute *a, *task_tree, *xenoltt_tree, *state_tree, *synch_tree;
1602
1603 LttvAttributeValue prio, period;
1604
1605 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
1606 xenoltt_tree = lttv_attribute_find_subdir(tcs->xenoltt_stats, LTTV_XENO_STATS);
1607
1608 task_tree = lttv_attribute_find_subdir(xenoltt_tree, LTTV_XENO_STATS_THREADS);
1609 task_tree = lttv_attribute_find_subdir(task_tree, name);
1610 *events_tree = task_tree;
1611 lttv_attribute_find_subdir(xenoltt_tree, LTTV_XENO_STATS_SYNCH);
1612
1613 lttv_attribute_find(task_tree, LTTV_XENO_STATS_THREAD_PERIOD, LTTV_UINT, &period);
1614 lttv_attribute_find(task_tree, LTTV_XENO_STATS_THREAD_PRIO, LTTV_UINT, &prio);
1615
1616 lttv_attribute_find_subdir(task_tree, LTTV_XENO_STATS_SYNCH);
1617
1618 lttv_attribute_find_subdir(task_tree, LTTV_XENO_STATS_PERIOD_OVERRUNS);
1619
1620
1621 state_tree = lttv_attribute_find_subdir(task_tree, LTTV_XENO_STATS_STATE);
1622
1623 synch_tree = lttv_attribute_find_subdir(task_tree, LTTV_XENO_STATS_SYNCH);
1624
1625 a = lttv_attribute_find_subdir(task_tree, LTTV_STATS_EVENT_TYPES);
1626 *event_types_tree = a;
1627
1628 }
1629
1630 gboolean xenoltt_thread_init(void *hook_data, void *call_data){
1631 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1632 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1633 LttvXenoThreadState *thread;
1634 LttvAttributeValue prio;
1635 guint cpu = tfcs->parent.cpu;
1636 thread = ts->running_thread[cpu];
1637
1638 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1639
1640 lttv_attribute_find(tfcs->current_events_tree, LTTV_XENO_STATS_THREAD_PRIO, LTTV_UINT, &prio);
1641 *(prio.v_uint) = thread->prio;
1642
1643 xenoltt_after_change_state(hook_data,call_data);
1644
1645 return FALSE;
1646 }
1647
1648 gboolean xenoltt_thread_renice(void *hook_data, void *call_data){
1649 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1650 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1651 LttvXenoThreadState *thread;
1652 LttvAttributeValue prio;
1653 guint cpu = tfcs->parent.cpu;
1654 thread = ts->running_thread[cpu];
1655
1656 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1657
1658 lttv_attribute_find(tfcs->current_events_tree, LTTV_XENO_STATS_THREAD_PRIO, LTTV_UINT, &prio);
1659 *(prio.v_uint) = thread->prio;
1660
1661 return FALSE;
1662 }
1663
1664 gboolean xenoltt_thread_set_period(void *hook_data, void *call_data){
1665 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1666 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1667 LttvXenoThreadState *thread;
1668 LttvAttributeValue period;
1669 guint cpu = tfcs->parent.cpu;
1670 thread = ts->running_thread[cpu];
1671
1672 // Find corresponding task
1673 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1674
1675 // Write the period of the task
1676 lttv_attribute_find(tfcs->current_events_tree, LTTV_XENO_STATS_THREAD_PERIOD, LTTV_UINT, &period);
1677 *(period.v_uint) = thread->period;
1678
1679 return FALSE;
1680 }
1681
1682 gboolean xenoltt_thread_overruns(void *hook_data, void *call_data){
1683 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1684 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1685 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
1686 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1687 LttvAttributeValue overrun;
1688 LttvAttribute *overrun_tree;
1689 guint cpu = tfcs->parent.cpu;
1690
1691 g_assert(thf->f1 != NULL);
1692 GQuark name = g_quark_from_string(ltt_event_get_string(e, thf->f1));
1693 g_assert(thf->f2 != NULL);
1694 gulong address = ltt_event_get_long_unsigned(e, thf->f2);
1695 g_assert(thf->f3 != NULL);
1696 guint overruns = ltt_event_get_long_unsigned(e, thf->f3);
1697 LttvXenoThreadState *thread = lttv_xeno_state_find_thread(ts,cpu,address);
1698 xeno_find_task_tree(tfcs, name, address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1699
1700 overrun_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_PERIOD_OVERRUNS);
1701
1702 gchar overrun_time[MAX_64_HEX_STRING_LEN];
1703 sprintf(overrun_time,"%lu,%lu", tfcs->parent.parent.timestamp.tv_sec,tfcs->parent.parent.timestamp.tv_nsec);
1704 overrun_tree = lttv_attribute_find_subdir(overrun_tree, g_quark_from_string(overrun_time));
1705
1706 lttv_attribute_find(overrun_tree, LTTV_XENO_STATS_TEXT_TICKS, LTTV_UINT, &overrun);
1707 *(overrun.v_uint) = overruns;
1708
1709 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, thread->state->overrun_start);
1710 lttv_attribute_find(overrun_tree, LTTV_XENO_STATS_TEXT_TOTAL, LTTV_TIME, &overrun);
1711 *(overrun.v_time) = delta;
1712 return FALSE;
1713 }
1714
1715 gboolean xenoltt_before_change_state(void *hook_data, void *call_data){
1716 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1717 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1718 LttvXenoThreadState *thread;
1719 LttvAttributeValue state_count, state_time, state_time_average;
1720 LttvAttribute *a;
1721 guint cpu = tfcs->parent.cpu;
1722 thread = ts->running_thread[cpu];
1723
1724 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1725
1726 // Create or go to State subtree
1727 a = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_STATE);
1728 // Create or go to the current state subtree
1729 a = lttv_attribute_find_subdir(a, thread->state->status);
1730 lttv_attribute_find(a, g_quark_from_string("Number of times in this state"), LTTV_UINT, &state_count);
1731
1732 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, thread->state->change);
1733 lttv_attribute_find(a, g_quark_from_string("Cumulative time"), LTTV_TIME, &state_time);
1734 *(state_time.v_time) = ltt_time_add(*(state_time.v_time), delta);
1735
1736 lttv_attribute_find(a, g_quark_from_string("Average elapsed time"), LTTV_TIME, &state_time_average);
1737 if (*(state_count.v_uint) == 0 || ltt_time_compare(*(state_time.v_time),ltt_time_zero) == 0) *(state_time_average.v_time) = *(state_time.v_time);
1738 else *(state_time_average.v_time) = ltt_time_div(*(state_time.v_time), *(state_count.v_uint));
1739
1740 return FALSE;
1741 }
1742
1743 gboolean xenoltt_after_change_state(void *hook_data, void *call_data){
1744 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1745 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1746 LttvXenoThreadState *thread;
1747 LttvAttributeValue state_count, state_time, state_time_average;
1748 LttvAttribute *a;
1749 guint cpu = tfcs->parent.cpu;
1750 thread = ts->running_thread[cpu];
1751
1752 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1753
1754 // Create or go to State subtree
1755 a = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_STATE);
1756 // Create or go to the current state subtree
1757 a = lttv_attribute_find_subdir(a, thread->state->status);
1758 lttv_attribute_find(a, g_quark_from_string("Number of times in this state"), LTTV_UINT, &state_count);
1759 *(state_count.v_uint) = *(state_count.v_uint) + 1;
1760
1761 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, thread->state->entry);
1762 lttv_attribute_find(a, g_quark_from_string("Cumulative time"), LTTV_TIME, &state_time);
1763 *(state_time.v_time) = ltt_time_add(*(state_time.v_time), delta);
1764
1765 lttv_attribute_find(a, g_quark_from_string("Average elapsed time"), LTTV_TIME, &state_time_average);
1766 if (*(state_count.v_uint) == 0 || ltt_time_compare(*(state_time.v_time),ltt_time_zero) == 0) *(state_time_average.v_time) = *(state_time.v_time);
1767 else *(state_time_average.v_time) = ltt_time_div(*(state_time.v_time), *(state_count.v_uint));
1768
1769
1770 return FALSE;
1771 }
1772
1773 gboolean xenoltt_synch_owner(void *hook_data, void *call_data){
1774 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1775 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1776 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
1777 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
1778 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1779 LttvAttributeValue synch;
1780 LttvAttribute *synch_tree, *global_synch_tree;
1781 guint cpu = tfcs->parent.cpu;
1782 LttvXenoThreadState *thread = ts->running_thread[cpu];
1783
1784 if (thread->state->started == TRUE){
1785 g_assert(thf->f1 != NULL);
1786 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f1);
1787
1788 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1789
1790 synch_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_SYNCH);
1791
1792 // Update the task ressources tree
1793 gchar synch_id[MAX_64_HEX_STRING_LEN];
1794 sprintf(synch_id,"%p", (void *) synch_address);
1795 synch_tree = lttv_attribute_find_subdir(synch_tree, g_quark_from_string(synch_id));
1796
1797 // We must update the global ressources tree also
1798 global_synch_tree = lttv_attribute_find_subdir(tcs->xenoltt_stats, LTTV_XENO_STATS);
1799 global_synch_tree = lttv_attribute_find_subdir(global_synch_tree, LTTV_XENO_STATS_SYNCH);
1800 global_synch_tree = lttv_attribute_find_subdir(global_synch_tree, g_quark_from_string(synch_id));
1801
1802 // In the task tree
1803 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
1804 *(synch.v_uint) += 1;
1805
1806 // In the global tree
1807 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
1808 *(synch.v_uint) += 1;
1809 }
1810 return FALSE;
1811 }
1812
1813 // When sleep-on is called
1814 gboolean xenoltt_synch_wait(void *hook_data, void *call_data){
1815 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1816 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1817 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
1818 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
1819 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1820 LttvAttributeValue synch;
1821 LttvAttribute *synch_tree, *global_synch_tree;
1822 guint cpu = tfcs->parent.cpu;
1823 LttvXenoThreadState *thread;
1824 thread = ts->running_thread[cpu];
1825
1826 g_assert(thf->f1 != NULL);
1827 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f1);
1828 g_assert(thf->f2 != NULL);
1829 GQuark name = g_quark_from_string(ltt_event_get_string(e, thf->f2));
1830 g_assert(thf->f3 != NULL);
1831 gulong address = ltt_event_get_long_unsigned(e, thf->f3);
1832
1833 xeno_find_task_tree(tfcs, name, address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1834
1835 synch_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_SYNCH);
1836
1837 gchar synch_id[MAX_64_HEX_STRING_LEN];
1838 sprintf(synch_id,"%p", (void *) synch_address);
1839 synch_tree = lttv_attribute_find_subdir(synch_tree, g_quark_from_string(synch_id));
1840
1841 // We must update the global ressources tree also
1842 global_synch_tree = lttv_attribute_find_subdir(tcs->xenoltt_stats, LTTV_XENO_STATS);
1843 global_synch_tree = lttv_attribute_find_subdir(global_synch_tree, LTTV_XENO_STATS_SYNCH);
1844 global_synch_tree = lttv_attribute_find_subdir(global_synch_tree, g_quark_from_string(synch_id));
1845
1846 // We have one more waiting call to register
1847 // In the task tree
1848 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING, LTTV_UINT, &synch);
1849 *(synch.v_uint) = *(synch.v_uint) + 1;
1850
1851 // In the global tree
1852 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING, LTTV_UINT, &synch);
1853 *(synch.v_uint) = *(synch.v_uint) + 1;
1854
1855 return FALSE;
1856 }
1857
1858 gboolean xenoltt_synch_wakeup(void *hook_data, void *call_data){
1859 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1860 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1861 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
1862 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
1863 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1864 LttvAttributeValue synch, total_time, avg_time, max_time, min_time;
1865 LttvAttributeValue global_synch, global_total_time, global_avg_time, global_max_time, global_min_time;
1866 LttvAttribute *synch_tree, *global_synch_tree;
1867 guint cpu = tfcs->parent.cpu;
1868 GQuark event_name = ltt_eventtype_name(ltt_event_eventtype(e));
1869
1870 g_assert(thf->f1 != NULL);
1871 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f1);
1872 g_assert(thf->f2 != NULL);
1873 GQuark name = g_quark_from_string(ltt_event_get_string(e, thf->f2));
1874 g_assert(thf->f3 != NULL);
1875 gulong address = ltt_event_get_long_unsigned(e, thf->f3);
1876 LttvXenoSynchState *synch_state = lttv_xeno_state_find_synch(ts,synch_address);
1877 LttvXenoThreadState *thread = lttv_xeno_state_find_thread(ts,cpu,address);
1878 if (synch_state != NULL && thread != NULL ){
1879 xeno_find_task_tree(tfcs, name, address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1880
1881 synch_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_SYNCH);
1882
1883 gchar synch_id[MAX_64_HEX_STRING_LEN];
1884 sprintf(synch_id,"%p", (void *) synch_address);
1885 synch_tree = lttv_attribute_find_subdir(synch_tree, g_quark_from_string(synch_id));
1886
1887 // We must update the global ressources tree also
1888 global_synch_tree = lttv_attribute_find_subdir(tcs->xenoltt_stats, LTTV_XENO_STATS);
1889 global_synch_tree = lttv_attribute_find_subdir(global_synch_tree, LTTV_XENO_STATS_SYNCH);
1890 global_synch_tree = lttv_attribute_find_subdir(global_synch_tree, g_quark_from_string(synch_id));
1891
1892 if (event_name != LTT_EVENT_XENOLTT_SYNCH_FORGET){
1893 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
1894 *(synch.v_uint) = *(synch.v_uint) + 1;
1895
1896 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
1897 *(synch.v_uint) = *(synch.v_uint) + 1;
1898 }
1899
1900 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING, LTTV_UINT, &synch);
1901
1902 // Compute time spent in waiting state
1903 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, thread->start_wait_synch);
1904
1905 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_TOTAL, LTTV_TIME, &total_time);
1906 *(total_time.v_time) = ltt_time_add(*(total_time.v_time), delta);
1907
1908 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_AVG, LTTV_TIME, &avg_time);
1909 if (*(synch.v_uint) == 0 || ltt_time_compare(*(total_time.v_time),ltt_time_zero) == 0) *(avg_time.v_time) = *(total_time.v_time);
1910 else *(avg_time.v_time) = ltt_time_div(*(total_time.v_time), *(synch.v_uint));
1911
1912 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MAX, LTTV_TIME, &max_time);
1913 // If this owning time is longer than any other before
1914 if (ltt_time_compare(delta,*(max_time.v_time)) == 1) *(max_time.v_time) = delta;
1915
1916 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MIN, LTTV_TIME, &min_time);
1917 // If this owning time is shorter than any other before
1918 if (*(synch.v_uint) == 1) *(min_time.v_time) = delta;
1919 else if (ltt_time_compare(*(min_time.v_time), delta) == 1) *(min_time.v_time) = delta;
1920
1921 /**** GLOBAL RESOURCE TREE ***********/
1922 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING, LTTV_UINT, &global_synch);
1923
1924 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING_TOTAL, LTTV_TIME, &global_total_time);
1925 *(global_total_time.v_time) = ltt_time_add(*(global_total_time.v_time), delta);
1926
1927 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING_AVG, LTTV_TIME, &global_avg_time);
1928 if (*(global_synch.v_uint) == 0 || ltt_time_compare(*(global_total_time.v_time),ltt_time_zero) == 0) *(global_avg_time.v_time) = *(global_total_time.v_time);
1929 else *(global_avg_time.v_time) = ltt_time_div(*(global_total_time.v_time), *(global_synch.v_uint));
1930
1931 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MAX, LTTV_TIME, &global_max_time);
1932 // If this owning time is longer than any other before
1933 if (ltt_time_compare(delta,*(global_max_time.v_time)) == 1) *(global_max_time.v_time) = delta;
1934
1935 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MIN, LTTV_TIME, &global_min_time);
1936 // If this owning time is shorter than any other before
1937 if (*(global_synch.v_uint) == 1) *(global_min_time.v_time) = delta;
1938 else if (ltt_time_compare(*(global_min_time.v_time), delta) == 1) *(global_min_time.v_time) = delta;
1939 }
1940 return FALSE;
1941 }
1942
1943 gboolean xenoltt_synch_flush(void *hook_data, void *call_data){
1944 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
1945 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
1946 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
1947 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
1948 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
1949 LttvAttributeValue synch, total_time, avg_time, max_time, min_time;
1950 LttvAttributeValue global_synch, global_total_time, global_avg_time, global_max_time, global_min_time;
1951 LttvAttribute *synch_tree, *global_synch_tree;
1952 guint cpu = tfcs->parent.cpu;
1953 GQuark event_name = ltt_eventtype_name(ltt_event_eventtype(e));
1954
1955 g_assert(thf->f1 != NULL);
1956 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f1);
1957
1958 LttvXenoSynchState *synch_state = lttv_xeno_state_find_synch(ts,synch_address);
1959 LttvXenoThreadState *thread;
1960 if (synch_state != NULL){
1961 int i;
1962 for(i=0;i<synch_state->state->waiting_threads->len;i++){
1963 thread = g_array_index(synch_state->state->waiting_threads, LttvXenoThreadState*, i);
1964 if (thread != NULL){
1965 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
1966
1967 synch_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_SYNCH);
1968
1969 gchar synch_id[MAX_64_HEX_STRING_LEN];
1970 sprintf(synch_id,"%p", (void *) synch_address);
1971 synch_tree = lttv_attribute_find_subdir(synch_tree, g_quark_from_string(synch_id));
1972
1973 // We must update the global ressources tree also
1974 global_synch_tree = lttv_attribute_find_subdir(tcs->xenoltt_stats, LTTV_XENO_STATS);
1975 global_synch_tree = lttv_attribute_find_subdir(global_synch_tree, LTTV_XENO_STATS_SYNCH);
1976 global_synch_tree = lttv_attribute_find_subdir(global_synch_tree, g_quark_from_string(synch_id));
1977
1978 if (event_name != LTT_EVENT_XENOLTT_SYNCH_FORGET){
1979 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
1980 *(synch.v_uint) = *(synch.v_uint) + 1;
1981
1982 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
1983 *(synch.v_uint) = *(synch.v_uint) + 1;
1984 }
1985
1986 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING, LTTV_UINT, &synch);
1987
1988 // Compute time spent in waiting state
1989 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, thread->start_wait_synch);
1990
1991 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_TOTAL, LTTV_TIME, &total_time);
1992 *(total_time.v_time) = ltt_time_add(*(total_time.v_time), delta);
1993
1994 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_AVG, LTTV_TIME, &avg_time);
1995 if (*(synch.v_uint) == 0 || ltt_time_compare(*(total_time.v_time),ltt_time_zero) == 0) *(avg_time.v_time) = *(total_time.v_time);
1996 else *(avg_time.v_time) = ltt_time_div(*(total_time.v_time), *(synch.v_uint));
1997
1998 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MAX, LTTV_TIME, &max_time);
1999 // If this owning time is longer than any other before
2000 if (ltt_time_compare(delta,*(max_time.v_time)) == 1) *(max_time.v_time) = delta;
2001
2002 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MIN, LTTV_TIME, &min_time);
2003 // If this owning time is shorter than any other before
2004 if (*(synch.v_uint) == 1) *(min_time.v_time) = delta;
2005 else if (ltt_time_compare(*(min_time.v_time), delta) == 1) *(min_time.v_time) = delta;
2006
2007 /**** GLOBAL RESOURCE TREE ***********/
2008 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING, LTTV_UINT, &global_synch);
2009
2010 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING_TOTAL, LTTV_TIME, &global_total_time);
2011 *(global_total_time.v_time) = ltt_time_add(*(global_total_time.v_time), delta);
2012
2013 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING_AVG, LTTV_TIME, &global_avg_time);
2014 if (*(global_synch.v_uint) == 0 || ltt_time_compare(*(global_total_time.v_time),ltt_time_zero) == 0) *(global_avg_time.v_time) = *(global_total_time.v_time);
2015 else *(global_avg_time.v_time) = ltt_time_div(*(global_total_time.v_time), *(global_synch.v_uint));
2016
2017 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MAX, LTTV_TIME, &global_max_time);
2018 // If this owning time is longer than any other before
2019 if (ltt_time_compare(delta,*(global_max_time.v_time)) == 1) *(global_max_time.v_time) = delta;
2020
2021 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_WAITING_MIN, LTTV_TIME, &global_min_time);
2022 // If this owning time is shorter than any other before
2023 if (*(global_synch.v_uint) == 1) *(global_min_time.v_time) = delta;
2024 else if (ltt_time_compare(*(global_min_time.v_time), delta) == 1) *(global_min_time.v_time) = delta;
2025 }
2026 }
2027 }
2028 return FALSE;
2029 }
2030
2031 gboolean xenoltt_synch_unblock(void *hook_data, void *call_data){
2032 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
2033 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
2034 LttvTraceStats *tcs = (LttvTraceStats*)tfcs->parent.parent.t_context;
2035 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
2036 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
2037 LttvAttributeValue synch, total_time, avg_time, max_time, min_time;
2038 LttvAttributeValue global_synch, global_total_time, global_avg_time, global_max_time, global_min_time;
2039 LttvAttribute *synch_tree, *global_synch_tree;
2040 guint cpu = tfcs->parent.cpu;
2041 LttvXenoThreadState *thread = ts->running_thread[cpu];
2042
2043 g_assert(thf->f1 != NULL);
2044 gulong synch_address = ltt_event_get_long_unsigned(e, thf->f1);
2045 LttvXenoSynchState *synch_state = lttv_xeno_state_find_synch(ts,synch_address);
2046 if (synch_state != NULL){
2047
2048 xeno_find_task_tree(tfcs, thread->name, thread->address,cpu, &(tfcs->current_events_tree), &(tfcs->current_event_types_tree));
2049
2050 synch_tree = lttv_attribute_find_subdir(tfcs->current_events_tree, LTTV_XENO_STATS_SYNCH);
2051
2052 gchar synch_id[MAX_64_HEX_STRING_LEN];
2053 sprintf(synch_id,"%p", (void *) synch_address);
2054 synch_tree = lttv_attribute_find_subdir(synch_tree, g_quark_from_string(synch_id));
2055
2056 // We must update the global ressources tree also
2057 global_synch_tree = lttv_attribute_find_subdir(tcs->xenoltt_stats, LTTV_XENO_STATS);
2058 global_synch_tree = lttv_attribute_find_subdir(global_synch_tree, LTTV_XENO_STATS_SYNCH);
2059 global_synch_tree = lttv_attribute_find_subdir(global_synch_tree, g_quark_from_string(synch_id));
2060
2061 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &synch);
2062
2063 // Compute time spent in possession of the ressource
2064 LttTime delta = ltt_time_sub(tfcs->parent.parent.timestamp, synch_state->state->start_time);
2065
2066 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER_TOTAL, LTTV_TIME, &total_time);
2067 *(total_time.v_time) = ltt_time_add(*(total_time.v_time), delta);
2068
2069 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER_AVG, LTTV_TIME, &avg_time);
2070 if (*(synch.v_uint) == 0 || ltt_time_compare(*(total_time.v_time),ltt_time_zero) == 0) *(avg_time.v_time) = *(total_time.v_time);
2071 else *(avg_time.v_time) = ltt_time_div(*(total_time.v_time), *(synch.v_uint));
2072
2073 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER_MAX, LTTV_TIME, &max_time);
2074 // If this owning time is longer than any other before
2075 if (ltt_time_compare(delta,*(max_time.v_time)) == 1) *(max_time.v_time) = delta;
2076
2077 lttv_attribute_find(synch_tree, LTTV_XENO_STATS_TEXT_OWNER_MIN, LTTV_TIME, &min_time);
2078 // If this owning time is shorter than any other before
2079 if (*(synch.v_uint) == 1) *(min_time.v_time) = delta;
2080 else if (ltt_time_compare(*(min_time.v_time), delta) == 1) *(min_time.v_time) = delta;
2081
2082 /**** GLOBAL RESOURCE TREE ***********/
2083 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_OWNER, LTTV_UINT, &global_synch);
2084
2085 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_OWNER_TOTAL, LTTV_TIME, &global_total_time);
2086 *(global_total_time.v_time) = ltt_time_add(*(global_total_time.v_time), delta);
2087
2088 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_OWNER_AVG, LTTV_TIME, &global_avg_time);
2089 if (*(global_synch.v_uint) == 0 || ltt_time_compare(*(global_total_time.v_time),ltt_time_zero) == 0) *(global_avg_time.v_time) = *(global_total_time.v_time);
2090 else *(global_avg_time.v_time) = ltt_time_div(*(global_total_time.v_time), *(global_synch.v_uint));
2091
2092 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_OWNER_MAX, LTTV_TIME, &global_max_time);
2093 // If this owning time is longer than any other before
2094 if (ltt_time_compare(delta,*(global_max_time.v_time)) == 1) *(global_max_time.v_time) = delta;
2095
2096 lttv_attribute_find(global_synch_tree, LTTV_XENO_STATS_TEXT_OWNER_MIN, LTTV_TIME, &global_min_time);
2097 // If this owning time is shorter than any other before
2098 if (*(global_synch.v_uint) == 1) *(global_min_time.v_time) = delta;
2099 else if (ltt_time_compare(*(global_min_time.v_time), delta) == 1) *(global_min_time.v_time) = delta;
2100
2101
2102 }
2103 return FALSE;
2104
2105 }
2106
2107 /****************************************************************************************************************************/
2108
2109
2110
2111
2112 static void module_init()
2113 {
2114 LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
2115 LTTV_STATS_PROCESSES = g_quark_from_string("processes");
2116 LTTV_STATS_CPU = g_quark_from_string("cpu");
2117 LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
2118 LTTV_STATS_MODES = g_quark_from_string("modes");
2119 LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
2120 LTTV_STATS_FUNCTIONS = g_quark_from_string("functions");
2121 LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
2122 LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
2123 LTTV_STATS_CUMULATIVE_CPU_TIME = g_quark_from_string("cumulative cpu time (includes nested routines and modes)");
2124 LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time (includes per process waiting time)");
2125 LTTV_STATS_EVENTS = g_quark_from_string("events");
2126 LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
2127 LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
2128 LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
2129 LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
2130 LTTV_STATS = g_quark_from_string("statistics");
2131 LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
2132 LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
2133 /****************************************************************************************************************************/
2134 LTTV_XENO_STATS = g_quark_from_string("Xenomai");
2135 LTTV_XENO_STATS_THREADS = g_quark_from_string("Tasks");
2136 LTTV_XENO_STATS_PERIOD = g_quark_from_string("Periods");
2137 LTTV_XENO_STATS_STATE = g_quark_from_string("Status");
2138 LTTV_XENO_STATS_SYNCH = g_quark_from_string("Resources");
2139 LTTV_XENO_STATS_THREAD_PRIO = g_quark_from_string("Priority");
2140 LTTV_XENO_STATS_THREAD_PERIOD = g_quark_from_string("Period");
2141 LTTV_XENO_STATS_PERIOD_OVERRUNS = g_quark_from_string("Overruns(s)");
2142 LTTV_XENO_STATS_TEXT_OVERRUNS = g_quark_from_string("Overrun(s)");
2143 LTTV_XENO_STATS_TEXT_TICKS = g_quark_from_string("Number of ticks");
2144 LTTV_XENO_STATS_TEXT_OWNER = g_quark_from_string("Owner");
2145 LTTV_XENO_STATS_TEXT_OWNER_TOTAL = g_quark_from_string("\tTotal time");
2146 LTTV_XENO_STATS_TEXT_OWNER_MAX = g_quark_from_string("\tMax time");
2147 LTTV_XENO_STATS_TEXT_OWNER_MIN = g_quark_from_string("\tMin time");
2148 LTTV_XENO_STATS_TEXT_OWNER_AVG = g_quark_from_string("\tAverage time");
2149 LTTV_XENO_STATS_TEXT_WAITING = g_quark_from_string("Waiting");
2150 LTTV_XENO_STATS_TEXT_WAITING_TOTAL = g_quark_from_string("\tTotal time waiting");
2151 LTTV_XENO_STATS_TEXT_WAITING_MAX = g_quark_from_string("\tMax time waiting");
2152 LTTV_XENO_STATS_TEXT_WAITING_MIN = g_quark_from_string("\tMin time waiting");
2153 LTTV_XENO_STATS_TEXT_WAITING_AVG = g_quark_from_string("\tAverage time waiting");
2154 LTTV_XENO_STATS_TEXT_TOTAL = g_quark_from_string("\tTotal time");
2155 LTTV_XENO_STATS_TEXT_READY_MAX = g_quark_from_string("\tMax time in readyq");
2156 LTTV_XENO_STATS_TEXT_READY_MIN = g_quark_from_string("\tMin time in readyq");
2157 LTTV_XENO_STATS_TEXT_READY_AVG = g_quark_from_string("\tAverage time in readyq");
2158 LTTV_XENO_STATS_TEXT_RUNNING_MAX = g_quark_from_string("\tMax time running");
2159 LTTV_XENO_STATS_TEXT_RUNNING_MIN = g_quark_from_string("\tMin time running");
2160 LTTV_XENO_STATS_TEXT_RUNNING_AVG = g_quark_from_string("\tAverage time running");
2161 LTTV_XENO_STATS_TEXT_SUSPEND_MAX = g_quark_from_string("\tMax time suspended");
2162 LTTV_XENO_STATS_TEXT_SUSPEND_MIN = g_quark_from_string("\tMin time suspended");
2163 LTTV_XENO_STATS_TEXT_SUSPEND_AVG = g_quark_from_string("\tAverage time suspended");
2164 LTTV_XENO_STATS_NB_PERIOD = g_quark_from_string("Number of periods executed");
2165 /****************************************************************************************************************************/
2166 }
2167
2168 static void module_destroy()
2169 {
2170 }
2171
2172
2173 LTTV_MODULE("stats", "Compute processes statistics", \
2174 "Accumulate statistics for event types, processes and CPUs", \
2175 module_init, module_destroy, "state");
2176
2177 /* Change the places where stats are called (create/read/write stats)
2178
2179 Check for options in batchtest.c to reduce writing and see what tests are
2180 best candidates for performance analysis. Once OK, commit, move to main
2181 and run tests. Update the gui for statistics. */
This page took 0.114439 seconds and 4 git commands to generate.