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
)
49 /*****************************************************************************
51 * ltt_event_refresh_fields : refresh fields of an event
53 * offsetRoot : offset from the root
54 * offsetParent : offset from the parent
57 * reverse_byte_order : 1 or 0
59 * int : size of the field
60 ****************************************************************************/
62 int ltt_event_refresh_fields(int offsetRoot
,int offsetParent
,
63 LttField
* fld
, void *evD
, gboolean reverse_byte_order
)
65 int size
, size1
, element_number
, i
, offset1
, offset2
;
66 LttType
* type
= fld
->field_type
;
68 switch(type
->type_class
) {
70 element_number
= (int) type
->element_number
;
71 if(fld
->field_fixed
== 0){// has string or sequence
73 for(i
=0;i
<element_number
;i
++){
74 size
+= ltt_event_refresh_fields(offsetRoot
+size
,size
,
75 fld
->child
[0], evD
+size
, reverse_byte_order
);
77 }else size
= fld
->field_size
;
81 size1
= fld
->sequ_number_size
;
82 element_number
= getIntNumber(reverse_byte_order
,size1
,evD
);
83 type
->element_number
= element_number
;
84 if(fld
->element_size
> 0){
85 size
= element_number
* fld
->element_size
;
86 }else{//sequence has string or sequence
88 for(i
=0;i
<element_number
;i
++){
89 size
+= ltt_event_refresh_fields(offsetRoot
+size
+size1
,size
+size1
,
90 fld
->child
[0], evD
+size
+size1
, reverse_byte_order
);
97 size
= strlen((gchar
*)evD
) + 1; //include end : '\0'
101 element_number
= (int) type
->element_number
;
102 if(fld
->field_fixed
== 0){
103 offset1
= offsetRoot
;
105 for(i
=0;i
<element_number
;i
++){
106 size
=ltt_event_refresh_fields(offset1
,offset2
,
107 fld
->child
[i
],evD
+offset2
, reverse_byte_order
);
112 }else size
= fld
->field_size
;
116 size
= fld
->field_size
;
120 size
= fld
->field_size
;
124 if(type
->type_class
!= LTT_STRUCT
&& type
->type_class
!= LTT_ARRAY
&&
125 type
->type_class
!= LTT_SEQUENCE
&& type
->type_class
!= LTT_STRING
){
126 size
= fld
->field_size
;
127 }else if(type
->type_class
== LTT_ARRAY
){
128 element_number
= (int) type
->element_number
;
129 if(fld
->field_fixed
== 0){// has string or sequence
131 for(i
=0;i
<element_number
;i
++){
132 size
+= ltt_event_refresh_fields(offsetRoot
+size
,size
,
133 fld
->child
[0], evD
+size
);
135 }else size
= fld
->field_size
;
136 }else if(type
->type_class
== LTT_SEQUENCE
){
137 size1
= fld
->sequ_number_size
;
138 element_number
= getIntNumber(size1
,evD
);
139 type
->element_number
= element_number
;
140 if(fld
->element_size
> 0){
141 size
= element_number
* fld
->element_size
;
142 }else{//sequence has string or sequence
144 for(i
=0;i
<element_number
;i
++){
145 size
+= ltt_event_refresh_fields(offsetRoot
+size
+size1
,size
+size1
,
146 fld
->child
[0], evD
+size
+size1
);
150 }else if(type
->type_class
== LTT_STRING
){
151 size
= strlen((char*)evD
) + 1; //include end : '\0'
152 }else if(type
->type_class
== LTT_STRUCT
){
153 element_number
= (int) type
->element_number
;
154 if(fld
->field_fixed
== 0){
155 offset1
= offsetRoot
;
157 for(i
=0;i
<element_number
;i
++){
158 size
=ltt_event_refresh_fields(offset1
,offset2
,
159 fld
->child
[i
],evD
+offset2
);
164 }else size
= fld
->field_size
;
167 fld
->offset_root
= offsetRoot
;
168 fld
->offset_parent
= offsetParent
;
169 fld
->fixed_root
= (offsetRoot
==-1) ? 0 : 1;
170 fld
->fixed_parent
= (offsetParent
==-1) ? 0 : 1;
171 fld
->field_size
= size
;
176 /*****************************************************************************
178 * ltt_event_eventtype_id: get event type id
179 * (base id + position of the event)
181 * e : an instance of an event type
183 * unsigned : event type id
184 ****************************************************************************/
186 unsigned ltt_event_eventtype_id(LttEvent
*e
)
188 return (unsigned) e
->event_id
;
191 /*****************************************************************************
193 * ltt_event_facility : get the facility of the event
195 * e : an instance of an event type
197 * LttFacility * : the facility of the event
198 ****************************************************************************/
200 LttFacility
*ltt_event_facility(LttEvent
*e
)
202 LttTrace
* trace
= e
->tracefile
->trace
;
203 unsigned id
= e
->event_id
;
204 return ltt_trace_facility_by_id(trace
,id
);
207 /*****************************************************************************
209 * ltt_event_eventtype : get the event type of the event
211 * e : an instance of an event type
213 * LttEventType * : the event type of the event
214 ****************************************************************************/
216 LttEventType
*ltt_event_eventtype(LttEvent
*e
)
218 LttFacility
* facility
= ltt_event_facility(e
);
219 if(!facility
) return NULL
;
220 return facility
->events
[e
->event_id
- facility
->base_id
];
223 /*****************************************************************************
225 * ltt_event_field : get the root field of the event
227 * e : an instance of an event type
229 * LttField * : the root field of the event
230 ****************************************************************************/
232 LttField
*ltt_event_field(LttEvent
*e
)
235 LttEventType
* event_type
= ltt_event_eventtype(e
);
236 if(unlikely(!event_type
)) return NULL
;
237 field
= event_type
->root_field
;
238 if(unlikely(!field
)) return NULL
;
240 //check if the field need refresh
241 if(likely(e
->which_block
!= event_type
->latest_block
||
242 e
->which_event
!= event_type
->latest_event
)){
244 event_type
->latest_block
= e
->which_block
;
245 event_type
->latest_event
= e
->which_event
;
247 if(unlikely(field
->field_fixed
!= 1))
248 ltt_event_refresh_fields(0, 0, field
, e
->data
,
249 e
->tracefile
->trace
->reverse_byte_order
);
254 /*****************************************************************************
256 * ltt_event_time : get the time of the event
258 * e : an instance of an event type
260 * LttTime : the time of the event
261 ****************************************************************************/
263 LttTime
ltt_event_time(LttEvent
*e
)
265 return e
->event_time
;
268 /*****************************************************************************
270 * ltt_event_time : get the cycle count of the event
272 * e : an instance of an event type
274 * LttCycleCount : the cycle count of the event
275 ****************************************************************************/
277 LttCycleCount
ltt_event_cycle_count(LttEvent
*e
)
279 return e
->event_cycle_count
;
282 /*****************************************************************************
284 * ltt_event_position : get the event's position
286 * e : an instance of an event type
287 * ep : a pointer to event's position structure
288 ****************************************************************************/
290 void ltt_event_position(LttEvent
*e
, LttEventPosition
*ep
)
292 ep
->block_num
= e
->which_block
;
293 ep
->event_num
= e
->which_event
;
294 ep
->event_time
= e
->event_time
;
295 ep
->event_cycle_count
= e
->event_cycle_count
;
296 ep
->heart_beat_number
= e
->tracefile
->cur_heart_beat_number
;
297 ep
->old_position
= TRUE
;
298 ep
->event_offset
= e
->data
- e
->tracefile
->buffer
- EVENT_HEADER_SIZE
;
299 ep
->tf
= e
->tracefile
;
300 ep
->overflow_nsec
= e
->overflow_nsec
;
301 /* This is a workaround for fast position seek */
302 ep
->last_event_pos
= e
->last_event_pos
;
303 ep
->prev_block_end_time
= e
->prev_block_end_time
;
304 ep
->prev_event_time
= e
->prev_event_time
;
305 ep
->pre_cycle_count
= e
->pre_cycle_count
;
306 ep
->count
= e
->count
;
307 ep
->last_heartbeat
= e
->last_heartbeat
;
309 /* end of workaround */
312 LttEventPosition
* ltt_event_position_new()
314 return g_new(LttEventPosition
, 1);
317 /*****************************************************************************
319 * ltt_event_position_get : get the block number and index of the event
321 * ep : a pointer to event's position structure
322 * block_number : the block number of the event
323 * index_in_block : the index of the event within the block
324 ****************************************************************************/
326 void ltt_event_position_get(LttEventPosition
*ep
,
327 unsigned *block_number
, unsigned *index_in_block
, LttTracefile
** tf
)
329 *block_number
= ep
->block_num
;
330 *index_in_block
= ep
->event_num
;
334 /*****************************************************************************
336 * ltt_event_position_set : set the block number and index of the event
337 * It does put the old_position gboolean to FALSE, as it is impossible
338 * to know the quick position to seek in the tracefile.
340 * ep : a pointer to event's position structure
341 * block_number : the block number of the event
342 * index_in_block : the index of the event within the block
343 ****************************************************************************/
345 void ltt_event_position_set(LttEventPosition
*ep
,
346 unsigned block_number
, unsigned index_in_block
)
348 if(ep
->block_num
!= block_number
|| ep
->event_num
!= index_in_block
)
349 ep
->old_position
= FALSE
;
351 ep
->block_num
= block_number
;
352 ep
->event_num
= index_in_block
;
356 /*****************************************************************************
358 * ltt_event_position_compare : compare two positions
359 * A NULL value is infinite.
361 * ep1 : a pointer to event's position structure
362 * ep2 : a pointer to event's position structure
367 ****************************************************************************/
370 gint
ltt_event_position_compare(const LttEventPosition
*ep1
,
371 const LttEventPosition
*ep2
)
373 if(ep1
->tf
!= ep2
->tf
)
374 g_error("ltt_event_position_compare on different tracefiles makes no sense");
375 if(ep1
== NULL
&& ep2
== NULL
)
377 if(ep1
!= NULL
&& ep2
== NULL
)
379 if(ep1
== NULL
&& ep2
!= NULL
)
382 if(ep1
->block_num
< ep2
->block_num
)
384 if(ep1
->block_num
> ep2
->block_num
)
386 if(ep1
->event_num
< ep2
->event_num
)
388 if(ep1
->event_num
> ep2
->event_num
)
393 /*****************************************************************************
395 * ltt_event_event_position_compare : compare two positions, one in event,
396 * other in position opaque structure.
398 * event : a pointer to event structure
399 * ep : a pointer to event's position structure
404 ****************************************************************************/
406 gint
ltt_event_event_position_compare(const LttEvent
*event
,
407 const LttEventPosition
*ep
)
409 if(event
== NULL
&& ep
== NULL
)
411 if(event
!= NULL
&& ep
== NULL
)
413 if(event
== NULL
&& ep
!= NULL
)
416 g_assert(event
->tracefile
== ep
->tf
);
418 if(event
->which_block
< ep
->block_num
)
420 if(event
->which_block
> ep
->block_num
)
422 if(event
->which_event
< ep
->event_num
)
424 if(event
->which_event
> ep
->event_num
)
429 /*****************************************************************************
431 * ltt_event_position_copy : copy position
433 * src : a pointer to event's position structure source
434 * dest : a pointer to event's position structure dest
437 ****************************************************************************/
438 void ltt_event_position_copy(LttEventPosition
*dest
,
439 const LttEventPosition
*src
)
448 /*****************************************************************************
450 * ltt_event_cpu_i: get the cpu id where the event happens
452 * e : an instance of an event type
454 * unsigned : the cpu id
455 ****************************************************************************/
457 unsigned ltt_event_cpu_id(LttEvent
*e
)
459 gchar
* c1
, * c2
, * c3
;
460 c1
= strrchr(e
->tracefile
->name
,'\\');
461 c2
= strrchr(e
->tracefile
->name
,'/');
462 if(c1
== NULL
&& c2
== NULL
){
463 return (unsigned)atoi(e
->tracefile
->name
);
464 }else if(c1
== NULL
){
466 return (unsigned)atoi(c2
);
467 }else if(c2
== NULL
){
469 return (unsigned)atoi(c1
);
471 c3
= (c1
> c2
) ? c1
: c2
;
473 return (unsigned)atoi(c3
);
477 /*****************************************************************************
479 * ltt_event_data : get the raw data for the event
481 * e : an instance of an event type
483 * void * : pointer to the raw data for the event
484 ****************************************************************************/
486 void *ltt_event_data(LttEvent
*e
)
491 /*****************************************************************************
493 * ltt_event_field_element_number
494 * : The number of elements in a sequence field is specific
495 * to each event. This function returns the number of
496 * elements for an array or sequence field in an event.
498 * e : an instance of an event type
499 * f : a field of the instance
501 * unsigned : the number of elements for an array/sequence field
502 ****************************************************************************/
504 unsigned ltt_event_field_element_number(LttEvent
*e
, LttField
*f
)
506 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
507 f
->field_type
->type_class
!= LTT_SEQUENCE
)
510 if(f
->field_type
->type_class
== LTT_ARRAY
)
511 return f
->field_type
->element_number
;
512 return (unsigned) getIntNumber(e
->tracefile
->trace
->reverse_byte_order
,
513 f
->sequ_number_size
, e
+ f
->offset_root
);
516 /*****************************************************************************
518 * ltt_event_field_element_select
519 * : Set the currently selected element for a sequence or
522 * e : an instance of an event type
523 * f : a field of the instance
524 * i : the ith element
525 ****************************************************************************/
527 void ltt_event_field_element_select(LttEvent
*e
, LttField
*f
, unsigned i
)
529 unsigned element_number
;
535 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
536 f
->field_type
->type_class
!= LTT_SEQUENCE
)
539 element_number
= ltt_event_field_element_number(e
,f
);
540 /* Sanity check for i : 1..n only, and must be lower or equal element_number
542 if(element_number
< i
|| i
== 0) return;
546 evD
= e
->data
+ f
->offset_root
;
549 size
+= ltt_event_refresh_fields(f
->offset_root
+size
,size
, fld
, evD
+size
,
550 e
->tracefile
->trace
->reverse_byte_order
);
552 f
->current_element
= i
- 1;
555 /*****************************************************************************
556 * These functions extract data from an event after architecture specific
558 ****************************************************************************/
560 guint32
ltt_event_get_unsigned(LttEvent
*e
, LttField
*f
)
562 //int revFlag = e->tracefile->trace->my_arch_endian ==
563 // e->tracefile->trace->system_description->endian ? 0:1;
564 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
566 LttTypeEnum t
= f
->field_type
->type_class
;
568 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
570 if(f
->field_size
== 1){
571 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
573 }else if(f
->field_size
== 2){
574 return (guint32
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
575 }else if(f
->field_size
== 4){
576 return (guint32
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
579 else if(f
->field_size
== 8){
580 guint64 x
= *(guint64
*)(e
->data
+ f
->offset_root
);
581 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
582 return (unsigned int) (revFlag
? GUINT64_FROM_BE(x
): x
);
584 return (unsigned int) (revFlag
? GUINT64_FROM_LE(x
): x
);
587 g_critical("ltt_event_get_unsigned : field size %i unknown", f
->field_size
);
591 gint32
ltt_event_get_int(LttEvent
*e
, LttField
*f
)
593 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
594 //int revFlag = e->tracefile->trace->my_arch_endian ==
595 // e->tracefile->trace->system_description->endian ? 0:1;
597 g_assert(f
->field_type
->type_class
== LTT_INT
);
599 if(f
->field_size
== 1){
600 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
602 }else if(f
->field_size
== 2){
603 return (gint32
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
604 }else if(f
->field_size
== 4){
605 return (gint32
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
608 else if(f
->field_size
== 8){
609 gint64 x
= *(gint64
*)(e
->data
+ f
->offset_root
);
610 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
611 return (int) (revFlag
? GINT64_FROM_BE(x
): x
);
613 return (int) (revFlag
? GINT64_FROM_LE(x
): x
);
616 g_critical("ltt_event_get_int : field size %i unknown", f
->field_size
);
620 guint64
ltt_event_get_long_unsigned(LttEvent
*e
, LttField
*f
)
622 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
623 //int revFlag = e->tracefile->trace->my_arch_endian ==
624 // e->tracefile->trace->system_description->endian ? 0:1;
625 LttTypeEnum t
= f
->field_type
->type_class
;
627 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
629 if(f
->field_size
== 1){
630 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
632 }else if(f
->field_size
== 2){
633 return (guint64
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
634 }else if(f
->field_size
== 4){
635 return (guint64
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
636 }else if(f
->field_size
== 8){
637 return ltt_get_uint64(reverse_byte_order
, e
->data
+ f
->offset_root
);
639 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f
->field_size
);
643 gint64
ltt_event_get_long_int(LttEvent
*e
, LttField
*f
)
645 //int revFlag = e->tracefile->trace->my_arch_endian ==
646 // e->tracefile->trace->system_description->endian ? 0:1;
647 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
649 g_assert( f
->field_type
->type_class
== LTT_INT
);
651 if(f
->field_size
== 1){
652 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
654 }else if(f
->field_size
== 2){
655 return (gint64
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
656 }else if(f
->field_size
== 4){
657 return (gint64
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
658 }else if(f
->field_size
== 8){
659 return ltt_get_int64(reverse_byte_order
, e
->data
+ f
->offset_root
);
661 g_critical("ltt_event_get_long_int : field size %i unknown", f
->field_size
);
665 float ltt_event_get_float(LttEvent
*e
, LttField
*f
)
667 //int revFlag = e->tracefile->trace->my_arch_endian ==
668 // e->tracefile->trace->system_description->endian ? 0:1;
669 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
671 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 4);
673 if(reverse_byte_order
== 0) return *(float *)(e
->data
+ f
->offset_root
);
676 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 4);
677 aInt
= ___swab32(aInt
);
678 return ((float)aInt
);
682 double ltt_event_get_double(LttEvent
*e
, LttField
*f
)
684 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
685 //int revFlag = e->tracefile->trace->my_arch_endian ==
686 // e->tracefile->trace->system_description->endian ? 0:1;
688 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 8);
690 if(reverse_byte_order
== 0) return *(double *)(e
->data
+ f
->offset_root
);
693 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 8);
694 aInt
= ___swab64(aInt
);
695 return ((double)aInt
);
699 /*****************************************************************************
700 * The string obtained is only valid until the next read from
701 * the same tracefile.
702 ****************************************************************************/
704 char *ltt_event_get_string(LttEvent
*e
, LttField
*f
)
706 g_assert(f
->field_type
->type_class
== LTT_STRING
);
708 return (gchar
*)g_strdup((gchar
*)(e
->data
+ f
->offset_root
));