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
;
244 get_field_type_size(e
->tracefile
, event_type
, 0, 0,
250 /*****************************************************************************
252 * ltt_event_time : get the time of the event
254 * e : an instance of an event type
256 * LttTime : the time of the event
257 ****************************************************************************/
259 LttTime
ltt_event_time(LttEvent
*e
)
261 return e
->event_time
;
264 /*****************************************************************************
266 * ltt_event_time : get the cycle count of the event
268 * e : an instance of an event type
270 * LttCycleCount : the cycle count of the event
271 ****************************************************************************/
273 LttCycleCount
ltt_event_cycle_count(LttEvent
*e
)
278 /*****************************************************************************
280 * ltt_event_position : get the event's position
282 * e : an instance of an event type
283 * ep : a pointer to event's position structure
284 ****************************************************************************/
286 void ltt_event_position(LttEvent
*e
, LttEventPosition
*ep
)
288 ep
->tracefile
= e
->tracefile
;
289 ep
->block
= e
->block
;
290 ep
->offset
= e
->offset
;
294 LttEventPosition
* ltt_event_position_new()
296 return g_new(LttEventPosition
, 1);
300 /*****************************************************************************
302 * ltt_event_position_compare : compare two positions
303 * A NULL value is infinite.
305 * ep1 : a pointer to event's position structure
306 * ep2 : a pointer to event's position structure
311 ****************************************************************************/
314 gint
ltt_event_position_compare(const LttEventPosition
*ep1
,
315 const LttEventPosition
*ep2
)
317 if(ep1
== NULL
&& ep2
== NULL
)
319 if(ep1
!= NULL
&& ep2
== NULL
)
321 if(ep1
== NULL
&& ep2
!= NULL
)
324 if(ep1
->tracefile
!= ep2
->tracefile
)
325 g_error("ltt_event_position_compare on different tracefiles makes no sense");
327 if(ep1
->block
< ep2
->block
)
329 if(ep1
->block
> ep2
->block
)
331 if(ep1
->offset
< ep2
->offset
)
333 if(ep1
->offset
> ep2
->offset
)
338 /*****************************************************************************
340 * ltt_event_position_copy : copy position
342 * src : a pointer to event's position structure source
343 * dest : a pointer to event's position structure dest
346 ****************************************************************************/
347 void ltt_event_position_copy(LttEventPosition
*dest
,
348 const LttEventPosition
*src
)
357 /*****************************************************************************
359 * ltt_event_cpu_i: get the cpu id where the event happens
361 * e : an instance of an event type
363 * unsigned : the cpu id
364 ****************************************************************************/
366 unsigned ltt_event_cpu_id(LttEvent
*e
)
368 return e
->tracefile
->cpu_num
;
371 /*****************************************************************************
373 * ltt_event_data : get the raw data for the event
375 * e : an instance of an event type
377 * void * : pointer to the raw data for the event
378 ****************************************************************************/
380 void *ltt_event_data(LttEvent
*e
)
385 /*****************************************************************************
387 * ltt_event_field_element_number
388 * : The number of elements in a sequence field is specific
389 * to each event. This function returns the number of
390 * elements for an array or sequence field in an event.
392 * e : an instance of an event type
393 * f : a field of the instance
395 * unsigned : the number of elements for an array/sequence field
396 ****************************************************************************/
397 guint64
ltt_event_field_element_number(LttEvent
*e
, LttField
*f
)
399 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
400 f
->field_type
->type_class
!= LTT_SEQUENCE
)
403 if(f
->field_type
->type_class
== LTT_ARRAY
)
404 return f
->field_type
->element_number
;
405 return get_unsigned(LTT_GET_BO(e
->tracefile
), f
->sequ_number_size
,
409 /*****************************************************************************
411 * ltt_event_field_element_select
412 * : Set the currently selected element for a sequence or
415 * e : an instance of an event type
416 * f : a field of the instance
417 * i : the ith element (0, ...)
418 ****************************************************************************/
419 void ltt_event_field_element_select(LttEvent
*e
, LttField
*f
, unsigned i
)
421 unsigned element_number
;
426 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
427 f
->field_type
->type_class
!= LTT_SEQUENCE
)
430 element_number
= ltt_event_field_element_number(e
,f
);
431 /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number
433 if(i
>= element_number
) return;
437 if(f
->field_type
->type_class
== LTT_SEQUENCE
)
438 size
= f
->sequ_number_size
;
443 size
+= get_field_type_size(e
->tracefile
, event_type
,
444 f
->offset_root
+size
, size
, field
, e
->data
);
446 f
->current_element
= i
;
449 /*****************************************************************************
450 * These functions extract data from an event after architecture specific
452 ****************************************************************************/
453 guint32
ltt_event_get_unsigned(LttEvent
*e
, LttField
*f
)
455 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
457 LttTypeEnum t
= f
->field_type
->type_class
;
459 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
461 if(f
->field_size
== 1){
462 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
464 }else if(f
->field_size
== 2){
465 return (guint32
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
466 }else if(f
->field_size
== 4){
467 return (guint32
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
470 else if(f
->field_size
== 8){
471 guint64 x
= *(guint64
*)(e
->data
+ f
->offset_root
);
472 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
473 return (unsigned int) (revFlag
? GUINT64_FROM_BE(x
): x
);
475 return (unsigned int) (revFlag
? GUINT64_FROM_LE(x
): x
);
478 g_critical("ltt_event_get_unsigned : field size %i unknown", f
->field_size
);
482 gint32
ltt_event_get_int(LttEvent
*e
, LttField
*f
)
484 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
486 g_assert(f
->field_type
->type_class
== LTT_INT
);
488 if(f
->field_size
== 1){
489 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
491 }else if(f
->field_size
== 2){
492 return (gint32
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
493 }else if(f
->field_size
== 4){
494 return (gint32
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
497 else if(f
->field_size
== 8){
498 gint64 x
= *(gint64
*)(e
->data
+ f
->offset_root
);
499 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
500 return (int) (revFlag
? GINT64_FROM_BE(x
): x
);
502 return (int) (revFlag
? GINT64_FROM_LE(x
): x
);
505 g_critical("ltt_event_get_int : field size %i unknown", f
->field_size
);
509 guint64
ltt_event_get_long_unsigned(LttEvent
*e
, LttField
*f
)
511 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
513 LttTypeEnum t
= f
->field_type
->type_class
;
515 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
517 if(f
->field_size
== 1){
518 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
520 }else if(f
->field_size
== 2){
521 return (guint64
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
522 }else if(f
->field_size
== 4){
523 return (guint64
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
524 }else if(f
->field_size
== 8){
525 return ltt_get_uint64(reverse_byte_order
, e
->data
+ f
->offset_root
);
527 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f
->field_size
);
531 gint64
ltt_event_get_long_int(LttEvent
*e
, LttField
*f
)
533 //int revFlag = e->tracefile->trace->my_arch_endian ==
534 // e->tracefile->trace->system_description->endian ? 0:1;
535 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
537 g_assert( f
->field_type
->type_class
== LTT_INT
);
539 if(f
->field_size
== 1){
540 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
542 }else if(f
->field_size
== 2){
543 return (gint64
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
544 }else if(f
->field_size
== 4){
545 return (gint64
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
546 }else if(f
->field_size
== 8){
547 return ltt_get_int64(reverse_byte_order
, e
->data
+ f
->offset_root
);
549 g_critical("ltt_event_get_long_int : field size %i unknown", f
->field_size
);
553 float ltt_event_get_float(LttEvent
*e
, LttField
*f
)
555 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
557 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 4);
559 if(reverse_byte_order
== 0) return *(float *)(e
->data
+ f
->offset_root
);
562 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 4);
563 aInt
= ___swab32(aInt
);
564 return ((float)aInt
);
568 double ltt_event_get_double(LttEvent
*e
, LttField
*f
)
570 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
572 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 8);
574 if(reverse_byte_order
== 0) return *(double *)(e
->data
+ f
->offset_root
);
577 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 8);
578 aInt
= ___swab64(aInt
);
579 return ((double)aInt
);
583 /*****************************************************************************
584 * The string obtained is only valid until the next read from
585 * the same tracefile.
586 ****************************************************************************/
587 char *ltt_event_get_string(LttEvent
*e
, LttField
*f
)
589 g_assert(f
->field_type
->type_class
== LTT_STRING
);
591 return (gchar
*)g_strdup((gchar
*)(e
->data
+ f
->offset_root
));