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>
39 LttEvent
*ltt_event_new()
41 return g_new(LttEvent
, 1);
44 void ltt_event_destroy(LttEvent
*event
)
51 /* Use get_field_type_size instead */
52 /*****************************************************************************
54 * ltt_event_refresh_fields : refresh fields of an event
56 * offsetRoot : offset from the root
57 * offsetParent : offset from the parent
60 * reverse_byte_order : 1 or 0
62 * int : size of the field
63 ****************************************************************************/
65 int ltt_event_refresh_fields(int offsetRoot
,int offsetParent
,
66 LttField
* fld
, void *evD
, gboolean reverse_byte_order
)
68 int size
, size1
, element_number
, i
, offset1
, offset2
;
69 LttType
* type
= fld
->field_type
;
71 switch(type
->type_class
) {
73 element_number
= (int) type
->element_number
;
74 if(fld
->field_fixed
== 0){// has string or sequence
76 for(i
=0;i
<element_number
;i
++){
77 size
+= ltt_event_refresh_fields(offsetRoot
+size
,size
,
78 fld
->child
[0], evD
+size
, reverse_byte_order
);
80 }else size
= fld
->field_size
;
84 size1
= fld
->sequ_number_size
;
85 element_number
= getIntNumber(reverse_byte_order
,size1
,evD
);
86 type
->element_number
= element_number
;
87 if(fld
->element_size
> 0){
88 size
= element_number
* fld
->element_size
;
89 }else{//sequence has string or sequence
91 for(i
=0;i
<element_number
;i
++){
92 size
+= ltt_event_refresh_fields(offsetRoot
+size
+size1
,size
+size1
,
93 fld
->child
[0], evD
+size
+size1
, reverse_byte_order
);
100 size
= strlen((gchar
*)evD
) + 1; //include end : '\0'
104 element_number
= (int) type
->element_number
;
105 if(fld
->field_fixed
== 0){
106 offset1
= offsetRoot
;
108 for(i
=0;i
<element_number
;i
++){
109 size
=ltt_event_refresh_fields(offset1
,offset2
,
110 fld
->child
[i
],evD
+offset2
, reverse_byte_order
);
115 }else size
= fld
->field_size
;
119 size
= fld
->field_size
;
123 size
= fld
->field_size
;
127 if(type
->type_class
!= LTT_STRUCT
&& type
->type_class
!= LTT_ARRAY
&&
128 type
->type_class
!= LTT_SEQUENCE
&& type
->type_class
!= LTT_STRING
){
129 size
= fld
->field_size
;
130 }else if(type
->type_class
== LTT_ARRAY
){
131 element_number
= (int) type
->element_number
;
132 if(fld
->field_fixed
== 0){// has string or sequence
134 for(i
=0;i
<element_number
;i
++){
135 size
+= ltt_event_refresh_fields(offsetRoot
+size
,size
,
136 fld
->child
[0], evD
+size
);
138 }else size
= fld
->field_size
;
139 }else if(type
->type_class
== LTT_SEQUENCE
){
140 size1
= fld
->sequ_number_size
;
141 element_number
= getIntNumber(size1
,evD
);
142 type
->element_number
= element_number
;
143 if(fld
->element_size
> 0){
144 size
= element_number
* fld
->element_size
;
145 }else{//sequence has string or sequence
147 for(i
=0;i
<element_number
;i
++){
148 size
+= ltt_event_refresh_fields(offsetRoot
+size
+size1
,size
+size1
,
149 fld
->child
[0], evD
+size
+size1
);
153 }else if(type
->type_class
== LTT_STRING
){
154 size
= strlen((char*)evD
) + 1; //include end : '\0'
155 }else if(type
->type_class
== LTT_STRUCT
){
156 element_number
= (int) type
->element_number
;
157 if(fld
->field_fixed
== 0){
158 offset1
= offsetRoot
;
160 for(i
=0;i
<element_number
;i
++){
161 size
=ltt_event_refresh_fields(offset1
,offset2
,
162 fld
->child
[i
],evD
+offset2
);
167 }else size
= fld
->field_size
;
170 fld
->offset_root
= offsetRoot
;
171 fld
->offset_parent
= offsetParent
;
172 fld
->fixed_root
= (offsetRoot
==-1) ? 0 : 1;
173 fld
->fixed_parent
= (offsetParent
==-1) ? 0 : 1;
174 fld
->field_size
= size
;
181 /*****************************************************************************
183 * ltt_event_eventtype_id: get event type id
184 * (base id + position of the event)
186 * e : an instance of an event type
188 * unsigned : event type id
189 ****************************************************************************/
191 unsigned ltt_event_eventtype_id(LttEvent
*e
)
193 return (unsigned) e
->event_id
;
196 /*****************************************************************************
198 * ltt_event_facility : get the facility of the event
200 * e : an instance of an event type
202 * LttFacility * : the facility of the event
203 ****************************************************************************/
205 LttFacility
*ltt_event_facility(LttEvent
*e
)
207 LttTrace
* trace
= e
->tracefile
->trace
;
208 unsigned id
= e
->event_id
;
209 return ltt_trace_facility_by_id(trace
,id
);
212 /*****************************************************************************
214 * ltt_event_eventtype : get the event type of the event
216 * e : an instance of an event type
218 * LttEventType * : the event type of the event
219 ****************************************************************************/
221 LttEventType
*ltt_event_eventtype(LttEvent
*e
)
223 LttFacility
* facility
= ltt_event_facility(e
);
224 if(!facility
) return NULL
;
225 return &g_array_index(facility
->events
, LttEventType
, e
->event_id
);
228 /*****************************************************************************
230 * ltt_event_field : get the root field of the event
232 * e : an instance of an event type
234 * LttField * : the root field of the event
235 ****************************************************************************/
237 LttField
*ltt_event_field(LttEvent
*e
)
240 LttEventType
* event_type
= ltt_event_eventtype(e
);
241 if(unlikely(!event_type
)) return NULL
;
242 field
= event_type
->root_field
;
243 if(unlikely(!field
)) return NULL
;
245 get_field_type_size(e
->tracefile
, event_type
, 0, 0,
251 /*****************************************************************************
253 * ltt_event_time : get the time of the event
255 * e : an instance of an event type
257 * LttTime : the time of the event
258 ****************************************************************************/
260 LttTime
ltt_event_time(LttEvent
*e
)
262 return e
->event_time
;
265 /*****************************************************************************
267 * ltt_event_time : get the cycle count of the event
269 * e : an instance of an event type
271 * LttCycleCount : the cycle count of the event
272 ****************************************************************************/
274 LttCycleCount
ltt_event_cycle_count(LttEvent
*e
)
279 /*****************************************************************************
281 * ltt_event_position : get the event's position
283 * e : an instance of an event type
284 * ep : a pointer to event's position structure
285 ****************************************************************************/
287 void ltt_event_position(LttEvent
*e
, LttEventPosition
*ep
)
289 ep
->tracefile
= e
->tracefile
;
290 ep
->block
= e
->block
;
291 ep
->offset
= e
->offset
;
295 LttEventPosition
* ltt_event_position_new()
297 return g_new(LttEventPosition
, 1);
301 /*****************************************************************************
303 * ltt_event_position_compare : compare two positions
304 * A NULL value is infinite.
306 * ep1 : a pointer to event's position structure
307 * ep2 : a pointer to event's position structure
312 ****************************************************************************/
315 gint
ltt_event_position_compare(const LttEventPosition
*ep1
,
316 const LttEventPosition
*ep2
)
318 if(ep1
== NULL
&& ep2
== NULL
)
320 if(ep1
!= NULL
&& ep2
== NULL
)
322 if(ep1
== NULL
&& ep2
!= NULL
)
325 if(ep1
->tracefile
!= ep2
->tracefile
)
326 g_error("ltt_event_position_compare on different tracefiles makes no sense");
328 if(ep1
->block
< ep2
->block
)
330 if(ep1
->block
> ep2
->block
)
332 if(ep1
->offset
< ep2
->offset
)
334 if(ep1
->offset
> ep2
->offset
)
339 /*****************************************************************************
341 * ltt_event_position_copy : copy position
343 * src : a pointer to event's position structure source
344 * dest : a pointer to event's position structure dest
347 ****************************************************************************/
348 void ltt_event_position_copy(LttEventPosition
*dest
,
349 const LttEventPosition
*src
)
358 /*****************************************************************************
360 * ltt_event_cpu_i: get the cpu id where the event happens
362 * e : an instance of an event type
364 * unsigned : the cpu id
365 ****************************************************************************/
367 unsigned ltt_event_cpu_id(LttEvent
*e
)
369 return e
->tracefile
->cpu_num
;
372 /*****************************************************************************
374 * ltt_event_data : get the raw data for the event
376 * e : an instance of an event type
378 * void * : pointer to the raw data for the event
379 ****************************************************************************/
381 void *ltt_event_data(LttEvent
*e
)
386 /*****************************************************************************
388 * ltt_event_field_element_number
389 * : The number of elements in a sequence field is specific
390 * to each event. This function returns the number of
391 * elements for an array or sequence field in an event.
393 * e : an instance of an event type
394 * f : a field of the instance
396 * unsigned : the number of elements for an array/sequence field
397 ****************************************************************************/
398 guint64
ltt_event_field_element_number(LttEvent
*e
, LttField
*f
)
400 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
401 f
->field_type
->type_class
!= LTT_SEQUENCE
)
404 if(f
->field_type
->type_class
== LTT_ARRAY
)
405 return f
->field_type
->element_number
;
406 return get_unsigned(LTT_GET_BO(e
->tracefile
), f
->sequ_number_size
,
410 /*****************************************************************************
412 * ltt_event_field_element_select
413 * : Set the currently selected element for a sequence or
415 * O(1) if fields are of fixed size, else O(n) if fields are
418 * e : an instance of an event type
419 * f : a field of the instance
420 * i : the ith element (0, ...)
421 ****************************************************************************/
422 void ltt_event_field_element_select(LttEvent
*e
, LttField
*f
, unsigned i
)
424 unsigned element_number
;
428 LttEventType
*event_type
;
430 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
431 f
->field_type
->type_class
!= LTT_SEQUENCE
)
434 element_number
= ltt_event_field_element_number(e
,f
);
435 event_type
= ltt_event_eventtype(e
);
436 /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number
438 if(i
>= element_number
) return;
442 if(f
->field_type
->type_class
== LTT_SEQUENCE
)
443 size
= f
->sequ_number_size
;
447 if(field
->fixed_size
== FIELD_FIXED
) {
448 size
+= field
->field_size
* i
;
450 get_field_type_size(e
->tracefile
, event_type
,
451 f
->offset_root
+size
, size
, field
, e
->data
);
455 size
+= get_field_type_size(e
->tracefile
, event_type
,
456 f
->offset_root
+size
, size
, field
, e
->data
);
459 f
->current_element
= i
;
462 /*****************************************************************************
463 * These functions extract data from an event after architecture specific
465 ****************************************************************************/
466 guint32
ltt_event_get_unsigned(LttEvent
*e
, LttField
*f
)
468 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
470 LttTypeEnum t
= f
->field_type
->type_class
;
472 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
474 if(f
->field_size
== 1){
475 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
477 }else if(f
->field_size
== 2){
478 return (guint32
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
479 }else if(f
->field_size
== 4){
480 return (guint32
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
483 else if(f
->field_size
== 8){
484 guint64 x
= *(guint64
*)(e
->data
+ f
->offset_root
);
485 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
486 return (unsigned int) (revFlag
? GUINT64_FROM_BE(x
): x
);
488 return (unsigned int) (revFlag
? GUINT64_FROM_LE(x
): x
);
491 g_critical("ltt_event_get_unsigned : field size %i unknown", f
->field_size
);
495 gint32
ltt_event_get_int(LttEvent
*e
, LttField
*f
)
497 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
499 g_assert(f
->field_type
->type_class
== LTT_INT
);
501 if(f
->field_size
== 1){
502 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
504 }else if(f
->field_size
== 2){
505 return (gint32
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
506 }else if(f
->field_size
== 4){
507 return (gint32
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
510 else if(f
->field_size
== 8){
511 gint64 x
= *(gint64
*)(e
->data
+ f
->offset_root
);
512 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
513 return (int) (revFlag
? GINT64_FROM_BE(x
): x
);
515 return (int) (revFlag
? GINT64_FROM_LE(x
): x
);
518 g_critical("ltt_event_get_int : field size %i unknown", f
->field_size
);
522 guint64
ltt_event_get_long_unsigned(LttEvent
*e
, LttField
*f
)
524 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
526 LttTypeEnum t
= f
->field_type
->type_class
;
528 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
530 if(f
->field_size
== 1){
531 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
533 }else if(f
->field_size
== 2){
534 return (guint64
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
535 }else if(f
->field_size
== 4){
536 return (guint64
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
537 }else if(f
->field_size
== 8){
538 return ltt_get_uint64(reverse_byte_order
, e
->data
+ f
->offset_root
);
540 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f
->field_size
);
544 gint64
ltt_event_get_long_int(LttEvent
*e
, LttField
*f
)
546 //int revFlag = e->tracefile->trace->my_arch_endian ==
547 // e->tracefile->trace->system_description->endian ? 0:1;
548 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
550 g_assert( f
->field_type
->type_class
== LTT_INT
);
552 if(f
->field_size
== 1){
553 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
555 }else if(f
->field_size
== 2){
556 return (gint64
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
557 }else if(f
->field_size
== 4){
558 return (gint64
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
559 }else if(f
->field_size
== 8){
560 return ltt_get_int64(reverse_byte_order
, e
->data
+ f
->offset_root
);
562 g_critical("ltt_event_get_long_int : field size %i unknown", f
->field_size
);
566 float ltt_event_get_float(LttEvent
*e
, LttField
*f
)
568 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
570 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 4);
572 if(reverse_byte_order
== 0) return *(float *)(e
->data
+ f
->offset_root
);
575 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 4);
576 aInt
= ___swab32(aInt
);
577 return ((float)aInt
);
581 double ltt_event_get_double(LttEvent
*e
, LttField
*f
)
583 gboolean reverse_byte_order
= LTT_GET_BO(e
->tracefile
);
585 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 8);
587 if(reverse_byte_order
== 0) return *(double *)(e
->data
+ f
->offset_root
);
590 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 8);
591 aInt
= ___swab64(aInt
);
592 return ((double)aInt
);
596 /*****************************************************************************
597 * The string obtained is only valid until the next read from
598 * the same tracefile.
599 ****************************************************************************/
600 char *ltt_event_get_string(LttEvent
*e
, LttField
*f
)
602 g_assert(f
->field_type
->type_class
== LTT_STRING
);
604 return (gchar
*)g_strdup((gchar
*)(e
->data
+ f
->offset_root
));