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>
38 #include <ltt/markers.h>
41 void compute_fields_offsets(LttTracefile
*tf
,
42 LttFacility
*fac
, LttField
*field
, off_t
*offset
, void *root
,
46 LttEvent
*ltt_event_new()
48 return g_new(LttEvent
, 1);
51 void ltt_event_destroy(LttEvent
*event
)
57 /*****************************************************************************
59 * ltt_event_eventtype_id: get event type id
60 * (base id + position of the event)
62 * e : an instance of an event type
64 * unsigned : event type id
65 ****************************************************************************/
67 uint16_t ltt_event_eventtype_id(const LttEvent
*e
)
72 /*****************************************************************************
74 * ltt_event_facility : get the facility of the event
76 * e : an instance of an event type
78 * struct marker_info *: the marker associated with the event
79 ****************************************************************************/
81 struct marker_info
*ltt_event_marker(const LttEvent
*e
)
83 return marker_get_info_from_id(e
->tracefile
->trace
, e
->event_id
);
86 /*****************************************************************************
88 * ltt_event_time : get the time of the event
90 * e : an instance of an event type
92 * LttTime : the time of the event
93 ****************************************************************************/
95 LttTime
ltt_event_time(const LttEvent
*e
)
100 /*****************************************************************************
102 * ltt_event_time : get the cycle count of the event
104 * e : an instance of an event type
106 * LttCycleCount : the cycle count of the event
107 ****************************************************************************/
109 LttCycleCount
ltt_event_cycle_count(const LttEvent
*e
)
114 /*****************************************************************************
116 * ltt_event_position_get : get the event position data
118 * e : an instance of an event type
119 * ep : a pointer to event's position structure
120 * tf : tracefile pointer
121 * block : current block
122 * offset : current offset
124 ****************************************************************************/
125 void ltt_event_position_get(LttEventPosition
*ep
, LttTracefile
**tf
,
126 guint
*block
, guint
*offset
, guint64
*tsc
)
130 *offset
= ep
->offset
;
135 void ltt_event_position_set(LttEventPosition
*ep
, LttTracefile
*tf
,
136 guint block
, guint offset
, guint64 tsc
)
145 /*****************************************************************************
147 * ltt_event_position : get the event's position
149 * e : an instance of an event type
150 * ep : a pointer to event's position structure
151 ****************************************************************************/
153 void ltt_event_position(LttEvent
*e
, LttEventPosition
*ep
)
155 ep
->tracefile
= e
->tracefile
;
156 ep
->block
= e
->block
;
157 ep
->offset
= e
->offset
;
161 LttEventPosition
* ltt_event_position_new()
163 return g_new(LttEventPosition
, 1);
167 /*****************************************************************************
169 * ltt_event_position_compare : compare two positions
170 * A NULL value is infinite.
172 * ep1 : a pointer to event's position structure
173 * ep2 : a pointer to event's position structure
178 ****************************************************************************/
181 gint
ltt_event_position_compare(const LttEventPosition
*ep1
,
182 const LttEventPosition
*ep2
)
184 if(ep1
== NULL
&& ep2
== NULL
)
186 if(ep1
!= NULL
&& ep2
== NULL
)
188 if(ep1
== NULL
&& ep2
!= NULL
)
191 if(ep1
->tracefile
!= ep2
->tracefile
)
192 g_error("ltt_event_position_compare on different tracefiles makes no sense");
194 if(ep1
->block
< ep2
->block
)
196 if(ep1
->block
> ep2
->block
)
198 if(ep1
->offset
< ep2
->offset
)
200 if(ep1
->offset
> ep2
->offset
)
205 /*****************************************************************************
207 * ltt_event_position_copy : copy position
209 * src : a pointer to event's position structure source
210 * dest : a pointer to event's position structure dest
213 ****************************************************************************/
214 void ltt_event_position_copy(LttEventPosition
*dest
,
215 const LttEventPosition
*src
)
225 LttTracefile
*ltt_event_position_tracefile(LttEventPosition
*ep
)
227 return ep
->tracefile
;
230 /*****************************************************************************
232 * ltt_event_cpu_i: get the cpu id where the event happens
234 * e : an instance of an event type
236 * unsigned : the cpu id
237 ****************************************************************************/
239 unsigned ltt_event_cpu_id(LttEvent
*e
)
241 return e
->tracefile
->cpu_num
;
244 /*****************************************************************************
246 * ltt_event_data : get the raw data for the event
248 * e : an instance of an event type
250 * void * : pointer to the raw data for the event
251 ****************************************************************************/
253 void *ltt_event_data(LttEvent
*e
)
258 /*****************************************************************************
260 * ltt_event_field_element_number
261 * : The number of elements in a sequence field is specific
262 * to each event. This function returns the number of
263 * elements for an array or sequence field in an event.
265 * e : an instance of an event type
266 * f : a field of the instance
268 * unsigned : the number of elements for an array/sequence field
269 ****************************************************************************/
270 guint64
ltt_event_field_element_number(LttEvent
*e
, LttField
*f
)
272 if(f
->field_type
.type_class
!= LTT_ARRAY
&&
273 f
->field_type
.type_class
!= LTT_SEQUENCE
)
276 if(f
->field_type
.type_class
== LTT_ARRAY
)
277 return f
->field_type
.size
;
278 return ltt_event_get_long_unsigned(e
, &g_array_index(f
->field_type
.fields
,
282 /*****************************************************************************
284 * ltt_event_field_element_select
285 * : Set the currently selected element for a sequence or
287 * O(1) because of offset array.
289 * e : an instance of an event type
290 * f : a field of the instance
291 * i : the ith element (0, ...)
292 *returns : the child field, at the right index, updated.
293 ****************************************************************************/
294 LttField
*ltt_event_field_element_select(LttEvent
*e
, LttField
*f
, gulong i
)
296 gulong element_number
;
300 LttEventType
*event_type
;
303 if(f
->field_type
.type_class
!= LTT_ARRAY
&&
304 f
->field_type
.type_class
!= LTT_SEQUENCE
)
307 element_number
= ltt_event_field_element_number(e
,f
);
308 event_type
= ltt_event_eventtype(e
);
309 /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number
311 if(i
>= element_number
) return NULL
;
313 if(f
->field_type
.type_class
== LTT_ARRAY
) {
314 field
= &g_array_index(f
->field_type
.fields
, LttField
, 0);
316 field
= &g_array_index(f
->field_type
.fields
, LttField
, 1);
319 if(field
->field_size
!= 0) {
320 if(f
->array_offset
+ (i
* field
->field_size
) == field
->offset_root
)
321 return field
; /* fixed length child, already at the right offset */
323 new_offset
= f
->array_offset
+ (i
* field
->field_size
);
325 /* Var. len. child */
326 new_offset
= g_array_index(f
->dynamic_offsets
, off_t
, i
);
328 compute_fields_offsets(e
->tracefile
,
329 ltt_event_facility(e
), field
, &new_offset
, e
->data
, 0);
335 off_t
ltt_event_field_offset(LttEvent
*e
, LttField
*f
)
337 return f
->offset_root
;
342 /*****************************************************************************
343 * These functions extract data from an event after architecture specific
345 ****************************************************************************/
346 guint32
ltt_event_get_unsigned(LttEvent
*e
, LttField
*f
)
348 gboolean reverse_byte_order
;
349 if(unlikely(f
->field_type
.network
)) {
350 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
352 reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
355 switch(f
->field_size
) {
358 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
363 return (guint32
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
366 return (guint32
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
370 g_critical("ltt_event_get_unsigned : field size %i unknown", f
->field_size
);
376 gint32
ltt_event_get_int(LttEvent
*e
, LttField
*f
)
378 gboolean reverse_byte_order
;
379 if(unlikely(f
->field_type
.network
)) {
380 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
382 reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
385 switch(f
->field_size
) {
388 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
393 return (gint32
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
396 return (gint32
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
400 g_critical("ltt_event_get_int : field size %i unknown", f
->field_size
);
406 guint64
ltt_event_get_long_unsigned(LttEvent
*e
, LttField
*f
)
408 gboolean reverse_byte_order
;
409 if(unlikely(f
->field_type
.network
)) {
410 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
412 reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
415 switch(f
->field_size
) {
418 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
423 return (guint64
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
426 return (guint64
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
429 return ltt_get_uint64(reverse_byte_order
, e
->data
+ f
->offset_root
);
432 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f
->field_size
);
438 gint64
ltt_event_get_long_int(LttEvent
*e
, LttField
*f
)
440 gboolean reverse_byte_order
;
441 if(unlikely(f
->field_type
.network
)) {
442 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
444 reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
447 switch(f
->field_size
) {
450 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
455 return (gint64
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
458 return (gint64
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
461 return ltt_get_int64(reverse_byte_order
, e
->data
+ f
->offset_root
);
464 g_critical("ltt_event_get_long_int : field size %i unknown", f
->field_size
);
470 float ltt_event_get_float(LttEvent
*e
, LttField
*f
)
472 gboolean reverse_byte_order
;
473 if(unlikely(f
->field_type
.network
)) {
474 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
476 g_assert(LTT_HAS_FLOAT(e
->tracefile
));
477 reverse_byte_order
= LTT_GET_FLOAT_BO(e
->tracefile
);
480 g_assert(f
->field_type
.type_class
== LTT_FLOAT
&& f
->field_size
== 4);
482 if(reverse_byte_order
== 0) return *(float *)(e
->data
+ f
->offset_root
);
484 void *ptr
= e
->data
+ f
->offset_root
;
485 guint32 value
= bswap_32(*(guint32
*)ptr
);
486 return *(float*)&value
;
490 double ltt_event_get_double(LttEvent
*e
, LttField
*f
)
492 gboolean reverse_byte_order
;
493 if(unlikely(f
->field_type
.network
)) {
494 reverse_byte_order
= (g_ntohs(0x1) != 0x1);
496 g_assert(LTT_HAS_FLOAT(e
->tracefile
));
497 reverse_byte_order
= LTT_GET_FLOAT_BO(e
->tracefile
);
500 if(f
->field_size
== 4)
501 return ltt_event_get_float(e
, f
);
503 g_assert(f
->field_type
.type_class
== LTT_FLOAT
&& f
->field_size
== 8);
505 if(reverse_byte_order
== 0) return *(double *)(e
->data
+ f
->offset_root
);
507 void *ptr
= e
->data
+ f
->offset_root
;
508 guint64 value
= bswap_64(*(guint64
*)ptr
);
509 return *(double*)&value
;
513 /*****************************************************************************
514 * The string obtained is only valid until the next read from
515 * the same tracefile.
516 ****************************************************************************/
517 char *ltt_event_get_string(LttEvent
*e
, LttField
*f
)
519 g_assert(f
->field_type
.type_class
== LTT_STRING
);
521 return (gchar
*)g_strdup((gchar
*)(e
->data
+ f
->offset_root
));
524 /*****************************************************************************
526 * compute_fields_offsets : set the precomputable offset of the fields
530 * offset : pointer to the current offset, must be incremented
531 ****************************************************************************/
534 void compute_fields_offsets(LttTracefile
*tf
,
535 LttFacility
*fac
, LttField
*field
, off_t
*offset
, void *root
, guint is_compact
)
537 LttType
*type
= &field
->field_type
;
539 if(unlikely(is_compact
)) {
540 g_assert(field
->field_size
!= 0);
541 /* FIXME THIS IS A HUUUUUGE hack :
542 * offset is between the compact_data field in struct LttEvent
543 * and the address of the field root in the memory map.
544 * ark. Both will stay at the same addresses while the event
545 * is readable, so it's ok.
547 field
->offset_root
= (unsigned long)(&tf
->event
.compact_data
)
548 - (unsigned long)root
;
549 field
->fixed_root
= FIELD_FIXED
;
553 switch(type
->type_class
) {
570 if(field
->fixed_root
== FIELD_VARIABLE
) {
571 /* Align offset on type size */
572 *offset
+= ltt_align(*offset
, get_alignment(field
),
574 /* remember offset */
575 field
->offset_root
= *offset
;
576 /* Increment offset */
577 *offset
+= field
->field_size
;
579 //g_debug("type before offset : %llu %llu %u\n", *offset,
580 // field->offset_root,
581 // field->field_size);
582 *offset
= field
->offset_root
;
583 *offset
+= field
->field_size
;
584 //g_debug("type after offset : %llu\n", *offset);
588 if(field
->fixed_root
== FIELD_VARIABLE
) {
589 field
->offset_root
= *offset
;
591 *offset
+= strlen((gchar
*)(root
+*offset
)) + 1;
592 /* Realign the data */
593 *offset
+= ltt_align(*offset
, fac
->pointer_size
,
597 g_assert(type
->fields
->len
== 1);
600 LttField
*child
= &g_array_index(type
->fields
, LttField
, 0);
601 if(field
->fixed_root
== FIELD_VARIABLE
) {
602 *offset
+= ltt_align(*offset
, get_alignment(field
),
604 /* remember offset */
605 field
->offset_root
= *offset
;
606 field
->array_offset
= *offset
;
609 if(field
->field_size
!= 0) {
610 /* Increment offset */
611 /* field_size is the array size in bytes */
612 *offset
= field
->offset_root
+ field
->field_size
;
615 *offset
= field
->array_offset
;
616 field
->dynamic_offsets
= g_array_set_size(field
->dynamic_offsets
,
618 for(i
=0; i
<type
->size
; i
++) {
619 g_array_append_val(field
->dynamic_offsets
, *offset
);
620 compute_fields_offsets(tf
, fac
, child
, offset
, root
, is_compact
);
623 // local_offset = field->array_offset;
624 // /* Set the offset at position 0 */
625 // compute_fields_offsets(tf, fac, child, &local_offset, root);
629 g_assert(type
->fields
->len
== 2);
635 if(field
->fixed_root
== FIELD_VARIABLE
) {
636 *offset
+= ltt_align(*offset
, get_alignment(field
),
638 /* remember offset */
639 field
->offset_root
= *offset
;
641 child
= &g_array_index(type
->fields
, LttField
, 0);
642 compute_fields_offsets(tf
, fac
, child
, offset
, root
, is_compact
);
643 child
= &g_array_index(type
->fields
, LttField
, 1);
644 *offset
+= ltt_align(*offset
, get_alignment(child
),
646 field
->array_offset
= *offset
;
649 child
= &g_array_index(type
->fields
, LttField
, 1);
651 *offset
= field
->array_offset
;
652 field
->dynamic_offsets
= g_array_set_size(field
->dynamic_offsets
,
654 num_elem
= ltt_event_field_element_number(&tf
->event
, field
);
655 for(i
=0; i
<num_elem
; i
++) {
656 g_array_append_val(field
->dynamic_offsets
, *offset
);
657 compute_fields_offsets(tf
, fac
, child
, offset
, root
, is_compact
);
659 g_assert(num_elem
== field
->dynamic_offsets
->len
);
661 /* Realign the data */
662 *offset
+= ltt_align(*offset
, fac
->pointer_size
,
665 // local_offset = field->array_offset;
666 // /* Set the offset at position 0 */
667 // compute_fields_offsets(tf, fac, child, &local_offset, root);
675 if(field
->fixed_root
== FIELD_VARIABLE
) {
676 *offset
+= ltt_align(*offset
, get_alignment(field
),
678 /* remember offset */
679 field
->offset_root
= *offset
;
681 *offset
= field
->offset_root
;
683 for(i
=0; i
<type
->fields
->len
; i
++) {
684 child
= &g_array_index(type
->fields
, LttField
, i
);
685 compute_fields_offsets(tf
, fac
, child
, offset
, root
, is_compact
);
694 if(field
->fixed_root
== FIELD_VARIABLE
) {
695 *offset
+= ltt_align(*offset
, get_alignment(field
),
697 /* remember offset */
698 field
->offset_root
= *offset
;
700 for(i
=0; i
<type
->fields
->len
; i
++) {
701 *offset
= field
->offset_root
;
702 child
= &g_array_index(type
->fields
, LttField
, i
);
703 compute_fields_offsets(tf
, fac
, child
, offset
, root
, is_compact
);
705 *offset
= field
->offset_root
+ field
->field_size
;
710 g_error("compute_fields_offsets : unknown type");
716 /*****************************************************************************
718 * compute_offsets : set the dynamically computable offsets of an event type
723 ****************************************************************************/
724 void compute_offsets(LttTracefile
*tf
, LttFacility
*fac
,
725 LttEventType
*event
, off_t
*offset
, void *root
)
729 /* compute all variable offsets */
730 for(i
=0; i
<event
->fields
->len
; i
++) {
731 //g_debug("computing offset %u of %u\n", i, event->fields->len-1);
732 LttField
*field
= &g_array_index(event
->fields
, LttField
, i
);
733 if(event
->has_compact_data
&& i
== 0)
734 compute_fields_offsets(tf
, fac
, field
, offset
, root
, 1);
736 compute_fields_offsets(tf
, fac
, field
, offset
, root
, 0);