1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Xiangxiu Yang
3 * 2006 Mathieu Desnoyers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License Version 2.1 as published by the Free Software Foundation.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
29 #include <asm/types.h>
34 #include "ltt-private.h"
35 #include <ltt/event.h>
36 #include <ltt/trace.h>
37 #include <ltt/ltt-types.h>
41 void compute_fields_offsets(LttTracefile
*tf
,
42 LttFacility
*fac
, LttField
*field
, off_t
*offset
, void *root
, guint is_compact
);
45 LttEvent
*ltt_event_new()
47 return g_new(LttEvent
, 1);
50 void ltt_event_destroy(LttEvent
*event
)
56 /*****************************************************************************
58 * ltt_event_eventtype_id: get event type id
59 * (base id + position of the event)
61 * e : an instance of an event type
63 * unsigned : event type id
64 ****************************************************************************/
66 unsigned ltt_event_eventtype_id(const LttEvent
*e
)
68 return (unsigned) e
->event_id
;
71 /*****************************************************************************
73 * ltt_event_facility : get the facility of the event
75 * e : an instance of an event type
77 * LttFacility * : the facility of the event
78 ****************************************************************************/
80 LttFacility
*ltt_event_facility(const LttEvent
*e
)
82 LttTrace
* trace
= e
->tracefile
->trace
;
83 unsigned id
= e
->facility_id
;
84 LttFacility
*facility
= ltt_trace_facility_by_id(trace
,id
);
86 g_assert(facility
->exists
);
91 /*****************************************************************************
93 * ltt_event_facility_id : get the facility id of the event
95 * e : an instance of an event type
97 * unsigned : the facility of the event
98 ****************************************************************************/
100 unsigned ltt_event_facility_id(const LttEvent
*e
)
102 return e
->facility_id
;
105 /*****************************************************************************
107 * ltt_event_eventtype : get the event type of the event
109 * e : an instance of an event type
111 * LttEventType * : the event type of the event
112 ****************************************************************************/
114 LttEventType
*ltt_event_eventtype(const LttEvent
*e
)
116 LttFacility
* facility
= ltt_event_facility(e
);
117 if(!facility
) return NULL
;
118 return &g_array_index(facility
->events
, LttEventType
, e
->event_id
);
122 /*****************************************************************************
124 * ltt_event_time : get the time of the event
126 * e : an instance of an event type
128 * LttTime : the time of the event
129 ****************************************************************************/
131 LttTime
ltt_event_time(const LttEvent
*e
)
133 return e
->event_time
;
136 /*****************************************************************************
138 * ltt_event_time : get the cycle count of the event
140 * e : an instance of an event type
142 * LttCycleCount : the cycle count of the event
143 ****************************************************************************/
145 LttCycleCount
ltt_event_cycle_count(const LttEvent
*e
)
152 /*****************************************************************************
154 * ltt_event_position_get : get the event position data
156 * e : an instance of an event type
157 * ep : a pointer to event's position structure
158 * tf : tracefile pointer
159 * block : current block
160 * offset : current offset
162 ****************************************************************************/
163 void ltt_event_position_get(LttEventPosition
*ep
, LttTracefile
**tf
,
164 guint
*block
, guint
*offset
, guint64
*tsc
)
168 *offset
= ep
->offset
;
173 void ltt_event_position_set(LttEventPosition
*ep
, LttTracefile
*tf
,
174 guint block
, guint offset
, guint64 tsc
)
183 /*****************************************************************************
185 * ltt_event_position : get the event's position
187 * e : an instance of an event type
188 * ep : a pointer to event's position structure
189 ****************************************************************************/
191 void ltt_event_position(LttEvent
*e
, LttEventPosition
*ep
)
193 ep
->tracefile
= e
->tracefile
;
194 ep
->block
= e
->block
;
195 ep
->offset
= e
->offset
;
199 LttEventPosition
* ltt_event_position_new()
201 return g_new(LttEventPosition
, 1);
205 /*****************************************************************************
207 * ltt_event_position_compare : compare two positions
208 * A NULL value is infinite.
210 * ep1 : a pointer to event's position structure
211 * ep2 : a pointer to event's position structure
216 ****************************************************************************/
219 gint
ltt_event_position_compare(const LttEventPosition
*ep1
,
220 const LttEventPosition
*ep2
)
222 if(ep1
== NULL
&& ep2
== NULL
)
224 if(ep1
!= NULL
&& ep2
== NULL
)
226 if(ep1
== NULL
&& ep2
!= NULL
)
229 if(ep1
->tracefile
!= ep2
->tracefile
)
230 g_error("ltt_event_position_compare on different tracefiles makes no sense");
232 if(ep1
->block
< ep2
->block
)
234 if(ep1
->block
> ep2
->block
)
236 if(ep1
->offset
< ep2
->offset
)
238 if(ep1
->offset
> ep2
->offset
)
243 /*****************************************************************************
245 * ltt_event_position_copy : copy position
247 * src : a pointer to event's position structure source
248 * dest : a pointer to event's position structure dest
251 ****************************************************************************/
252 void ltt_event_position_copy(LttEventPosition
*dest
,
253 const LttEventPosition
*src
)
263 LttTracefile
*ltt_event_position_tracefile(LttEventPosition
*ep
)
265 return ep
->tracefile
;
268 /*****************************************************************************
270 * ltt_event_cpu_i: get the cpu id where the event happens
272 * e : an instance of an event type
274 * unsigned : the cpu id
275 ****************************************************************************/
277 unsigned ltt_event_cpu_id(LttEvent
*e
)
279 return e
->tracefile
->cpu_num
;
282 /*****************************************************************************
284 * ltt_event_data : get the raw data for the event
286 * e : an instance of an event type
288 * void * : pointer to the raw data for the event
289 ****************************************************************************/
291 void *ltt_event_data(LttEvent
*e
)
296 /*****************************************************************************
298 * ltt_event_field_element_number
299 * : The number of elements in a sequence field is specific
300 * to each event. This function returns the number of
301 * elements for an array or sequence field in an event.
303 * e : an instance of an event type
304 * f : a field of the instance
306 * unsigned : the number of elements for an array/sequence field
307 ****************************************************************************/
308 guint64
ltt_event_field_element_number(LttEvent
*e
, LttField
*f
)
310 if(f
->field_type
.type_class
!= LTT_ARRAY
&&
311 f
->field_type
.type_class
!= LTT_SEQUENCE
)
314 if(f
->field_type
.type_class
== LTT_ARRAY
)
315 return f
->field_type
.size
;
316 return ltt_event_get_long_unsigned(e
, &g_array_index(f
->field_type
.fields
,
320 /*****************************************************************************
322 * ltt_event_field_element_select
323 * : Set the currently selected element for a sequence or
325 * O(1) because of offset array.
327 * e : an instance of an event type
328 * f : a field of the instance
329 * i : the ith element (0, ...)
330 *returns : the child field, at the right index, updated.
331 ****************************************************************************/
332 LttField
*ltt_event_field_element_select(LttEvent
*e
, LttField
*f
, gulong i
)
334 gulong element_number
;
338 LttEventType
*event_type
;
341 if(f
->field_type
.type_class
!= LTT_ARRAY
&&
342 f
->field_type
.type_class
!= LTT_SEQUENCE
)
345 element_number
= ltt_event_field_element_number(e
,f
);
346 event_type
= ltt_event_eventtype(e
);
347 /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number
349 if(i
>= element_number
) return NULL
;
351 if(f
->field_type
.type_class
== LTT_ARRAY
) {
352 field
= &g_array_index(f
->field_type
.fields
, LttField
, 0);
354 field
= &g_array_index(f
->field_type
.fields
, LttField
, 1);
357 if(field
->field_size
!= 0) {
358 if(f
->array_offset
+ (i
* field
->field_size
) == field
->offset_root
)
359 return field
; /* fixed length child, already at the right offset */
361 new_offset
= f
->array_offset
+ (i
* field
->field_size
);
363 /* Var. len. child */
364 new_offset
= g_array_index(f
->dynamic_offsets
, off_t
, i
);
366 compute_fields_offsets(e
->tracefile
,
367 ltt_event_facility(e
), field
, &new_offset
, e
->data
, 0);
373 off_t
ltt_event_field_offset(LttEvent
*e
, LttField
*f
)
375 return f
->offset_root
;
380 /*****************************************************************************
381 * These functions extract data from an event after architecture specific
383 ****************************************************************************/
384 guint32
ltt_event_get_unsigned(LttEvent
*e
, LttField
*f
)
386 gboolean reverse_byte_order
;
387 if(unlikely(f
->field_type
.network
)) {
388 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
390 reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
393 switch(f
->field_size
) {
396 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
401 return (guint32
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
404 return (guint32
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
408 g_critical("ltt_event_get_unsigned : field size %i unknown", f
->field_size
);
414 gint32
ltt_event_get_int(LttEvent
*e
, LttField
*f
)
416 gboolean reverse_byte_order
;
417 if(unlikely(f
->field_type
.network
)) {
418 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
420 reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
423 switch(f
->field_size
) {
426 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
431 return (gint32
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
434 return (gint32
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
438 g_critical("ltt_event_get_int : field size %i unknown", f
->field_size
);
444 guint64
ltt_event_get_long_unsigned(LttEvent
*e
, LttField
*f
)
446 gboolean reverse_byte_order
;
447 if(unlikely(f
->field_type
.network
)) {
448 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
450 reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
453 switch(f
->field_size
) {
456 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
461 return (guint64
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
464 return (guint64
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
467 return ltt_get_uint64(reverse_byte_order
, e
->data
+ f
->offset_root
);
470 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f
->field_size
);
476 gint64
ltt_event_get_long_int(LttEvent
*e
, LttField
*f
)
478 gboolean reverse_byte_order
;
479 if(unlikely(f
->field_type
.network
)) {
480 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
482 reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
485 switch(f
->field_size
) {
488 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
493 return (gint64
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
496 return (gint64
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
499 return ltt_get_int64(reverse_byte_order
, e
->data
+ f
->offset_root
);
502 g_critical("ltt_event_get_long_int : field size %i unknown", f
->field_size
);
508 float ltt_event_get_float(LttEvent
*e
, LttField
*f
)
510 gboolean reverse_byte_order
;
511 if(unlikely(f
->field_type
.network
)) {
512 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
514 g_assert(LTT_HAS_FLOAT(e
->tracefile
));
515 reverse_byte_order
= LTT_GET_FLOAT_BO(e
->tracefile
);
518 g_assert(f
->field_type
.type_class
== LTT_FLOAT
&& f
->field_size
== 4);
520 if(reverse_byte_order
== 0) return *(float *)(e
->data
+ f
->offset_root
);
522 void *ptr
= e
->data
+ f
->offset_root
;
523 guint32 value
= bswap_32(*(guint32
*)ptr
);
524 return *(float*)&value
;
528 double ltt_event_get_double(LttEvent
*e
, LttField
*f
)
530 gboolean reverse_byte_order
;
531 if(unlikely(f
->field_type
.network
)) {
532 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
534 g_assert(LTT_HAS_FLOAT(e
->tracefile
));
535 reverse_byte_order
= LTT_GET_FLOAT_BO(e
->tracefile
);
538 if(f
->field_size
== 4)
539 return ltt_event_get_float(e
, f
);
541 g_assert(f
->field_type
.type_class
== LTT_FLOAT
&& f
->field_size
== 8);
543 if(reverse_byte_order
== 0) return *(double *)(e
->data
+ f
->offset_root
);
545 void *ptr
= e
->data
+ f
->offset_root
;
546 guint64 value
= bswap_64(*(guint64
*)ptr
);
547 return *(double*)&value
;
551 /*****************************************************************************
552 * The string obtained is only valid until the next read from
553 * the same tracefile.
554 ****************************************************************************/
555 char *ltt_event_get_string(LttEvent
*e
, LttField
*f
)
557 g_assert(f
->field_type
.type_class
== LTT_STRING
);
559 return (gchar
*)g_strdup((gchar
*)(e
->data
+ f
->offset_root
));
562 /*****************************************************************************
564 * compute_fields_offsets : set the precomputable offset of the fields
568 * offset : pointer to the current offset, must be incremented
569 ****************************************************************************/
572 void compute_fields_offsets(LttTracefile
*tf
,
573 LttFacility
*fac
, LttField
*field
, off_t
*offset
, void *root
, guint is_compact
)
575 LttType
*type
= &field
->field_type
;
577 if(unlikely(is_compact
)) {
578 g_assert(field
->field_size
!= 0);
579 /* FIXME THIS IS A HUUUUUGE hack :
580 * offset is between the compact_data field in struct LttEvent
581 * and the address of the field root in the memory map.
582 * ark. Both will stay at the same addresses while the event
583 * is readable, so it's ok.
585 field
->offset_root
= (unsigned long)(&tf
->event
.compact_data
)
586 - (unsigned long)root
;
587 field
->fixed_root
= FIELD_FIXED
;
591 switch(type
->type_class
) {
608 if(field
->fixed_root
== FIELD_VARIABLE
) {
609 /* Align offset on type size */
610 *offset
+= ltt_align(*offset
, get_alignment(field
),
612 /* remember offset */
613 field
->offset_root
= *offset
;
614 /* Increment offset */
615 *offset
+= field
->field_size
;
617 //g_debug("type before offset : %llu %llu %u\n", *offset,
618 // field->offset_root,
619 // field->field_size);
620 *offset
= field
->offset_root
;
621 *offset
+= field
->field_size
;
622 //g_debug("type after offset : %llu\n", *offset);
626 if(field
->fixed_root
== FIELD_VARIABLE
) {
627 field
->offset_root
= *offset
;
629 *offset
+= strlen((gchar
*)(root
+*offset
)) + 1;
630 /* Realign the data */
631 *offset
+= ltt_align(*offset
, fac
->pointer_size
,
635 g_assert(type
->fields
->len
== 1);
638 LttField
*child
= &g_array_index(type
->fields
, LttField
, 0);
639 if(field
->fixed_root
== FIELD_VARIABLE
) {
640 *offset
+= ltt_align(*offset
, get_alignment(field
),
642 /* remember offset */
643 field
->offset_root
= *offset
;
644 field
->array_offset
= *offset
;
647 if(field
->field_size
!= 0) {
648 /* Increment offset */
649 /* field_size is the array size in bytes */
650 *offset
= field
->offset_root
+ field
->field_size
;
653 *offset
= field
->array_offset
;
654 field
->dynamic_offsets
= g_array_set_size(field
->dynamic_offsets
,
656 for(i
=0; i
<type
->size
; i
++) {
657 g_array_append_val(field
->dynamic_offsets
, *offset
);
658 compute_fields_offsets(tf
, fac
, child
, offset
, root
, is_compact
);
661 // local_offset = field->array_offset;
662 // /* Set the offset at position 0 */
663 // compute_fields_offsets(tf, fac, child, &local_offset, root);
667 g_assert(type
->fields
->len
== 2);
673 if(field
->fixed_root
== FIELD_VARIABLE
) {
674 *offset
+= ltt_align(*offset
, get_alignment(field
),
676 /* remember offset */
677 field
->offset_root
= *offset
;
679 child
= &g_array_index(type
->fields
, LttField
, 0);
680 compute_fields_offsets(tf
, fac
, child
, offset
, root
, is_compact
);
681 child
= &g_array_index(type
->fields
, LttField
, 1);
682 *offset
+= ltt_align(*offset
, get_alignment(child
),
684 field
->array_offset
= *offset
;
687 child
= &g_array_index(type
->fields
, LttField
, 1);
689 *offset
= field
->array_offset
;
690 field
->dynamic_offsets
= g_array_set_size(field
->dynamic_offsets
,
692 num_elem
= ltt_event_field_element_number(&tf
->event
, field
);
693 for(i
=0; i
<num_elem
; i
++) {
694 g_array_append_val(field
->dynamic_offsets
, *offset
);
695 compute_fields_offsets(tf
, fac
, child
, offset
, root
, is_compact
);
697 g_assert(num_elem
== field
->dynamic_offsets
->len
);
699 /* Realign the data */
700 *offset
+= ltt_align(*offset
, fac
->pointer_size
,
703 // local_offset = field->array_offset;
704 // /* Set the offset at position 0 */
705 // compute_fields_offsets(tf, fac, child, &local_offset, root);
713 if(field
->fixed_root
== FIELD_VARIABLE
) {
714 *offset
+= ltt_align(*offset
, get_alignment(field
),
716 /* remember offset */
717 field
->offset_root
= *offset
;
719 *offset
= field
->offset_root
;
721 for(i
=0; i
<type
->fields
->len
; i
++) {
722 child
= &g_array_index(type
->fields
, LttField
, i
);
723 compute_fields_offsets(tf
, fac
, child
, offset
, root
, is_compact
);
732 if(field
->fixed_root
== FIELD_VARIABLE
) {
733 *offset
+= ltt_align(*offset
, get_alignment(field
),
735 /* remember offset */
736 field
->offset_root
= *offset
;
738 for(i
=0; i
<type
->fields
->len
; i
++) {
739 *offset
= field
->offset_root
;
740 child
= &g_array_index(type
->fields
, LttField
, i
);
741 compute_fields_offsets(tf
, fac
, child
, offset
, root
, is_compact
);
743 *offset
= field
->offset_root
+ field
->field_size
;
748 g_error("compute_fields_offsets : unknown type");
754 /*****************************************************************************
756 * compute_offsets : set the dynamically computable offsets of an event type
761 ****************************************************************************/
762 void compute_offsets(LttTracefile
*tf
, LttFacility
*fac
,
763 LttEventType
*event
, off_t
*offset
, void *root
)
767 /* compute all variable offsets */
768 for(i
=0; i
<event
->fields
->len
; i
++) {
769 //g_debug("computing offset %u of %u\n", i, event->fields->len-1);
770 LttField
*field
= &g_array_index(event
->fields
, LttField
, i
);
771 if(event
->has_compact_data
&& i
== 0)
772 compute_fields_offsets(tf
, fac
, field
, offset
, root
, 1);
774 compute_fields_offsets(tf
, fac
, field
, offset
, root
, 0);