1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Xiangxiu Yang
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;
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.
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,
28 #include <asm/types.h>
33 #include "ltt-private.h"
34 #include <ltt/event.h>
35 #include <ltt/trace.h>
36 #include <ltt/ltt-types.h>
38 LttEvent
*ltt_event_new()
40 return g_new(LttEvent
, 1);
43 void ltt_event_destroy(LttEvent
*event
)
50 /* Use get_field_type_size instead */
51 /*****************************************************************************
53 * ltt_event_refresh_fields : refresh fields of an event
55 * offsetRoot : offset from the root
56 * offsetParent : offset from the parent
59 * reverse_byte_order : 1 or 0
61 * int : size of the field
62 ****************************************************************************/
64 int ltt_event_refresh_fields(int offsetRoot
,int offsetParent
,
65 LttField
* fld
, void *evD
, gboolean reverse_byte_order
)
67 int size
, size1
, element_number
, i
, offset1
, offset2
;
68 LttType
* type
= fld
->field_type
;
70 switch(type
->type_class
) {
72 element_number
= (int) type
->element_number
;
73 if(fld
->field_fixed
== 0){// has string or sequence
75 for(i
=0;i
<element_number
;i
++){
76 size
+= ltt_event_refresh_fields(offsetRoot
+size
,size
,
77 fld
->child
[0], evD
+size
, reverse_byte_order
);
79 }else size
= fld
->field_size
;
83 size1
= fld
->sequ_number_size
;
84 element_number
= getIntNumber(reverse_byte_order
,size1
,evD
);
85 type
->element_number
= element_number
;
86 if(fld
->element_size
> 0){
87 size
= element_number
* fld
->element_size
;
88 }else{//sequence has string or sequence
90 for(i
=0;i
<element_number
;i
++){
91 size
+= ltt_event_refresh_fields(offsetRoot
+size
+size1
,size
+size1
,
92 fld
->child
[0], evD
+size
+size1
, reverse_byte_order
);
99 size
= strlen((gchar
*)evD
) + 1; //include end : '\0'
103 element_number
= (int) type
->element_number
;
104 if(fld
->field_fixed
== 0){
105 offset1
= offsetRoot
;
107 for(i
=0;i
<element_number
;i
++){
108 size
=ltt_event_refresh_fields(offset1
,offset2
,
109 fld
->child
[i
],evD
+offset2
, reverse_byte_order
);
114 }else size
= fld
->field_size
;
118 size
= fld
->field_size
;
122 size
= fld
->field_size
;
126 if(type
->type_class
!= LTT_STRUCT
&& type
->type_class
!= LTT_ARRAY
&&
127 type
->type_class
!= LTT_SEQUENCE
&& type
->type_class
!= LTT_STRING
){
128 size
= fld
->field_size
;
129 }else if(type
->type_class
== LTT_ARRAY
){
130 element_number
= (int) type
->element_number
;
131 if(fld
->field_fixed
== 0){// has string or sequence
133 for(i
=0;i
<element_number
;i
++){
134 size
+= ltt_event_refresh_fields(offsetRoot
+size
,size
,
135 fld
->child
[0], evD
+size
);
137 }else size
= fld
->field_size
;
138 }else if(type
->type_class
== LTT_SEQUENCE
){
139 size1
= fld
->sequ_number_size
;
140 element_number
= getIntNumber(size1
,evD
);
141 type
->element_number
= element_number
;
142 if(fld
->element_size
> 0){
143 size
= element_number
* fld
->element_size
;
144 }else{//sequence has string or sequence
146 for(i
=0;i
<element_number
;i
++){
147 size
+= ltt_event_refresh_fields(offsetRoot
+size
+size1
,size
+size1
,
148 fld
->child
[0], evD
+size
+size1
);
152 }else if(type
->type_class
== LTT_STRING
){
153 size
= strlen((char*)evD
) + 1; //include end : '\0'
154 }else if(type
->type_class
== LTT_STRUCT
){
155 element_number
= (int) type
->element_number
;
156 if(fld
->field_fixed
== 0){
157 offset1
= offsetRoot
;
159 for(i
=0;i
<element_number
;i
++){
160 size
=ltt_event_refresh_fields(offset1
,offset2
,
161 fld
->child
[i
],evD
+offset2
);
166 }else size
= fld
->field_size
;
169 fld
->offset_root
= offsetRoot
;
170 fld
->offset_parent
= offsetParent
;
171 fld
->fixed_root
= (offsetRoot
==-1) ? 0 : 1;
172 fld
->fixed_parent
= (offsetParent
==-1) ? 0 : 1;
173 fld
->field_size
= size
;
180 /*****************************************************************************
182 * ltt_event_eventtype_id: get event type id
183 * (base id + position of the event)
185 * e : an instance of an event type
187 * unsigned : event type id
188 ****************************************************************************/
190 unsigned ltt_event_eventtype_id(const LttEvent
*e
)
192 return (unsigned) e
->event_id
;
195 /*****************************************************************************
197 * ltt_event_facility : get the facility of the event
199 * e : an instance of an event type
201 * LttFacility * : the facility of the event
202 ****************************************************************************/
204 LttFacility
*ltt_event_facility(const LttEvent
*e
)
206 LttTrace
* trace
= e
->tracefile
->trace
;
207 unsigned id
= e
->facility_id
;
208 LttFacility
*facility
= ltt_trace_facility_by_id(trace
,id
);
210 g_assert(facility
->exists
);
215 /*****************************************************************************
217 * ltt_event_facility_id : get the facility id of the event
219 * e : an instance of an event type
221 * unsigned : the facility of the event
222 ****************************************************************************/
224 unsigned ltt_event_facility_id(const LttEvent
*e
)
226 return e
->facility_id
;
229 /*****************************************************************************
231 * ltt_event_eventtype : get the event type of the event
233 * e : an instance of an event type
235 * LttEventType * : the event type of the event
236 ****************************************************************************/
238 LttEventType
*ltt_event_eventtype(const LttEvent
*e
)
240 LttFacility
* facility
= ltt_event_facility(e
);
241 if(!facility
) return NULL
;
242 return &g_array_index(facility
->events
, LttEventType
, e
->event_id
);
245 /*****************************************************************************
247 * ltt_event_field : get the root field of the event
249 * e : an instance of an event type
251 * LttField * : the root field of the event
252 ****************************************************************************/
254 LttField
*ltt_event_field(LttEvent
*e
)
257 LttEventType
* event_type
= ltt_event_eventtype(e
);
258 if(unlikely(!event_type
)) return NULL
;
259 field
= event_type
->root_field
;
260 if(unlikely(!field
)) return NULL
;
262 get_field_type_size(e
->tracefile
, event_type
, 0, 0,
268 /*****************************************************************************
270 * ltt_event_time : get the time of the event
272 * e : an instance of an event type
274 * LttTime : the time of the event
275 ****************************************************************************/
277 LttTime
ltt_event_time(const LttEvent
*e
)
279 return e
->event_time
;
282 /*****************************************************************************
284 * ltt_event_time : get the cycle count of the event
286 * e : an instance of an event type
288 * LttCycleCount : the cycle count of the event
289 ****************************************************************************/
291 LttCycleCount
ltt_event_cycle_count(const LttEvent
*e
)
298 /*****************************************************************************
300 * ltt_event_position_get : get the event position data
302 * e : an instance of an event type
303 * ep : a pointer to event's position structure
304 * tf : tracefile pointer
305 * block : current block
306 * offset : current offset
308 ****************************************************************************/
309 void ltt_event_position_get(LttEventPosition
*ep
, LttTracefile
**tf
,
310 guint
*block
, guint
*offset
, guint64
*tsc
)
314 *offset
= ep
->offset
;
319 /*****************************************************************************
321 * ltt_event_position : get the event's position
323 * e : an instance of an event type
324 * ep : a pointer to event's position structure
325 ****************************************************************************/
327 void ltt_event_position(LttEvent
*e
, LttEventPosition
*ep
)
329 ep
->tracefile
= e
->tracefile
;
330 ep
->block
= e
->block
;
331 ep
->offset
= e
->offset
;
335 LttEventPosition
* ltt_event_position_new()
337 return g_new(LttEventPosition
, 1);
341 /*****************************************************************************
343 * ltt_event_position_compare : compare two positions
344 * A NULL value is infinite.
346 * ep1 : a pointer to event's position structure
347 * ep2 : a pointer to event's position structure
352 ****************************************************************************/
355 gint
ltt_event_position_compare(const LttEventPosition
*ep1
,
356 const LttEventPosition
*ep2
)
358 if(ep1
== NULL
&& ep2
== NULL
)
360 if(ep1
!= NULL
&& ep2
== NULL
)
362 if(ep1
== NULL
&& ep2
!= NULL
)
365 if(ep1
->tracefile
!= ep2
->tracefile
)
366 g_error("ltt_event_position_compare on different tracefiles makes no sense");
368 if(ep1
->block
< ep2
->block
)
370 if(ep1
->block
> ep2
->block
)
372 if(ep1
->offset
< ep2
->offset
)
374 if(ep1
->offset
> ep2
->offset
)
379 /*****************************************************************************
381 * ltt_event_position_copy : copy position
383 * src : a pointer to event's position structure source
384 * dest : a pointer to event's position structure dest
387 ****************************************************************************/
388 void ltt_event_position_copy(LttEventPosition
*dest
,
389 const LttEventPosition
*src
)
399 LttTracefile
*ltt_event_position_tracefile(LttEventPosition
*ep
)
401 return ep
->tracefile
;
404 /*****************************************************************************
406 * ltt_event_cpu_i: get the cpu id where the event happens
408 * e : an instance of an event type
410 * unsigned : the cpu id
411 ****************************************************************************/
413 unsigned ltt_event_cpu_id(LttEvent
*e
)
415 return e
->tracefile
->cpu_num
;
418 /*****************************************************************************
420 * ltt_event_data : get the raw data for the event
422 * e : an instance of an event type
424 * void * : pointer to the raw data for the event
425 ****************************************************************************/
427 void *ltt_event_data(LttEvent
*e
)
432 /*****************************************************************************
434 * ltt_event_field_element_number
435 * : The number of elements in a sequence field is specific
436 * to each event. This function returns the number of
437 * elements for an array or sequence field in an event.
439 * e : an instance of an event type
440 * f : a field of the instance
442 * unsigned : the number of elements for an array/sequence field
443 ****************************************************************************/
444 guint64
ltt_event_field_element_number(LttEvent
*e
, LttField
*f
)
446 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
447 f
->field_type
->type_class
!= LTT_SEQUENCE
)
450 if(f
->field_type
->type_class
== LTT_ARRAY
)
451 return f
->field_type
->element_number
;
452 return ltt_get_uint(LTT_GET_BO(e
->tracefile
), f
->sequ_number_size
,
456 /*****************************************************************************
458 * ltt_event_field_element_select
459 * : Set the currently selected element for a sequence or
461 * O(1) if fields are of fixed size, else O(n) if fields are
464 * e : an instance of an event type
465 * f : a field of the instance
466 * i : the ith element (0, ...)
467 ****************************************************************************/
468 void ltt_event_field_element_select(LttEvent
*e
, LttField
*f
, unsigned i
)
470 unsigned element_number
;
474 LttEventType
*event_type
;
476 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
477 f
->field_type
->type_class
!= LTT_SEQUENCE
)
480 element_number
= ltt_event_field_element_number(e
,f
);
481 event_type
= ltt_event_eventtype(e
);
482 /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number
484 if(i
>= element_number
) return;
488 if(f
->field_type
->type_class
== LTT_SEQUENCE
)
489 size
= f
->sequ_number_size
;
493 if(field
->fixed_size
== FIELD_FIXED
) {
494 size
+= field
->field_size
* i
;
496 get_field_type_size(e
->tracefile
, event_type
,
497 f
->offset_root
+size
, size
, field
, e
->data
);
501 size
+= get_field_type_size(e
->tracefile
, event_type
,
502 f
->offset_root
+size
, size
, field
, e
->data
);
505 f
->current_element
= i
;
508 /*****************************************************************************
509 * These functions extract data from an event after architecture specific
511 ****************************************************************************/
512 guint32
ltt_event_get_unsigned(LttEvent
*e
, LttField
*f
)
514 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
516 LttTypeEnum t
= f
->field_type
->type_class
;
518 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
520 if(f
->field_size
== 1){
521 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
523 }else if(f
->field_size
== 2){
524 return (guint32
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
525 }else if(f
->field_size
== 4){
526 return (guint32
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
529 else if(f
->field_size
== 8){
530 guint64 x
= *(guint64
*)(e
->data
+ f
->offset_root
);
531 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
532 return (unsigned int) (revFlag
? GUINT64_FROM_BE(x
): x
);
534 return (unsigned int) (revFlag
? GUINT64_FROM_LE(x
): x
);
537 g_critical("ltt_event_get_unsigned : field size %i unknown", f
->field_size
);
541 gint32
ltt_event_get_int(LttEvent
*e
, LttField
*f
)
543 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
545 g_assert(f
->field_type
->type_class
== LTT_INT
);
547 if(f
->field_size
== 1){
548 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
550 }else if(f
->field_size
== 2){
551 return (gint32
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
552 }else if(f
->field_size
== 4){
553 return (gint32
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
556 else if(f
->field_size
== 8){
557 gint64 x
= *(gint64
*)(e
->data
+ f
->offset_root
);
558 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
559 return (int) (revFlag
? GINT64_FROM_BE(x
): x
);
561 return (int) (revFlag
? GINT64_FROM_LE(x
): x
);
564 g_critical("ltt_event_get_int : field size %i unknown", f
->field_size
);
568 guint64
ltt_event_get_long_unsigned(LttEvent
*e
, LttField
*f
)
570 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
572 LttTypeEnum t
= f
->field_type
->type_class
;
574 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
575 || t
== LTT_ULONG
|| LTT_SIZE_T
|| LTT_OFF_T
|| LTT_POINTER
);
577 if(f
->field_size
== 1){
578 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
580 }else if(f
->field_size
== 2){
581 return (guint64
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
582 }else if(f
->field_size
== 4){
583 return (guint64
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
584 }else if(f
->field_size
== 8){
585 return ltt_get_uint64(reverse_byte_order
, e
->data
+ f
->offset_root
);
587 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f
->field_size
);
591 gint64
ltt_event_get_long_int(LttEvent
*e
, LttField
*f
)
593 //int revFlag = e->tracefile->trace->my_arch_endian ==
594 // e->tracefile->trace->system_description->endian ? 0:1;
595 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
597 g_assert( f
->field_type
->type_class
== LTT_INT
598 || f
->field_type
->type_class
== LTT_LONG
599 || f
->field_type
->type_class
== LTT_SSIZE_T
);
601 if(f
->field_size
== 1){
602 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
604 }else if(f
->field_size
== 2){
605 return (gint64
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
606 }else if(f
->field_size
== 4){
607 return (gint64
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
608 }else if(f
->field_size
== 8){
609 return ltt_get_int64(reverse_byte_order
, e
->data
+ f
->offset_root
);
611 g_critical("ltt_event_get_long_int : field size %i unknown", f
->field_size
);
615 float ltt_event_get_float(LttEvent
*e
, LttField
*f
)
617 g_assert(LTT_HAS_FLOAT(e
->tracefile
));
618 gboolean reverse_byte_order
= LTT_GET_FLOAT_BO(e
->tracefile
);
620 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 4);
622 if(reverse_byte_order
== 0) return *(float *)(e
->data
+ f
->offset_root
);
624 void *ptr
= e
->data
+ f
->offset_root
;
625 guint32 value
= bswap_32(*(guint32
*)ptr
);
626 return *(float*)&value
;
630 double ltt_event_get_double(LttEvent
*e
, LttField
*f
)
632 g_assert(LTT_HAS_FLOAT(e
->tracefile
));
633 gboolean reverse_byte_order
= LTT_GET_FLOAT_BO(e
->tracefile
);
635 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 8);
637 if(reverse_byte_order
== 0) return *(double *)(e
->data
+ f
->offset_root
);
639 void *ptr
= e
->data
+ f
->offset_root
;
640 guint64 value
= bswap_64(*(guint64
*)ptr
);
641 return *(double*)&value
;
645 /*****************************************************************************
646 * The string obtained is only valid until the next read from
647 * the same tracefile.
648 ****************************************************************************/
649 char *ltt_event_get_string(LttEvent
*e
, LttField
*f
)
651 g_assert(f
->field_type
->type_class
== LTT_STRING
);
653 return (gchar
*)g_strdup((gchar
*)(e
->data
+ f
->offset_root
));
657 /*****************************************************************************
659 * get_field_type_size : set the fixed and dynamic sizes of the field type
660 * from the data read.
663 * event_type : event type
664 * offset_root : offset from the root
665 * offset_parent : offset from the parent
667 * data : a pointer to the event data.
668 *Returns the field type size.
669 ****************************************************************************/
670 size_t get_field_type_size(LttTracefile
*tf
, LttEventType
*event_type
,
671 off_t offset_root
, off_t offset_parent
,
672 LttField
*field
, void *data
)
678 g_assert(field
->fixed_root
!= FIELD_UNKNOWN
);
679 g_assert(field
->fixed_parent
!= FIELD_UNKNOWN
);
680 g_assert(field
->fixed_size
!= FIELD_UNKNOWN
);
682 field
->offset_root
= offset_root
;
683 field
->offset_parent
= offset_parent
;
685 type
= field
->field_type
;
687 switch(type
->type_class
) {
698 g_assert(field
->fixed_size
== FIELD_FIXED
);
699 size
= field
->field_size
;
703 gint seqnum
= ltt_get_uint(LTT_GET_BO(tf
),
704 field
->sequ_number_size
,
707 if(field
->child
[0]->fixed_size
== FIELD_FIXED
) {
708 size
= field
->sequ_number_size
+
709 (seqnum
* get_field_type_size(tf
, event_type
,
710 offset_root
, offset_parent
,
711 field
->child
[0], data
));
713 size
+= field
->sequ_number_size
;
714 for(i
=0;i
<seqnum
;i
++) {
716 child_size
= get_field_type_size(tf
, event_type
,
717 offset_root
, offset_parent
,
718 field
->child
[0], data
);
719 offset_root
+= child_size
;
720 offset_parent
+= child_size
;
724 field
->field_size
= size
;
728 size
= strlen((char*)(data
+offset_root
)) + 1;// length + \0
729 field
->field_size
= size
;
732 if(field
->fixed_size
== FIELD_FIXED
)
733 size
= field
->field_size
;
735 for(i
=0;i
<field
->field_type
->element_number
;i
++) {
737 child_size
= get_field_type_size(tf
, event_type
,
738 offset_root
, offset_parent
,
739 field
->child
[0], data
);
740 offset_root
+= child_size
;
741 offset_parent
+= child_size
;
744 field
->field_size
= size
;
748 if(field
->fixed_size
== FIELD_FIXED
)
749 size
= field
->field_size
;
751 size_t current_root_offset
= offset_root
;
752 size_t current_offset
= 0;
753 size_t child_size
= 0;
754 for(i
=0;i
<type
->element_number
;i
++) {
755 child_size
= get_field_type_size(tf
,
756 event_type
, current_root_offset
, current_offset
,
757 field
->child
[i
], data
);
758 current_offset
+= child_size
;
759 current_root_offset
+= child_size
;
762 size
= current_offset
;
763 field
->field_size
= size
;
767 if(field
->fixed_size
== FIELD_FIXED
)
768 size
= field
->field_size
;
770 size_t current_root_offset
= field
->offset_root
;
771 size_t current_offset
= 0;
772 for(i
=0;i
<type
->element_number
;i
++) {
773 size
= get_field_type_size(tf
, event_type
,
774 current_root_offset
, current_offset
,
775 field
->child
[i
], data
);
776 size
= max(size
, field
->child
[i
]->field_size
);
778 field
->field_size
= size
;