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>
33 LttEvent
*ltt_event_new()
35 return g_new(LttEvent
, 1);
38 void ltt_event_destroy(LttEvent
*event
)
44 /*****************************************************************************
46 * ltt_event_refresh_fields : refresh fields of an event
48 * offsetRoot : offset from the root
49 * offsetParent : offset from the parent
53 * int : size of the field
54 ****************************************************************************/
56 int ltt_event_refresh_fields(int offsetRoot
,int offsetParent
,
57 LttField
* fld
, void *evD
)
59 int size
, size1
, element_number
, i
, offset1
, offset2
;
60 LttType
* type
= fld
->field_type
;
62 switch(type
->type_class
) {
64 element_number
= (int) type
->element_number
;
65 if(fld
->field_fixed
== 0){// has string or sequence
67 for(i
=0;i
<element_number
;i
++){
68 size
+= ltt_event_refresh_fields(offsetRoot
+size
,size
,
69 fld
->child
[0], evD
+size
);
71 }else size
= fld
->field_size
;
75 size1
= fld
->sequ_number_size
;
76 element_number
= getIntNumber(size1
,evD
);
77 type
->element_number
= element_number
;
78 if(fld
->element_size
> 0){
79 size
= element_number
* fld
->element_size
;
80 }else{//sequence has string or sequence
82 for(i
=0;i
<element_number
;i
++){
83 size
+= ltt_event_refresh_fields(offsetRoot
+size
+size1
,size
+size1
,
84 fld
->child
[0], evD
+size
+size1
);
91 size
= strlen((char*)evD
) + 1; //include end : '\0'
95 element_number
= (int) type
->element_number
;
96 if(fld
->field_fixed
== 0){
99 for(i
=0;i
<element_number
;i
++){
100 size
=ltt_event_refresh_fields(offset1
,offset2
,
101 fld
->child
[i
],evD
+offset2
);
106 }else size
= fld
->field_size
;
110 size
= fld
->field_size
;
114 size
= fld
->field_size
;
118 if(type
->type_class
!= LTT_STRUCT
&& type
->type_class
!= LTT_ARRAY
&&
119 type
->type_class
!= LTT_SEQUENCE
&& type
->type_class
!= LTT_STRING
){
120 size
= fld
->field_size
;
121 }else if(type
->type_class
== LTT_ARRAY
){
122 element_number
= (int) type
->element_number
;
123 if(fld
->field_fixed
== 0){// has string or sequence
125 for(i
=0;i
<element_number
;i
++){
126 size
+= ltt_event_refresh_fields(offsetRoot
+size
,size
,
127 fld
->child
[0], evD
+size
);
129 }else size
= fld
->field_size
;
130 }else if(type
->type_class
== LTT_SEQUENCE
){
131 size1
= fld
->sequ_number_size
;
132 element_number
= getIntNumber(size1
,evD
);
133 type
->element_number
= element_number
;
134 if(fld
->element_size
> 0){
135 size
= element_number
* fld
->element_size
;
136 }else{//sequence has string or sequence
138 for(i
=0;i
<element_number
;i
++){
139 size
+= ltt_event_refresh_fields(offsetRoot
+size
+size1
,size
+size1
,
140 fld
->child
[0], evD
+size
+size1
);
144 }else if(type
->type_class
== LTT_STRING
){
145 size
= strlen((char*)evD
) + 1; //include end : '\0'
146 }else if(type
->type_class
== LTT_STRUCT
){
147 element_number
= (int) type
->element_number
;
148 if(fld
->field_fixed
== 0){
149 offset1
= offsetRoot
;
151 for(i
=0;i
<element_number
;i
++){
152 size
=ltt_event_refresh_fields(offset1
,offset2
,
153 fld
->child
[i
],evD
+offset2
);
158 }else size
= fld
->field_size
;
161 fld
->offset_root
= offsetRoot
;
162 fld
->offset_parent
= offsetParent
;
163 fld
->fixed_root
= (offsetRoot
==-1) ? 0 : 1;
164 fld
->fixed_parent
= (offsetParent
==-1) ? 0 : 1;
165 fld
->field_size
= size
;
170 /*****************************************************************************
172 * ltt_event_eventtype_id: get event type id
173 * (base id + position of the event)
175 * e : an instance of an event type
177 * unsigned : event type id
178 ****************************************************************************/
180 unsigned ltt_event_eventtype_id(LttEvent
*e
)
182 return (unsigned) e
->event_id
;
185 /*****************************************************************************
187 * ltt_event_facility : get the facility of the event
189 * e : an instance of an event type
191 * LttFacility * : the facility of the event
192 ****************************************************************************/
194 LttFacility
*ltt_event_facility(LttEvent
*e
)
196 LttTrace
* trace
= e
->tracefile
->trace
;
197 unsigned id
= e
->event_id
;
198 return ltt_trace_facility_by_id(trace
,id
);
201 /*****************************************************************************
203 * ltt_event_eventtype : get the event type of the event
205 * e : an instance of an event type
207 * LttEventType * : the event type of the event
208 ****************************************************************************/
210 LttEventType
*ltt_event_eventtype(LttEvent
*e
)
212 LttFacility
* facility
= ltt_event_facility(e
);
213 if(!facility
) return NULL
;
214 return facility
->events
[e
->event_id
- facility
->base_id
];
217 /*****************************************************************************
219 * ltt_event_field : get the root field of the event
221 * e : an instance of an event type
223 * LttField * : the root field of the event
224 ****************************************************************************/
226 LttField
*ltt_event_field(LttEvent
*e
)
229 LttEventType
* event_type
= ltt_event_eventtype(e
);
230 if(unlikely(!event_type
)) return NULL
;
231 field
= event_type
->root_field
;
232 if(unlikely(!field
)) return NULL
;
234 //check if the field need refresh
235 if(likely(e
->which_block
!= event_type
->latest_block
||
236 e
->which_event
!= event_type
->latest_event
)){
238 event_type
->latest_block
= e
->which_block
;
239 event_type
->latest_event
= e
->which_event
;
241 if(unlikely(field
->field_fixed
!= 1))
242 ltt_event_refresh_fields(0, 0, field
, e
->data
);
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
)
272 return e
->event_cycle_count
;
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
->block_num
= e
->which_block
;
286 ep
->event_num
= e
->which_event
;
287 ep
->event_time
= e
->event_time
;
288 ep
->event_cycle_count
= e
->event_cycle_count
;
289 ep
->heart_beat_number
= e
->tracefile
->cur_heart_beat_number
;
290 ep
->old_position
= TRUE
;
291 ep
->event_offset
= e
->data
- e
->tracefile
->buffer
- EVENT_HEADER_SIZE
;
292 ep
->tf
= e
->tracefile
;
293 ep
->overflow_nsec
= e
->overflow_nsec
;
294 /* This is a workaround for fast position seek */
295 ep
->last_event_pos
= e
->last_event_pos
;
296 ep
->prev_block_end_time
= e
->prev_block_end_time
;
297 ep
->prev_event_time
= e
->prev_event_time
;
298 ep
->pre_cycle_count
= e
->pre_cycle_count
;
299 ep
->count
= e
->count
;
300 ep
->last_heartbeat
= e
->last_heartbeat
;
302 /* end of workaround */
305 LttEventPosition
* ltt_event_position_new()
307 return g_new(LttEventPosition
, 1);
310 /*****************************************************************************
312 * ltt_event_position_get : get the block number and index of the event
314 * ep : a pointer to event's position structure
315 * block_number : the block number of the event
316 * index_in_block : the index of the event within the block
317 ****************************************************************************/
319 void ltt_event_position_get(LttEventPosition
*ep
,
320 unsigned *block_number
, unsigned *index_in_block
, LttTracefile
** tf
)
322 *block_number
= ep
->block_num
;
323 *index_in_block
= ep
->event_num
;
327 /*****************************************************************************
329 * ltt_event_position_set : set the block number and index of the event
330 * It does put the old_position gboolean to FALSE, as it is impossible
331 * to know the quick position to seek in the tracefile.
333 * ep : a pointer to event's position structure
334 * block_number : the block number of the event
335 * index_in_block : the index of the event within the block
336 ****************************************************************************/
338 void ltt_event_position_set(LttEventPosition
*ep
,
339 unsigned block_number
, unsigned index_in_block
)
341 if(ep
->block_num
!= block_number
|| ep
->event_num
!= index_in_block
)
342 ep
->old_position
= FALSE
;
344 ep
->block_num
= block_number
;
345 ep
->event_num
= index_in_block
;
349 /*****************************************************************************
351 * ltt_event_position_compare : compare two positions
352 * A NULL value is infinite.
354 * ep1 : a pointer to event's position structure
355 * ep2 : a pointer to event's position structure
360 ****************************************************************************/
363 gint
ltt_event_position_compare(const LttEventPosition
*ep1
,
364 const LttEventPosition
*ep2
)
366 if(ep1
->tf
!= ep2
->tf
)
367 g_error("ltt_event_position_compare on different tracefiles makes no sense");
368 if(ep1
== NULL
&& ep2
== NULL
)
370 if(ep1
!= NULL
&& ep2
== NULL
)
372 if(ep1
== NULL
&& ep2
!= NULL
)
375 if(ep1
->block_num
< ep2
->block_num
)
377 if(ep1
->block_num
> ep2
->block_num
)
379 if(ep1
->event_num
< ep2
->event_num
)
381 if(ep1
->event_num
> ep2
->event_num
)
386 /*****************************************************************************
388 * ltt_event_event_position_compare : compare two positions, one in event,
389 * other in position opaque structure.
391 * event : a pointer to event structure
392 * ep : a pointer to event's position structure
397 ****************************************************************************/
399 gint
ltt_event_event_position_compare(const LttEvent
*event
,
400 const LttEventPosition
*ep
)
402 if(event
== NULL
&& ep
== NULL
)
404 if(event
!= NULL
&& ep
== NULL
)
406 if(event
== NULL
&& ep
!= NULL
)
409 g_assert(event
->tracefile
== ep
->tf
);
411 if(event
->which_block
< ep
->block_num
)
413 if(event
->which_block
> ep
->block_num
)
415 if(event
->which_event
< ep
->event_num
)
417 if(event
->which_event
> ep
->event_num
)
422 /*****************************************************************************
424 * ltt_event_position_copy : copy position
426 * src : a pointer to event's position structure source
427 * dest : a pointer to event's position structure dest
430 ****************************************************************************/
431 void ltt_event_position_copy(LttEventPosition
*dest
,
432 const LttEventPosition
*src
)
441 /*****************************************************************************
443 * ltt_event_cpu_i: get the cpu id where the event happens
445 * e : an instance of an event type
447 * unsigned : the cpu id
448 ****************************************************************************/
450 unsigned ltt_event_cpu_id(LttEvent
*e
)
452 char * c1
, * c2
, * c3
;
453 c1
= strrchr(e
->tracefile
->name
,'\\');
454 c2
= strrchr(e
->tracefile
->name
,'/');
455 if(c1
== NULL
&& c2
== NULL
){
456 return (unsigned)atoi(e
->tracefile
->name
);
457 }else if(c1
== NULL
){
459 return (unsigned)atoi(c2
);
460 }else if(c2
== NULL
){
462 return (unsigned)atoi(c1
);
464 c3
= (c1
> c2
) ? c1
: c2
;
466 return (unsigned)atoi(c3
);
470 /*****************************************************************************
472 * ltt_event_data : get the raw data for the event
474 * e : an instance of an event type
476 * void * : pointer to the raw data for the event
477 ****************************************************************************/
479 void *ltt_event_data(LttEvent
*e
)
484 /*****************************************************************************
486 * ltt_event_field_element_number
487 * : The number of elements in a sequence field is specific
488 * to each event. This function returns the number of
489 * elements for an array or sequence field in an event.
491 * e : an instance of an event type
492 * f : a field of the instance
494 * unsigned : the number of elements for an array/sequence field
495 ****************************************************************************/
497 unsigned ltt_event_field_element_number(LttEvent
*e
, LttField
*f
)
499 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
500 f
->field_type
->type_class
!= LTT_SEQUENCE
)
503 if(f
->field_type
->type_class
== LTT_ARRAY
)
504 return f
->field_type
->element_number
;
505 return (unsigned) getIntNumber(f
->sequ_number_size
, e
+ f
->offset_root
);
508 /*****************************************************************************
510 * ltt_event_field_element_select
511 * : Set the currently selected element for a sequence or
514 * e : an instance of an event type
515 * f : a field of the instance
516 * i : the ith element
517 ****************************************************************************/
519 void ltt_event_field_element_select(LttEvent
*e
, LttField
*f
, unsigned i
)
521 unsigned element_number
;
527 if(f
->field_type
->type_class
!= LTT_ARRAY
&&
528 f
->field_type
->type_class
!= LTT_SEQUENCE
)
531 element_number
= ltt_event_field_element_number(e
,f
);
532 /* Sanity check for i : 1..n only, and must be lower or equal element_number
534 if(element_number
< i
|| i
== 0) return;
538 evD
= e
->data
+ f
->offset_root
;
541 size
+= ltt_event_refresh_fields(f
->offset_root
+size
,size
, fld
, evD
+size
);
543 f
->current_element
= i
- 1;
546 /*****************************************************************************
547 * These functions extract data from an event after architecture specific
549 ****************************************************************************/
551 guint32
ltt_event_get_unsigned(LttEvent
*e
, LttField
*f
)
553 int revFlag
= e
->tracefile
->trace
->my_arch_endian
==
554 e
->tracefile
->trace
->system_description
->endian
? 0:1;
555 LttTypeEnum t
= f
->field_type
->type_class
;
557 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
559 if(f
->field_size
== 1){
560 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
562 }else if(f
->field_size
== 2){
563 guint16 x
= *(guint16
*)(e
->data
+ f
->offset_root
);
564 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
565 return (guint32
) (revFlag
? GUINT16_FROM_BE(x
): x
);
567 return (guint32
) (revFlag
? GUINT16_FROM_LE(x
): x
);
568 }else if(f
->field_size
== 4){
569 guint32 x
= *(guint32
*)(e
->data
+ f
->offset_root
);
570 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
571 return (guint32
) (revFlag
? GUINT32_FROM_BE(x
): x
);
573 return (guint32
) (revFlag
? GUINT32_FROM_LE(x
): x
);
576 else if(f
->field_size
== 8){
577 guint64 x
= *(guint64
*)(e
->data
+ f
->offset_root
);
578 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
579 return (unsigned int) (revFlag
? GUINT64_FROM_BE(x
): x
);
581 return (unsigned int) (revFlag
? GUINT64_FROM_LE(x
): x
);
584 g_critical("ltt_event_get_unsigned : field size %i unknown", f
->field_size
);
588 gint32
ltt_event_get_int(LttEvent
*e
, LttField
*f
)
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 gint16 x
= *(gint16
*)(e
->data
+ f
->offset_root
);
600 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
601 return (gint32
) (revFlag
? GINT16_FROM_BE(x
): x
);
603 return (gint32
) (revFlag
? GINT16_FROM_LE(x
): x
);
604 }else if(f
->field_size
== 4){
605 gint32 x
= *(gint32
*)(e
->data
+ f
->offset_root
);
606 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
607 return (gint32
) (revFlag
? GINT32_FROM_BE(x
): x
);
609 return (gint32
) (revFlag
? GINT32_FROM_LE(x
): x
);
612 else if(f
->field_size
== 8){
613 gint64 x
= *(gint64
*)(e
->data
+ f
->offset_root
);
614 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
615 return (int) (revFlag
? GINT64_FROM_BE(x
): x
);
617 return (int) (revFlag
? GINT64_FROM_LE(x
): x
);
620 g_critical("ltt_event_get_int : field size %i unknown", f
->field_size
);
624 guint64
ltt_event_get_long_unsigned(LttEvent
*e
, LttField
*f
)
626 int revFlag
= e
->tracefile
->trace
->my_arch_endian
==
627 e
->tracefile
->trace
->system_description
->endian
? 0:1;
628 LttTypeEnum t
= f
->field_type
->type_class
;
630 g_assert(t
== LTT_UINT
|| t
== LTT_ENUM
);
632 if(f
->field_size
== 1){
633 guint8 x
= *(guint8
*)(e
->data
+ f
->offset_root
);
635 }else if(f
->field_size
== 2){
636 guint16 x
= *(guint16
*)(e
->data
+ f
->offset_root
);
637 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
638 return (guint64
) (revFlag
? GUINT16_FROM_BE(x
): x
);
640 return (guint64
) (revFlag
? GUINT16_FROM_LE(x
): x
);
641 }else if(f
->field_size
== 4){
642 guint32 x
= *(guint32
*)(e
->data
+ f
->offset_root
);
643 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
644 return (guint64
) (revFlag
? GUINT32_FROM_BE(x
): x
);
646 return (guint64
) (revFlag
? GUINT32_FROM_LE(x
): x
);
647 }else if(f
->field_size
== 8){
648 guint64 x
= *(guint64
*)(e
->data
+ f
->offset_root
);
649 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
650 return (guint64
) (revFlag
? GUINT64_FROM_BE(x
): x
);
652 return (guint64
) (revFlag
? GUINT64_FROM_LE(x
): x
);
654 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f
->field_size
);
658 gint64
ltt_event_get_long_int(LttEvent
*e
, LttField
*f
)
660 int revFlag
= e
->tracefile
->trace
->my_arch_endian
==
661 e
->tracefile
->trace
->system_description
->endian
? 0:1;
663 g_assert( f
->field_type
->type_class
== LTT_INT
);
665 if(f
->field_size
== 1){
666 gint8 x
= *(gint8
*)(e
->data
+ f
->offset_root
);
668 }else if(f
->field_size
== 2){
669 gint16 x
= *(gint16
*)(e
->data
+ f
->offset_root
);
670 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
671 return (gint64
) (revFlag
? GINT16_FROM_BE(x
): x
);
673 return (gint64
) (revFlag
? GINT16_FROM_LE(x
): x
);
674 }else if(f
->field_size
== 4){
675 gint32 x
= *(gint32
*)(e
->data
+ f
->offset_root
);
676 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
677 return (gint64
) (revFlag
? GINT32_FROM_BE(x
): x
);
679 return (gint64
) (revFlag
? GINT32_FROM_LE(x
): x
);
680 }else if(f
->field_size
== 8){
681 gint64 x
= *(gint64
*)(e
->data
+ f
->offset_root
);
682 if(e
->tracefile
->trace
->my_arch_endian
== LTT_LITTLE_ENDIAN
)
683 return (gint64
) (revFlag
? GINT64_FROM_BE(x
): x
);
685 return (gint64
) (revFlag
? GINT64_FROM_LE(x
): x
);
687 g_critical("ltt_event_get_long_int : field size %i unknown", f
->field_size
);
691 float ltt_event_get_float(LttEvent
*e
, LttField
*f
)
693 int revFlag
= e
->tracefile
->trace
->my_arch_endian
==
694 e
->tracefile
->trace
->system_description
->endian
? 0:1;
696 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 4);
698 if(revFlag
== 0) return *(float *)(e
->data
+ f
->offset_root
);
701 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 4);
702 aInt
= ___swab32(aInt
);
703 return ((float)aInt
);
707 double ltt_event_get_double(LttEvent
*e
, LttField
*f
)
709 int revFlag
= e
->tracefile
->trace
->my_arch_endian
==
710 e
->tracefile
->trace
->system_description
->endian
? 0:1;
712 g_assert(f
->field_type
->type_class
== LTT_FLOAT
&& f
->field_size
== 8);
714 if(revFlag
== 0) return *(double *)(e
->data
+ f
->offset_root
);
717 memcpy((void*)&aInt
, e
->data
+ f
->offset_root
, 8);
718 aInt
= ___swab64(aInt
);
719 return ((double)aInt
);
723 /*****************************************************************************
724 * The string obtained is only valid until the next read from
725 * the same tracefile.
726 ****************************************************************************/
728 char *ltt_event_get_string(LttEvent
*e
, LttField
*f
)
730 g_assert(f
->field_type
->type_class
== LTT_STRING
);
732 return (char*)g_strdup((char*)(e
->data
+ f
->offset_root
));
This page took 0.054314 seconds and 4 git commands to generate.