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>
29 #include <linux/byteorder/swab.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
->event_id
;
208 return ltt_trace_facility_by_id(trace
,id
);
211 /*****************************************************************************
213 * ltt_event_facility_id : get the facility id of the event
215 * e : an instance of an event type
217 * unsigned : the facility of the event
218 ****************************************************************************/
220 unsigned ltt_event_facility_id(const LttEvent
*e
)
222 return e
->facility_id
;
225 /*****************************************************************************
227 * ltt_event_eventtype : get the event type of the event
229 * e : an instance of an event type
231 * LttEventType * : the event type of the event
232 ****************************************************************************/
234 LttEventType
*ltt_event_eventtype(const LttEvent
*e
)
236 LttFacility
* facility
= ltt_event_facility(e
);
237 if(!facility
) return NULL
;
238 return &g_array_index(facility
->events
, LttEventType
, e
->event_id
);
241 /*****************************************************************************
243 * ltt_event_field : get the root field of the event
245 * e : an instance of an event type
247 * LttField * : the root field of the event
248 ****************************************************************************/
250 LttField
*ltt_event_field(LttEvent
*e
)
253 LttEventType
* event_type
= ltt_event_eventtype(e
);
254 if(unlikely(!event_type
)) return NULL
;
255 field
= event_type
->root_field
;
256 if(unlikely(!field
)) return NULL
;
258 get_field_type_size(e
->tracefile
, event_type
, 0, 0,
264 /*****************************************************************************
266 * ltt_event_time : get the time of the event
268 * e : an instance of an event type
270 * LttTime : the time of the event
271 ****************************************************************************/
273 LttTime
ltt_event_time(const LttEvent
*e
)
275 return e
->event_time
;
278 /*****************************************************************************
280 * ltt_event_time : get the cycle count of the event
282 * e : an instance of an event type
284 * LttCycleCount : the cycle count of the event
285 ****************************************************************************/
287 LttCycleCount
ltt_event_cycle_count(const LttEvent
*e
)
294 /*****************************************************************************
296 * ltt_event_position_get : get the event position data
298 * e : an instance of an event type
299 * ep : a pointer to event's position structure
300 * tf : tracefile pointer
301 * block : current block
302 * offset : current offset
304 ****************************************************************************/
305 void ltt_event_position_get(LttEventPosition
*ep
, LttTracefile
**tf
,
306 guint
*block
, guint
*offset
, guint64
*tsc
)
310 *offset
= ep
->offset
;
315 /*****************************************************************************
317 * ltt_event_position : get the event's position
319 * e : an instance of an event type
320 * ep : a pointer to event's position structure
321 ****************************************************************************/
323 void ltt_event_position(LttEvent
*e
, LttEventPosition
*ep
)
325 ep
->tracefile
= e
->tracefile
;
326 ep
->block
= e
->block
;
327 ep
->offset
= e
->offset
;
331 LttEventPosition
* ltt_event_position_new()
333 return g_new(LttEventPosition
, 1);
337 /*****************************************************************************
339 * ltt_event_position_compare : compare two positions
340 * A NULL value is infinite.
342 * ep1 : a pointer to event's position structure
343 * ep2 : a pointer to event's position structure
348 ****************************************************************************/
351 gint
ltt_event_position_compare(const LttEventPosition
*ep1
,
352 const LttEventPosition
*ep2
)
354 if(ep1
== NULL
&& ep2
== NULL
)
356 if(ep1
!= NULL
&& ep2
== NULL
)
358 if(ep1
== NULL
&& ep2
!= NULL
)
361 if(ep1
->tracefile
!= ep2
->tracefile
)
362 g_error("ltt_event_position_compare on different tracefiles makes no sense");
364 if(ep1
->block
< ep2
->block
)
366 if(ep1
->block
> ep2
->block
)
368 if(ep1
->offset
< ep2
->offset
)
370 if(ep1
->offset
> ep2
->offset
)
375 /*****************************************************************************
377 * ltt_event_position_copy : copy position
379 * src : a pointer to event's position structure source
380 * dest : a pointer to event's position structure dest
383 ****************************************************************************/
384 void ltt_event_position_copy(LttEventPosition
*dest
,
385 const LttEventPosition
*src
)
394 /*****************************************************************************
396 * ltt_event_cpu_i: get the cpu id where the event happens
398 * e : an instance of an event type
400 * unsigned : the cpu id
401 ****************************************************************************/
403 unsigned ltt_event_cpu_id(LttEvent
*e
)
405 return e
->tracefile
->cpu_num
;
408 /*****************************************************************************
410 * ltt_event_data : get the raw data for the event
412 * e : an instance of an event type
414 * void * : pointer to the raw data for the event
415 ****************************************************************************/
417 void *ltt_event_data(LttEvent
*e
)
422 /*****************************************************************************
424 * ltt_event_field_element_number
425 * : The number of elements in a sequence field is specific
426 * to each event. This function returns the number of
427 * elements for an array or sequence field in an event.
429 * e : an instance of an event type
430 * f : a field of the instance
432 * unsigned : the number of elements for an array/sequence field
433 ****************************************************************************/
434 guint64
ltt_event_field_element_number(LttEvent
*e
, LttField
*f
)
436 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
437 f
->field_type
->type_class
!= LTT_SEQUENCE
)
440 if(f
->field_type
->type_class
== LTT_ARRAY
)
441 return f
->field_type
->element_number
;
442 return ltt_get_uint(LTT_GET_BO(e
->tracefile
), f
->sequ_number_size
,
446 /*****************************************************************************
448 * ltt_event_field_element_select
449 * : Set the currently selected element for a sequence or
451 * O(1) if fields are of fixed size, else O(n) if fields are
454 * e : an instance of an event type
455 * f : a field of the instance
456 * i : the ith element (0, ...)
457 ****************************************************************************/
458 void ltt_event_field_element_select(LttEvent
*e
, LttField
*f
, unsigned i
)
460 unsigned element_number
;
464 LttEventType
*event_type
;
466 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
467 f
->field_type
->type_class
!= LTT_SEQUENCE
)
470 element_number
= ltt_event_field_element_number(e
,f
);
471 event_type
= ltt_event_eventtype(e
);
472 /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number
474 if(i
>= element_number
) return;
478 if(f
->field_type
->type_class
== LTT_SEQUENCE
)
479 size
= f
->sequ_number_size
;
483 if(field
->fixed_size
== FIELD_FIXED
) {
484 size
+= field
->field_size
* i
;
486 get_field_type_size(e
->tracefile
, event_type
,
487 f
->offset_root
+size
, size
, field
, e
->data
);
491 size
+= get_field_type_size(e
->tracefile
, event_type
,
492 f
->offset_root
+size
, size
, field
, e
->data
);
495 f
->current_element
= i
;
498 /*****************************************************************************
499 * These functions extract data from an event after architecture specific
501 ****************************************************************************/
502 guint32
ltt_event_get_unsigned(LttEvent
*e
, LttField
*f
)
504 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
506 LttTypeEnum t
= f
->field_type
->type_class
;
508 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
510 if(f
->field_size
== 1){
511 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
513 }else if(f
->field_size
== 2){
514 return (guint32
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
515 }else if(f
->field_size
== 4){
516 return (guint32
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
519 else if(f
->field_size
== 8){
520 guint64 x
= *(guint64
*)(e
->data
+ f
->offset_root
);
521 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
522 return (unsigned int) (revFlag
? GUINT64_FROM_BE(x
): x
);
524 return (unsigned int) (revFlag
? GUINT64_FROM_LE(x
): x
);
527 g_critical("ltt_event_get_unsigned : field size %i unknown", f
->field_size
);
531 gint32
ltt_event_get_int(LttEvent
*e
, LttField
*f
)
533 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
535 g_assert(f
->field_type
->type_class
== LTT_INT
);
537 if(f
->field_size
== 1){
538 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
540 }else if(f
->field_size
== 2){
541 return (gint32
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
542 }else if(f
->field_size
== 4){
543 return (gint32
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
546 else if(f
->field_size
== 8){
547 gint64 x
= *(gint64
*)(e
->data
+ f
->offset_root
);
548 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
549 return (int) (revFlag
? GINT64_FROM_BE(x
): x
);
551 return (int) (revFlag
? GINT64_FROM_LE(x
): x
);
554 g_critical("ltt_event_get_int : field size %i unknown", f
->field_size
);
558 guint64
ltt_event_get_long_unsigned(LttEvent
*e
, LttField
*f
)
560 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
562 LttTypeEnum t
= f
->field_type
->type_class
;
564 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
566 if(f
->field_size
== 1){
567 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
569 }else if(f
->field_size
== 2){
570 return (guint64
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
571 }else if(f
->field_size
== 4){
572 return (guint64
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
573 }else if(f
->field_size
== 8){
574 return ltt_get_uint64(reverse_byte_order
, e
->data
+ f
->offset_root
);
576 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f
->field_size
);
580 gint64
ltt_event_get_long_int(LttEvent
*e
, LttField
*f
)
582 //int revFlag = e->tracefile->trace->my_arch_endian ==
583 // e->tracefile->trace->system_description->endian ? 0:1;
584 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
586 g_assert( f
->field_type
->type_class
== LTT_INT
);
588 if(f
->field_size
== 1){
589 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
591 }else if(f
->field_size
== 2){
592 return (gint64
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
593 }else if(f
->field_size
== 4){
594 return (gint64
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
595 }else if(f
->field_size
== 8){
596 return ltt_get_int64(reverse_byte_order
, e
->data
+ f
->offset_root
);
598 g_critical("ltt_event_get_long_int : field size %i unknown", f
->field_size
);
602 float ltt_event_get_float(LttEvent
*e
, LttField
*f
)
604 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
606 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 4);
608 if(reverse_byte_order
== 0) return *(float *)(e
->data
+ f
->offset_root
);
611 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 4);
612 aInt
= ___swab32(aInt
);
613 return ((float)aInt
);
617 double ltt_event_get_double(LttEvent
*e
, LttField
*f
)
619 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
621 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 8);
623 if(reverse_byte_order
== 0) return *(double *)(e
->data
+ f
->offset_root
);
626 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 8);
627 aInt
= ___swab64(aInt
);
628 return ((double)aInt
);
632 /*****************************************************************************
633 * The string obtained is only valid until the next read from
634 * the same tracefile.
635 ****************************************************************************/
636 char *ltt_event_get_string(LttEvent
*e
, LttField
*f
)
638 g_assert(f
->field_type
->type_class
== LTT_STRING
);
640 return (gchar
*)g_strdup((gchar
*)(e
->data
+ f
->offset_root
));
644 /*****************************************************************************
646 * get_field_type_size : set the fixed and dynamic sizes of the field type
647 * from the data read.
650 * event_type : event type
651 * offset_root : offset from the root
652 * offset_parent : offset from the parent
654 * data : a pointer to the event data.
655 *Returns the field type size.
656 ****************************************************************************/
657 size_t get_field_type_size(LttTracefile
*tf
, LttEventType
*event_type
,
658 off_t offset_root
, off_t offset_parent
,
659 LttField
*field
, void *data
)
665 g_assert(field
->fixed_root
!= FIELD_UNKNOWN
);
666 g_assert(field
->fixed_parent
!= FIELD_UNKNOWN
);
667 g_assert(field
->fixed_size
!= FIELD_UNKNOWN
);
669 field
->offset_root
= offset_root
;
670 field
->offset_parent
= offset_parent
;
672 type
= field
->field_type
;
674 switch(type
->type_class
) {
685 g_assert(field
->fixed_size
== FIELD_FIXED
);
686 size
= field
->field_size
;
690 gint seqnum
= ltt_get_uint(LTT_GET_BO(tf
),
691 field
->sequ_number_size
,
694 if(field
->child
[0]->fixed_size
== FIELD_FIXED
) {
695 size
= field
->sequ_number_size
+
696 (seqnum
* get_field_type_size(tf
, event_type
,
697 offset_root
, offset_parent
,
698 field
->child
[0], data
));
700 size
+= field
->sequ_number_size
;
701 for(i
=0;i
<seqnum
;i
++) {
703 child_size
= get_field_type_size(tf
, event_type
,
704 offset_root
, offset_parent
,
705 field
->child
[0], data
);
706 offset_root
+= child_size
;
707 offset_parent
+= child_size
;
711 field
->field_size
= size
;
715 size
= strlen((char*)(data
+offset_root
)) + 1;// length + \0
716 field
->field_size
= size
;
719 if(field
->fixed_size
== FIELD_FIXED
)
720 size
= field
->field_size
;
722 for(i
=0;i
<field
->field_type
->element_number
;i
++) {
724 child_size
= get_field_type_size(tf
, event_type
,
725 offset_root
, offset_parent
,
726 field
->child
[0], data
);
727 offset_root
+= child_size
;
728 offset_parent
+= child_size
;
731 field
->field_size
= size
;
735 if(field
->fixed_size
== FIELD_FIXED
)
736 size
= field
->field_size
;
738 size_t current_root_offset
= offset_root
;
739 size_t current_offset
= 0;
740 size_t child_size
= 0;
741 for(i
=0;i
<type
->element_number
;i
++) {
742 child_size
= get_field_type_size(tf
,
743 event_type
, current_root_offset
, current_offset
,
744 field
->child
[i
], data
);
745 current_offset
+= child_size
;
746 current_root_offset
+= child_size
;
749 size
= current_offset
;
750 field
->field_size
= size
;
754 if(field
->fixed_size
== FIELD_FIXED
)
755 size
= field
->field_size
;
757 size_t current_root_offset
= field
->offset_root
;
758 size_t current_offset
= 0;
759 for(i
=0;i
<type
->element_number
;i
++) {
760 size
= get_field_type_size(tf
, event_type
,
761 current_root_offset
, current_offset
,
762 field
->child
[i
], data
);
763 size
= max(size
, field
->child
[i
]->field_size
);
765 field
->field_size
= size
;