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,
23 #include <asm/types.h>
24 #include <linux/byteorder/swab.h>
28 #include "ltt-private.h"
29 #include <ltt/event.h>
30 #include <ltt/trace.h>
31 #include <ltt/ltt-types.h>
34 LttEvent
*ltt_event_new()
36 return g_new(LttEvent
, 1);
39 void ltt_event_destroy(LttEvent
*event
)
45 /*****************************************************************************
47 * ltt_event_refresh_fields : refresh fields of an event
49 * offsetRoot : offset from the root
50 * offsetParent : offset from the parent
53 * reverse_byte_order : 1 or 0
55 * int : size of the field
56 ****************************************************************************/
58 int ltt_event_refresh_fields(int offsetRoot
,int offsetParent
,
59 LttField
* fld
, void *evD
, gboolean reverse_byte_order
)
61 int size
, size1
, element_number
, i
, offset1
, offset2
;
62 LttType
* type
= fld
->field_type
;
64 switch(type
->type_class
) {
66 element_number
= (int) type
->element_number
;
67 if(fld
->field_fixed
== 0){// has string or sequence
69 for(i
=0;i
<element_number
;i
++){
70 size
+= ltt_event_refresh_fields(offsetRoot
+size
,size
,
71 fld
->child
[0], evD
+size
, reverse_byte_order
);
73 }else size
= fld
->field_size
;
77 size1
= fld
->sequ_number_size
;
78 element_number
= getIntNumber(reverse_byte_order
,size1
,evD
);
79 type
->element_number
= element_number
;
80 if(fld
->element_size
> 0){
81 size
= element_number
* fld
->element_size
;
82 }else{//sequence has string or sequence
84 for(i
=0;i
<element_number
;i
++){
85 size
+= ltt_event_refresh_fields(offsetRoot
+size
+size1
,size
+size1
,
86 fld
->child
[0], evD
+size
+size1
, reverse_byte_order
);
93 size
= strlen((char*)evD
) + 1; //include end : '\0'
97 element_number
= (int) type
->element_number
;
98 if(fld
->field_fixed
== 0){
101 for(i
=0;i
<element_number
;i
++){
102 size
=ltt_event_refresh_fields(offset1
,offset2
,
103 fld
->child
[i
],evD
+offset2
, reverse_byte_order
);
108 }else size
= fld
->field_size
;
112 size
= fld
->field_size
;
116 size
= fld
->field_size
;
120 if(type
->type_class
!= LTT_STRUCT
&& type
->type_class
!= LTT_ARRAY
&&
121 type
->type_class
!= LTT_SEQUENCE
&& type
->type_class
!= LTT_STRING
){
122 size
= fld
->field_size
;
123 }else if(type
->type_class
== LTT_ARRAY
){
124 element_number
= (int) type
->element_number
;
125 if(fld
->field_fixed
== 0){// has string or sequence
127 for(i
=0;i
<element_number
;i
++){
128 size
+= ltt_event_refresh_fields(offsetRoot
+size
,size
,
129 fld
->child
[0], evD
+size
);
131 }else size
= fld
->field_size
;
132 }else if(type
->type_class
== LTT_SEQUENCE
){
133 size1
= fld
->sequ_number_size
;
134 element_number
= getIntNumber(size1
,evD
);
135 type
->element_number
= element_number
;
136 if(fld
->element_size
> 0){
137 size
= element_number
* fld
->element_size
;
138 }else{//sequence has string or sequence
140 for(i
=0;i
<element_number
;i
++){
141 size
+= ltt_event_refresh_fields(offsetRoot
+size
+size1
,size
+size1
,
142 fld
->child
[0], evD
+size
+size1
);
146 }else if(type
->type_class
== LTT_STRING
){
147 size
= strlen((char*)evD
) + 1; //include end : '\0'
148 }else if(type
->type_class
== LTT_STRUCT
){
149 element_number
= (int) type
->element_number
;
150 if(fld
->field_fixed
== 0){
151 offset1
= offsetRoot
;
153 for(i
=0;i
<element_number
;i
++){
154 size
=ltt_event_refresh_fields(offset1
,offset2
,
155 fld
->child
[i
],evD
+offset2
);
160 }else size
= fld
->field_size
;
163 fld
->offset_root
= offsetRoot
;
164 fld
->offset_parent
= offsetParent
;
165 fld
->fixed_root
= (offsetRoot
==-1) ? 0 : 1;
166 fld
->fixed_parent
= (offsetParent
==-1) ? 0 : 1;
167 fld
->field_size
= size
;
172 /*****************************************************************************
174 * ltt_event_eventtype_id: get event type id
175 * (base id + position of the event)
177 * e : an instance of an event type
179 * unsigned : event type id
180 ****************************************************************************/
182 unsigned ltt_event_eventtype_id(LttEvent
*e
)
184 return (unsigned) e
->event_id
;
187 /*****************************************************************************
189 * ltt_event_facility : get the facility of the event
191 * e : an instance of an event type
193 * LttFacility * : the facility of the event
194 ****************************************************************************/
196 LttFacility
*ltt_event_facility(LttEvent
*e
)
198 LttTrace
* trace
= e
->tracefile
->trace
;
199 unsigned id
= e
->event_id
;
200 return ltt_trace_facility_by_id(trace
,id
);
203 /*****************************************************************************
205 * ltt_event_eventtype : get the event type of the event
207 * e : an instance of an event type
209 * LttEventType * : the event type of the event
210 ****************************************************************************/
212 LttEventType
*ltt_event_eventtype(LttEvent
*e
)
214 LttFacility
* facility
= ltt_event_facility(e
);
215 if(!facility
) return NULL
;
216 return facility
->events
[e
->event_id
- facility
->base_id
];
219 /*****************************************************************************
221 * ltt_event_field : get the root field of the event
223 * e : an instance of an event type
225 * LttField * : the root field of the event
226 ****************************************************************************/
228 LttField
*ltt_event_field(LttEvent
*e
)
231 LttEventType
* event_type
= ltt_event_eventtype(e
);
232 if(unlikely(!event_type
)) return NULL
;
233 field
= event_type
->root_field
;
234 if(unlikely(!field
)) return NULL
;
236 //check if the field need refresh
237 if(likely(e
->which_block
!= event_type
->latest_block
||
238 e
->which_event
!= event_type
->latest_event
)){
240 event_type
->latest_block
= e
->which_block
;
241 event_type
->latest_event
= e
->which_event
;
243 if(unlikely(field
->field_fixed
!= 1))
244 ltt_event_refresh_fields(0, 0, field
, e
->data
,
245 e
->tracefile
->trace
->reverse_byte_order
);
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
)
275 return e
->event_cycle_count
;
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
->block_num
= e
->which_block
;
289 ep
->event_num
= e
->which_event
;
290 ep
->event_time
= e
->event_time
;
291 ep
->event_cycle_count
= e
->event_cycle_count
;
292 ep
->heart_beat_number
= e
->tracefile
->cur_heart_beat_number
;
293 ep
->old_position
= TRUE
;
294 ep
->event_offset
= e
->data
- e
->tracefile
->buffer
- EVENT_HEADER_SIZE
;
295 ep
->tf
= e
->tracefile
;
296 ep
->overflow_nsec
= e
->overflow_nsec
;
297 /* This is a workaround for fast position seek */
298 ep
->last_event_pos
= e
->last_event_pos
;
299 ep
->prev_block_end_time
= e
->prev_block_end_time
;
300 ep
->prev_event_time
= e
->prev_event_time
;
301 ep
->pre_cycle_count
= e
->pre_cycle_count
;
302 ep
->count
= e
->count
;
303 ep
->last_heartbeat
= e
->last_heartbeat
;
305 /* end of workaround */
308 LttEventPosition
* ltt_event_position_new()
310 return g_new(LttEventPosition
, 1);
313 /*****************************************************************************
315 * ltt_event_position_get : get the block number and index of the event
317 * ep : a pointer to event's position structure
318 * block_number : the block number of the event
319 * index_in_block : the index of the event within the block
320 ****************************************************************************/
322 void ltt_event_position_get(LttEventPosition
*ep
,
323 unsigned *block_number
, unsigned *index_in_block
, LttTracefile
** tf
)
325 *block_number
= ep
->block_num
;
326 *index_in_block
= ep
->event_num
;
330 /*****************************************************************************
332 * ltt_event_position_set : set the block number and index of the event
333 * It does put the old_position gboolean to FALSE, as it is impossible
334 * to know the quick position to seek in the tracefile.
336 * ep : a pointer to event's position structure
337 * block_number : the block number of the event
338 * index_in_block : the index of the event within the block
339 ****************************************************************************/
341 void ltt_event_position_set(LttEventPosition
*ep
,
342 unsigned block_number
, unsigned index_in_block
)
344 if(ep
->block_num
!= block_number
|| ep
->event_num
!= index_in_block
)
345 ep
->old_position
= FALSE
;
347 ep
->block_num
= block_number
;
348 ep
->event_num
= index_in_block
;
352 /*****************************************************************************
354 * ltt_event_position_compare : compare two positions
355 * A NULL value is infinite.
357 * ep1 : a pointer to event's position structure
358 * ep2 : a pointer to event's position structure
363 ****************************************************************************/
366 gint
ltt_event_position_compare(const LttEventPosition
*ep1
,
367 const LttEventPosition
*ep2
)
369 if(ep1
->tf
!= ep2
->tf
)
370 g_error("ltt_event_position_compare on different tracefiles makes no sense");
371 if(ep1
== NULL
&& ep2
== NULL
)
373 if(ep1
!= NULL
&& ep2
== NULL
)
375 if(ep1
== NULL
&& ep2
!= NULL
)
378 if(ep1
->block_num
< ep2
->block_num
)
380 if(ep1
->block_num
> ep2
->block_num
)
382 if(ep1
->event_num
< ep2
->event_num
)
384 if(ep1
->event_num
> ep2
->event_num
)
389 /*****************************************************************************
391 * ltt_event_event_position_compare : compare two positions, one in event,
392 * other in position opaque structure.
394 * event : a pointer to event structure
395 * ep : a pointer to event's position structure
400 ****************************************************************************/
402 gint
ltt_event_event_position_compare(const LttEvent
*event
,
403 const LttEventPosition
*ep
)
405 if(event
== NULL
&& ep
== NULL
)
407 if(event
!= NULL
&& ep
== NULL
)
409 if(event
== NULL
&& ep
!= NULL
)
412 g_assert(event
->tracefile
== ep
->tf
);
414 if(event
->which_block
< ep
->block_num
)
416 if(event
->which_block
> ep
->block_num
)
418 if(event
->which_event
< ep
->event_num
)
420 if(event
->which_event
> ep
->event_num
)
425 /*****************************************************************************
427 * ltt_event_position_copy : copy position
429 * src : a pointer to event's position structure source
430 * dest : a pointer to event's position structure dest
433 ****************************************************************************/
434 void ltt_event_position_copy(LttEventPosition
*dest
,
435 const LttEventPosition
*src
)
444 /*****************************************************************************
446 * ltt_event_cpu_i: get the cpu id where the event happens
448 * e : an instance of an event type
450 * unsigned : the cpu id
451 ****************************************************************************/
453 unsigned ltt_event_cpu_id(LttEvent
*e
)
455 char * c1
, * c2
, * c3
;
456 c1
= strrchr(e
->tracefile
->name
,'\\');
457 c2
= strrchr(e
->tracefile
->name
,'/');
458 if(c1
== NULL
&& c2
== NULL
){
459 return (unsigned)atoi(e
->tracefile
->name
);
460 }else if(c1
== NULL
){
462 return (unsigned)atoi(c2
);
463 }else if(c2
== NULL
){
465 return (unsigned)atoi(c1
);
467 c3
= (c1
> c2
) ? c1
: c2
;
469 return (unsigned)atoi(c3
);
473 /*****************************************************************************
475 * ltt_event_data : get the raw data for the event
477 * e : an instance of an event type
479 * void * : pointer to the raw data for the event
480 ****************************************************************************/
482 void *ltt_event_data(LttEvent
*e
)
487 /*****************************************************************************
489 * ltt_event_field_element_number
490 * : The number of elements in a sequence field is specific
491 * to each event. This function returns the number of
492 * elements for an array or sequence field in an event.
494 * e : an instance of an event type
495 * f : a field of the instance
497 * unsigned : the number of elements for an array/sequence field
498 ****************************************************************************/
500 unsigned ltt_event_field_element_number(LttEvent
*e
, LttField
*f
)
502 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
503 f
->field_type
->type_class
!= LTT_SEQUENCE
)
506 if(f
->field_type
->type_class
== LTT_ARRAY
)
507 return f
->field_type
->element_number
;
508 return (unsigned) getIntNumber(e
->tracefile
->trace
->reverse_byte_order
,
509 f
->sequ_number_size
, e
+ f
->offset_root
);
512 /*****************************************************************************
514 * ltt_event_field_element_select
515 * : Set the currently selected element for a sequence or
518 * e : an instance of an event type
519 * f : a field of the instance
520 * i : the ith element
521 ****************************************************************************/
523 void ltt_event_field_element_select(LttEvent
*e
, LttField
*f
, unsigned i
)
525 unsigned element_number
;
531 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
532 f
->field_type
->type_class
!= LTT_SEQUENCE
)
535 element_number
= ltt_event_field_element_number(e
,f
);
536 /* Sanity check for i : 1..n only, and must be lower or equal element_number
538 if(element_number
< i
|| i
== 0) return;
542 evD
= e
->data
+ f
->offset_root
;
545 size
+= ltt_event_refresh_fields(f
->offset_root
+size
,size
, fld
, evD
+size
,
546 e
->tracefile
->trace
->reverse_byte_order
);
548 f
->current_element
= i
- 1;
551 /*****************************************************************************
552 * These functions extract data from an event after architecture specific
554 ****************************************************************************/
556 guint32
ltt_event_get_unsigned(LttEvent
*e
, LttField
*f
)
558 //int revFlag = e->tracefile->trace->my_arch_endian ==
559 // e->tracefile->trace->system_description->endian ? 0:1;
560 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
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 (guint32
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
571 }else if(f
->field_size
== 4){
572 return (guint32
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
575 else if(f
->field_size
== 8){
576 guint64 x
= *(guint64
*)(e
->data
+ f
->offset_root
);
577 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
578 return (unsigned int) (revFlag
? GUINT64_FROM_BE(x
): x
);
580 return (unsigned int) (revFlag
? GUINT64_FROM_LE(x
): x
);
583 g_critical("ltt_event_get_unsigned : field size %i unknown", f
->field_size
);
587 gint32
ltt_event_get_int(LttEvent
*e
, LttField
*f
)
589 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
590 //int revFlag = e->tracefile->trace->my_arch_endian ==
591 // e->tracefile->trace->system_description->endian ? 0:1;
593 g_assert(f
->field_type
->type_class
== LTT_INT
);
595 if(f
->field_size
== 1){
596 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
598 }else if(f
->field_size
== 2){
599 return (gint32
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
600 }else if(f
->field_size
== 4){
601 return (gint32
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
604 else if(f
->field_size
== 8){
605 gint64 x
= *(gint64
*)(e
->data
+ f
->offset_root
);
606 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
607 return (int) (revFlag
? GINT64_FROM_BE(x
): x
);
609 return (int) (revFlag
? GINT64_FROM_LE(x
): x
);
612 g_critical("ltt_event_get_int : field size %i unknown", f
->field_size
);
616 guint64
ltt_event_get_long_unsigned(LttEvent
*e
, LttField
*f
)
618 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
619 //int revFlag = e->tracefile->trace->my_arch_endian ==
620 // e->tracefile->trace->system_description->endian ? 0:1;
621 LttTypeEnum t
= f
->field_type
->type_class
;
623 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
625 if(f
->field_size
== 1){
626 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
628 }else if(f
->field_size
== 2){
629 return (guint64
)ltt_get_uint16(reverse_byte_order
, e
->data
+ f
->offset_root
);
630 }else if(f
->field_size
== 4){
631 return (guint64
)ltt_get_uint32(reverse_byte_order
, e
->data
+ f
->offset_root
);
632 }else if(f
->field_size
== 8){
633 return ltt_get_uint64(reverse_byte_order
, e
->data
+ f
->offset_root
);
635 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f
->field_size
);
639 gint64
ltt_event_get_long_int(LttEvent
*e
, LttField
*f
)
641 //int revFlag = e->tracefile->trace->my_arch_endian ==
642 // e->tracefile->trace->system_description->endian ? 0:1;
643 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
645 g_assert( f
->field_type
->type_class
== LTT_INT
);
647 if(f
->field_size
== 1){
648 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
650 }else if(f
->field_size
== 2){
651 return (gint64
)ltt_get_int16(reverse_byte_order
, e
->data
+ f
->offset_root
);
652 }else if(f
->field_size
== 4){
653 return (gint64
)ltt_get_int32(reverse_byte_order
, e
->data
+ f
->offset_root
);
654 }else if(f
->field_size
== 8){
655 return ltt_get_int64(reverse_byte_order
, e
->data
+ f
->offset_root
);
657 g_critical("ltt_event_get_long_int : field size %i unknown", f
->field_size
);
661 float ltt_event_get_float(LttEvent
*e
, LttField
*f
)
663 //int revFlag = e->tracefile->trace->my_arch_endian ==
664 // e->tracefile->trace->system_description->endian ? 0:1;
665 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
667 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 4);
669 if(reverse_byte_order
== 0) return *(float *)(e
->data
+ f
->offset_root
);
672 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 4);
673 aInt
= ___swab32(aInt
);
674 return ((float)aInt
);
678 double ltt_event_get_double(LttEvent
*e
, LttField
*f
)
680 gboolean reverse_byte_order
= e
->tracefile
->trace
->reverse_byte_order
;
681 //int revFlag = e->tracefile->trace->my_arch_endian ==
682 // e->tracefile->trace->system_description->endian ? 0:1;
684 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 8);
686 if(reverse_byte_order
== 0) return *(double *)(e
->data
+ f
->offset_root
);
689 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 8);
690 aInt
= ___swab64(aInt
);
691 return ((double)aInt
);
695 /*****************************************************************************
696 * The string obtained is only valid until the next read from
697 * the same tracefile.
698 ****************************************************************************/
700 char *ltt_event_get_string(LttEvent
*e
, LttField
*f
)
702 g_assert(f
->field_type
->type_class
== LTT_STRING
);
704 return (char*)g_strdup((char*)(e
->data
+ f
->offset_root
));