2 #include <lttv/processTrace.h>
4 void lttv_context_init(LttvTracesetContext
*self
)
6 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->init(self
);
10 void lttv_context_fini(LttvTracesetContext
*self
)
12 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->fini(self
);
17 lttv_context_new_traceset_context(LttvTracesetContext
*self
)
19 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_traceset_context(self
);
26 lttv_context_new_trace_context(LttvTracesetContext
*self
)
28 return LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_trace_context(self
);
32 LttvTracefileContext
*
33 lttv_context_new_tracefile_context(LttvTracesetContext
*self
)
35 LTTV_TRACESET_CONTEXT_GET_CLASS(self
)->new_tracefile_context(self
);
40 init(LttvTracesetContext
*self
, LttvTraceset
*ts
)
42 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
46 LttvTracefileContext
*tfc
;
48 nb_trace
= lttv_traceset_number(ts
);
50 self
->traces
= g_new((LttvTraceContext
*), nb_trace
);
51 self
->before
= lttv_hooks_new();
52 self
->after
= lttv_hooks_new();
53 self
->attributes
= g_object_new(LTTV_ATTRIBUTE_TYPE
);
54 for(i
= 0 ; i
< nb_trace
; i
++) {
55 tc
= self
->new_trace_context();
58 tc
->ts_context
= self
;
60 tc
->t
= lttv_traceset_get(ts
, i
);
61 tc
->check
= lttv_hooks_new();
62 tc
->before
= lttv_hooks_new();
63 tc
->after
= lttv_hooks_new();
64 tc
->attributes
= g_object_new(LTTV_ATTRIBUTE_TYPE
);
65 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
66 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
67 nb_tracefile
= nb_control
+ nb_per_cpu
;
68 tc
->control_tracefiles
= g_new((LttvTracefileContext
*), nb_control
);
69 tc
->per_cpu_tracefiles
= g_new((LttvTracefileContext
*), nb_per_cpu
);
71 for(j
= 0 ; j
< nb_tracefile
; j
++) {
72 tfc
= self
->new_tracefile_context();
74 tc
->control_tracefiles
[j
] = tfc
;
77 tfc
->tf
= ltt_trace_control_tracefile_get(j
);
80 tc
->per_cpu_tracefiles
[j
- nb_control
] = tfc
;
82 tfc
->index
= j
- nb_control
;
83 tfc
->tf
= ltt_trace_per_cpu_tracefile_get(j
- nb_control
);
86 tfc
->check
= lttv_hooks_new();
87 tfc
->before
= lttv_hooks_new();
88 tfc
->after
= lttv_hooks_new();
89 tfc
->check_event
= lttv_hooks_new();
90 tfc
->before_event
= lttv_hooks_new();
91 tfc
->before_event_by_id
= lttv_hooks_by_id_new();
92 tfc
->after_event
= lttv_hooks_new();
93 tfc
->after_event_by_id
= lttv_hooks_by_id_new();
94 tfc
->attributes
= g_object_new(LTTV_ATTRIBUTE_TYPE
);
100 void fini(LttvTracesetContext
*self
)
102 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
104 LttvTraceContext
*tc
;
106 LttvTracefileContext
*tfc
;
108 LttvTraceset
*ts
= tc
->ts
;
110 lttv_hooks_destroy(self
->before
);
111 lttv_hooks_destroy(self
->after
);
112 g_object_unref(self
->attributes
);
114 nb_trace
= lttv_traceset_number(ts
);
116 for(i
= 0 ; i
< nb_trace
; i
++) {
117 tc
= self
->traces
[i
];
119 lttv_hooks_destroy(tc
->check
);
120 lttv_hooks_destroy(tc
->before
);
121 lttv_hooks_destroy(tc
->after
);
122 g_object_unref(tc
->attributes
);
124 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
125 nb_per_cpu
= ltt_trace_per_cpu_tracefile_number(tc
->t
);
126 nb_tracefile
= nb_control
+ nb_per_cpu
;
128 for(j
= 0 ; j
< nb_tracefile
; j
++) {
129 if(j
< nb_control
) tfc
= tc
->control_tracefiles
[j
];
130 else tfc
= tc
->per_cpu_tracefiles
[j
- nb_control
];
132 lttv_hooks_destroy(tfc
->check
);
133 lttv_hooks_destroy(tfc
->before
);
134 lttv_hooks_destroy(tfc
->after
);
135 lttv_hooks_destroy(tfc
->check_event
);
136 lttv_hooks_destroy(tfc
->before_event
);
137 lttv_hooks_by_id_destroy(tfc
->before_event_by_id
);
138 lttv_hooks_destroy(tfc
->after_event
);
139 lttv_hooks_by_id_destroy(tfc
->after_event_by_id
);
140 g_object_unref(tfc
->attributes
);
143 g_free(tc
->control_tracefiles
);
144 g_free(tc
->per_cpu_tracefiles
);
147 g_free(self
->traces
);
151 void lttv_traceset_context_add_hooks(LttvTracesetContext
*self
,
152 LttvHooks
*before_traceset
,
153 LttvHooks
*after_traceset
,
154 LttvHooks
*check_trace
,
155 LttvHooks
*before_trace
,
156 LttvHooks
*after_trace
,
157 LttvHooks
*check_event
,
158 LttvHooks
*before_event
,
159 LttvHooks
*after_event
)
161 LttvTraceset
*ts
= self
->ts
;
163 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
165 LttvTraceContext
*tc
;
167 LttvTracefileContext
*tfc
;
171 lttv_hooks_add_list(self
->before
, before_traceset
);
172 lttv_hooks_add_list(self
->after
, after_traceset
);
173 nb_trace
= lttv_traceset_number(ts
);
175 for(i
= 0 ; i
< nb_trace
; i
++) {
176 tc
= self
->traces
[i
];
177 lttv_hooks_add_list(tc
->check
, check_trace
);
178 lttv_hooks_add_list(tc
->before
, before_trace
);
179 lttv_hooks_add_list(tc
->after
, after_trace
);
180 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
181 nb_per_cpu
= ltt_trace_control_tracefile_number(tc
->t
);
182 nb_tracefile
= nb_control
+ nb_per_cpu
;
184 for(j
= 0 ; j
< nb_tracefile
; j
++) {
186 tfc
= tc
->control_tracefiles
[j
];
189 tfc
= tc
->per_cpu_tracefiles
[j
];
191 lttv_hooks_add_list(tfc
->check
, check_tracefile
);
192 lttv_hooks_add_list(tfc
->before
, before_tracefile
);
193 lttv_hooks_add_list(tfc
->after
, after_tracefile
);
194 lttv_hooks_add_list(tfc
->check_event
, check_event
);
195 lttv_hooks_add_list(tfc
->before_event
, before_event
);
196 lttv_hooks_add_list(tfc
->after_event
, after_event
);
202 void lttv_traceset_context_remove_hooks(LttvTracesetContext
*self
,
203 LttvHooks
*before_traceset
,
204 LttvHooks
*after_traceset
,
205 LttvHooks
*check_trace
,
206 LttvHooks
*before_trace
,
207 LttvHooks
*after_trace
,
208 LttvHooks
*check_event
,
209 LttvHooks
*before_event
,
210 LttvHooks
*after_event
)
212 LttvTraceset
*ts
= self
->ts
;
214 guint i
, j
, nb_trace
, nb_control
, nb_per_cpu
, nb_tracefile
;
216 LttvTraceContext
*tc
;
218 LttvTracefileContext
*tfc
;
222 lttv_hooks_remove_list(self
->before
, before_traceset
);
223 lttv_hooks_remove_list(self
->after
, after_traceset
);
224 nb_trace
= lttv_traceset_number(ts
);
226 for(i
= 0 ; i
< nb_trace
; i
++) {
227 tc
= self
->traces
[i
];
228 lttv_hooks_remove_list(tc
->check
, check_trace
);
229 lttv_hooks_remove_list(tc
->before
, before_trace
);
230 lttv_hooks_remove_list(tc
->after
, after_trace
);
231 nb_control
= ltt_trace_control_tracefile_number(tc
->t
);
232 nb_per_cpu
= ltt_trace_control_tracefile_number(tc
->t
);
233 nb_tracefile
= nb_control
+ nb_per_cpu
;
235 for(j
= 0 ; j
< nb_tracefile
; j
++) {
237 tfc
= tc
->control_tracefiles
[j
];
240 tfc
= tc
->per_cpu_tracefiles
[j
];
242 lttv_hooks_remove_list(tfc
->check
, check_tracefile
);
243 lttv_hooks_remove_list(tfc
->before
, before_tracefile
);
244 lttv_hooks_remove_list(tfc
->after
, after_tracefile
);
245 lttv_hooks_remove_list(tfc
->check_event
, check_event
);
246 lttv_hooks_remove_list(tfc
->before_event
, before_event
);
247 lttv_hooks_remove_list(tfc
->after_event
, after_event
);
253 LttvTracesetContext
*
254 new_traceset_context(LttvTracesetContext
*self
)
256 return g_object_new(LTTV_TRACESET_CONTEXT_TYPE
);
261 new_trace_context(LttvTracesetContext
*self
)
263 return g_object_new(LTTV_TRACE_CONTEXT_TYPE
);
267 LttvTracefileContext
*
268 new_tracefile_context(LttvTracesetContext
*self
)
270 return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE
);
275 lttv_traceset_context_get_type(void)
277 static GType type
= 0;
279 static const GTypeInfo info
= {
280 sizeof (LttvTracesetContextClass
),
281 NULL
, /* base_init */
282 NULL
, /* base_finalize */
283 traceset_context_class_init
, /* class_init */
284 NULL
, /* class_finalize */
285 NULL
, /* class_data */
286 sizeof (LttvTracesetContext
),
288 traceset_context_instance_init
/* instance_init */
291 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracesetContextType",
299 traceset_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
301 /* Be careful of anything which would not work well with shallow copies */
306 traceset_context_finalize (LttvTracesetContext
*self
)
308 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACESET_CONTEXT_TYPE
))->finalize(self
);
313 traceset_context_class_init (LttvTracesetContextClass
*klass
)
315 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
317 gobject_class
->finalize
= traceset_context_finalize
;
320 klass
->new_traceset_context
= new_traceset_context
;
321 klass
->new_trace_context
= new_trace_context
;
322 klass
->new_tracefile_context
= new_tracefile_context
;
327 lttv_trace_context_get_type(void)
329 static GType type
= 0;
331 static const GTypeInfo info
= {
332 sizeof (LttvTraceContextClass
),
333 NULL
, /* base_init */
334 NULL
, /* base_finalize */
335 trace_context_class_init
, /* class_init */
336 NULL
, /* class_finalize */
337 NULL
, /* class_data */
338 sizeof (LttvTraceSetContext
),
340 trace_context_instance_init
/* instance_init */
343 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTraceContextType",
351 trace_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
353 /* Be careful of anything which would not work well with shallow copies */
358 trace_context_finalize (LttvTraceContext
*self
)
360 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACE_CONTEXT_TYPE
))->finalize(self
);
365 trace_context_class_init (LttvTraceContextClass
*klass
)
367 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
369 gobject_class
->finalize
= trace_context_finalize
;
374 lttv_tracefile_context_get_type(void)
376 static GType type
= 0;
378 static const GTypeInfo info
= {
379 sizeof (LttvTracefileContextClass
),
380 NULL
, /* base_init */
381 NULL
, /* base_finalize */
382 tracefile_context_class_init
, /* class_init */
383 NULL
, /* class_finalize */
384 NULL
, /* class_data */
385 sizeof (LttvTracefileContext
),
387 tracefile_context_instance_init
/* instance_init */
390 type
= g_type_register_static (G_TYPE_OBJECT
, "LttvTracefileContextType",
398 tracefile_context_instance_init (GTypeInstance
*instance
, gpointer g_class
)
400 /* Be careful of anything which would not work well with shallow copies */
405 tracefile_context_finalize (LttvTracefileContext
*self
)
407 G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_TRACEFILE_CONTEXT_TYPE
))->finalize(self
);
412 tracefile_context_class_init (LttvTracefileContextClass
*klass
)
414 GObjectClass
*gobject_class
= G_OBJECT_CLASS(klass
);
416 gobject_class
->finalize
= tracefile_context_finalize
;
420 guint
compare_tracefile(gconstpointer a
, gconstpointer b
)
422 if((LttvTime
*)a
->tv_sec
> (LttvTime
*)b
->tv_sec
) return 1;
423 if((LttvTime
*)a
->tv_sec
< (LttvTime
*)b
->tv_sec
) return -1;
424 if((LttvTime
*)a
->tv_nsec
> (LttvTime
*)b
->tv_nsec
) return 1;
425 if((LttvTime
*)a
->tv_nsec
< (LttvTime
*)b
->tv_nsec
) return -1;
430 gboolean
get_first(gpointer key
, gpointer value
, gpointer user_data
) {
431 *((LttvTracefileContext
**)user_data
) = (LttvTracefileContext
*)value
;
436 void lttv_process_trace(LttvTime start
, LttvTime end
, LttvTraceset
*traceset
,
437 LttvTracesetContext
*context
)
439 GPtrArray
*traces
= g_ptr_array_new();
441 GPtrArray
*tracefiles
= g_ptr_array_new();
443 GTree
*pqueue
= g_tree_new(compare_tracefile
);
445 guint i
, j
, nbi
, nbj
, id
;
449 LttvTraceContext
*tc
;
451 LttTracefile
*tracefile
;
453 LttvTracefileContext
*tfc
;
457 /* Call all before_traceset, before_trace, and before_tracefile hooks.
458 For all qualifying tracefiles, seek to the start time, create a context,
459 read one event and insert in the pqueue based on the event time. */
461 lttv_hooks_call(context
->before
, context
);
462 nbi
= ltt_trace_set_number(traceset
);
464 for(i
= 0 ; i
< nbi
; i
++) {
465 tc
= context
->traces
[i
];
468 if(!lttv_hooks_call_check(tc
->check
, tc
)) {
469 g_ptr_array_add(traces
, tc
);
470 lttv_hooks_call(tc
->before
, tc
);
471 nb_control
= ltt_trace_control_tracefile_number(trace
);
472 nb_cpu
= ltt_trace_per_cpu_tracefile_number(trace
);
473 nbj
= nb_control
+ nb_cpu
;
475 for(j
= 0 ; j
< nbj
; j
++) {
477 tfc
= tc
->control_tracefiles
[j
];
480 tfc
= tc
->per_cpu_tracefiles
[j
- nb_control
];
485 if(!lttv_hooks_call_check(tfc
->check
, tfc
)) {
486 g_ptr_array_add(tracefiles
, tfc
);
487 lttv_hooks_call(tfc
->before
, tfc
);
489 ltt_tracefile_seek_time(tracefile
, start
);
490 event
= ltt_tracefile_read(tracefile
);
494 tfc
->time
= ltt_event_time(event
);
495 g_tree_insert(pqueue
, &(tfc
->time
), tfc
);
502 /* Get the next event from the pqueue, call its hooks,
503 reinsert in the pqueue the following event from the same tracefile
504 unless the tracefile is finished or the event is later than the
509 g_tree_foreach(pqueue
, get_first
, &tfc
);
510 if(tfc
== NULL
) break;
512 /* Get the tracefile with an event for the smallest time found. If two
513 or more tracefiles have events for the same time, hope that lookup
514 and remove are consistent. */
516 tfc
= g_tree_lookup(pqueue
, &(tfc
->time
));
517 g_tree_remove(pqueue
, &(tfc
->time
));
519 if(!lttv_hooks_call(tfc
->check_event
, context
)) {
520 id
= lttv_event_id(tfc
->e
);
521 lttv_hooks_call(tfc
->before_event
, tfc
);
522 lttv_hooks_call(lttv_hooks_by_id_get(tfc
->before_event_by_id
, id
), tfc
);
523 lttv_hooks_call(tfc
->after_event
, context
);
524 lttv_hooks_call(lttv_hooks_by_id_get(tfc
->after_event_by_id
, id
), tfc
);
527 event
= ltt_tracefile_read(tfc
->tf
);
530 tfc
->time
= ltt_event_time(event
);
531 g_tree_insert(pqueue
, &(tfc
->time
), tfc
);
535 /* Call all the after_tracefile, after_trace and after_traceset hooks. */
537 for(i
= 0, j
= 0 ; i
< traces
->len
; i
++) {
538 tc
= traces
->pdata
[i
];
539 while(j
< tracefiles
->len
) {
540 tfc
= tracefiles
->pdata
[j
];
542 if(tfc
->t_context
== tc
) {
543 lttv_hooks_call(tfc
->after
, tfc
);
548 lttv_hooks_call(tc
->after
, tc
);
551 g_assert(j
== tracefiles
->len
);
552 lttv_hooks_call(after_traceset
, context
);
554 /* Free the traces, tracefiles and pqueue */
556 g_ptr_array_free(tracefiles
, TRUE
);
557 g_ptr_array_free(traces
, TRUE
);
558 g_tree_destroy(pqueue
, TRUE
);