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,
27 #include <asm/types.h>
28 #include <linux/byteorder/swab.h>
32 #include "ltt-private.h"
33 #include <ltt/event.h>
34 #include <ltt/trace.h>
35 #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(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(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_eventtype : get the event type of the event
215 * e : an instance of an event type
217 * LttEventType * : the event type of the event
218 ****************************************************************************/
220 LttEventType
*ltt_event_eventtype(LttEvent
*e
)
222 LttFacility
* facility
= ltt_event_facility(e
);
223 if(!facility
) return NULL
;
224 return &g_array_index(facility
->events
, LttEventType
, e
->event_id
);
227 /*****************************************************************************
229 * ltt_event_field : get the root field of the event
231 * e : an instance of an event type
233 * LttField * : the root field of the event
234 ****************************************************************************/
236 LttField
*ltt_event_field(LttEvent
*e
)
239 LttEventType
* event_type
= ltt_event_eventtype(e
);
240 if(unlikely(!event_type
)) return NULL
;
241 field
= event_type
->root_field
;
242 if(unlikely(!field
)) return NULL
;
247 /*****************************************************************************
249 * ltt_event_time : get the time of the event
251 * e : an instance of an event type
253 * LttTime : the time of the event
254 ****************************************************************************/
256 LttTime
ltt_event_time(LttEvent
*e
)
258 return e
->event_time
;
261 /*****************************************************************************
263 * ltt_event_time : get the cycle count of the event
265 * e : an instance of an event type
267 * LttCycleCount : the cycle count of the event
268 ****************************************************************************/
270 LttCycleCount
ltt_event_cycle_count(LttEvent
*e
)
275 /*****************************************************************************
277 * ltt_event_position : get the event's position
279 * e : an instance of an event type
280 * ep : a pointer to event's position structure
281 ****************************************************************************/
283 void ltt_event_position(LttEvent
*e
, LttEventPosition
*ep
)
285 ep
->tracefile
= e
->tracefile
;
286 ep
->block
= e
->block
;
287 ep
->offset
= e
->offset
;
291 LttEventPosition
* ltt_event_position_new()
293 return g_new(LttEventPosition
, 1);
297 /*****************************************************************************
299 * ltt_event_position_compare : compare two positions
300 * A NULL value is infinite.
302 * ep1 : a pointer to event's position structure
303 * ep2 : a pointer to event's position structure
308 ****************************************************************************/
311 gint
ltt_event_position_compare(const LttEventPosition
*ep1
,
312 const LttEventPosition
*ep2
)
314 if(ep1
== NULL
&& ep2
== NULL
)
316 if(ep1
!= NULL
&& ep2
== NULL
)
318 if(ep1
== NULL
&& ep2
!= NULL
)
321 if(ep1
->tracefile
!= ep2
->tracefile
)
322 g_error("ltt_event_position_compare on different tracefiles makes no sense");
324 if(ep1
->block
< ep2
->block
)
326 if(ep1
->block
> ep2
->block
)
328 if(ep1
->offset
< ep2
->offset
)
330 if(ep1
->offset
> ep2
->offset
)
335 /*****************************************************************************
337 * ltt_event_position_copy : copy position
339 * src : a pointer to event's position structure source
340 * dest : a pointer to event's position structure dest
343 ****************************************************************************/
344 void ltt_event_position_copy(LttEventPosition
*dest
,
345 const LttEventPosition
*src
)
354 /*****************************************************************************
356 * ltt_event_cpu_i: get the cpu id where the event happens
358 * e : an instance of an event type
360 * unsigned : the cpu id
361 ****************************************************************************/
363 unsigned ltt_event_cpu_id(LttEvent
*e
)
365 return e
->tracefile
->cpu_num
;
368 /*****************************************************************************
370 * ltt_event_data : get the raw data for the event
372 * e : an instance of an event type
374 * void * : pointer to the raw data for the event
375 ****************************************************************************/
377 void *ltt_event_data(LttEvent
*e
)
382 /*****************************************************************************
384 * ltt_event_field_element_number
385 * : The number of elements in a sequence field is specific
386 * to each event. This function returns the number of
387 * elements for an array or sequence field in an event.
389 * e : an instance of an event type
390 * f : a field of the instance
392 * unsigned : the number of elements for an array/sequence field
393 ****************************************************************************/
394 unsigned ltt_event_field_element_number(LttEvent
*e
, LttField
*f
)
396 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
397 f
->field_type
->type_class
!= LTT_SEQUENCE
)
400 if(f
->field_type
->type_class
== LTT_ARRAY
)
401 return f
->field_type
->element_number
;
402 return (unsigned) get_unsigned(LTT_GET_BO(e
->tracefile
),
403 f
->sequ_number_size
, e
+ f
->offset_root
);
406 /*****************************************************************************
408 * ltt_event_field_element_select
409 * : Set the currently selected element for a sequence or
412 * e : an instance of an event type
413 * f : a field of the instance
414 * i : the ith element
415 ****************************************************************************/
416 void ltt_event_field_element_select(LttEvent
*e
, LttField
*f
, unsigned i
)
418 unsigned element_number
;
424 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
425 f
->field_type
->type_class
!= LTT_SEQUENCE
)
428 element_number
= ltt_event_field_element_number(e
,f
);
429 /* Sanity check for i : 1..n only, and must be lower or equal element_number
431 if(element_number
< i
|| i
== 0) return;
435 data
= e
->data
+ f
->offset_root
;
438 size
+= ltt_event_refresh_fields(f
->offset_root
+size
,size
, fld
, evD
+size
,
439 LTT_GET_BO(e
->tracefile
));
441 f
->current_element
= i
- 1;
444 /*****************************************************************************
445 * These functions extract data from an event after architecture specific
447 ****************************************************************************/
448 guint32
ltt_event_get_unsigned(LttEvent
*e
, LttField
*f
)
450 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
452 LttTypeEnum t
= f
->field_type
->type_class
;
454 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
456 if(f
->field_size
== 1){
457 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
459 }else if(f
->field_size
== 2){
460 return (guint32
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
461 }else if(f
->field_size
== 4){
462 return (guint32
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
465 else if(f
->field_size
== 8){
466 guint64 x
= *(guint64
*)(e
->data
+ f
->offset_root
);
467 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
468 return (unsigned int) (revFlag
? GUINT64_FROM_BE(x
): x
);
470 return (unsigned int) (revFlag
? GUINT64_FROM_LE(x
): x
);
473 g_critical("ltt_event_get_unsigned : field size %i unknown", f
->field_size
);
477 gint32
ltt_event_get_int(LttEvent
*e
, LttField
*f
)
479 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
481 g_assert(f
->field_type
->type_class
== LTT_INT
);
483 if(f
->field_size
== 1){
484 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
486 }else if(f
->field_size
== 2){
487 return (gint32
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
488 }else if(f
->field_size
== 4){
489 return (gint32
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
492 else if(f
->field_size
== 8){
493 gint64 x
= *(gint64
*)(e
->data
+ f
->offset_root
);
494 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
495 return (int) (revFlag
? GINT64_FROM_BE(x
): x
);
497 return (int) (revFlag
? GINT64_FROM_LE(x
): x
);
500 g_critical("ltt_event_get_int : field size %i unknown", f
->field_size
);
504 guint64
ltt_event_get_long_unsigned(LttEvent
*e
, LttField
*f
)
506 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
508 LttTypeEnum t
= f
->field_type
->type_class
;
510 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
512 if(f
->field_size
== 1){
513 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
515 }else if(f
->field_size
== 2){
516 return (guint64
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
517 }else if(f
->field_size
== 4){
518 return (guint64
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
519 }else if(f
->field_size
== 8){
520 return ltt_get_uint64(reverse_byte_order
, e
->data
+ f
->offset_root
);
522 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f
->field_size
);
526 gint64
ltt_event_get_long_int(LttEvent
*e
, LttField
*f
)
528 //int revFlag = e->tracefile->trace->my_arch_endian ==
529 // e->tracefile->trace->system_description->endian ? 0:1;
530 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
532 g_assert( f
->field_type
->type_class
== LTT_INT
);
534 if(f
->field_size
== 1){
535 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
537 }else if(f
->field_size
== 2){
538 return (gint64
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
539 }else if(f
->field_size
== 4){
540 return (gint64
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
541 }else if(f
->field_size
== 8){
542 return ltt_get_int64(reverse_byte_order
, e
->data
+ f
->offset_root
);
544 g_critical("ltt_event_get_long_int : field size %i unknown", f
->field_size
);
548 float ltt_event_get_float(LttEvent
*e
, LttField
*f
)
550 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
552 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 4);
554 if(reverse_byte_order
== 0) return *(float *)(e
->data
+ f
->offset_root
);
557 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 4);
558 aInt
= ___swab32(aInt
);
559 return ((float)aInt
);
563 double ltt_event_get_double(LttEvent
*e
, LttField
*f
)
565 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
567 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 8);
569 if(reverse_byte_order
== 0) return *(double *)(e
->data
+ f
->offset_root
);
572 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 8);
573 aInt
= ___swab64(aInt
);
574 return ((double)aInt
);
578 /*****************************************************************************
579 * The string obtained is only valid until the next read from
580 * the same tracefile.
581 ****************************************************************************/
582 char *ltt_event_get_string(LttEvent
*e
, LttField
*f
)
584 g_assert(f
->field_type
->type_class
== LTT_STRING
);
586 return (gchar
*)g_strdup((gchar
*)(e
->data
+ f
->offset_root
));