ltt library extra careful warnings check
[lttv.git] / ltt / branches / poly / ltt / event.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Xiangxiu Yang
3 *
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;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22
23 #include <asm/types.h>
24 #include <linux/byteorder/swab.h>
25
26 #include "parser.h"
27 #include <ltt/ltt.h>
28 #include "ltt-private.h"
29 #include <ltt/event.h>
30 #include <ltt/trace.h>
31
32
33 LttEvent *ltt_event_new()
34 {
35 return g_new(LttEvent, 1);
36 }
37
38 void ltt_event_destroy(LttEvent *event)
39 {
40 g_free(event);
41 }
42
43
44 /*****************************************************************************
45 *Function name
46 * ltt_event_refresh_fields : refresh fields of an event
47 *Input params
48 * offsetRoot : offset from the root
49 * offsetParent : offset from the parent
50 * fld : field
51 * evD : event data
52 *Return value
53 * int : size of the field
54 ****************************************************************************/
55
56 int ltt_event_refresh_fields(int offsetRoot,int offsetParent,
57 LttField * fld, void *evD)
58 {
59 int size, size1, element_number, i, offset1, offset2;
60 LttType * type = fld->field_type;
61
62 if(type->type_class != LTT_STRUCT && type->type_class != LTT_ARRAY &&
63 type->type_class != LTT_SEQUENCE && type->type_class != LTT_STRING){
64 size = fld->field_size;
65 }else if(type->type_class == LTT_ARRAY){
66 element_number = (int) type->element_number;
67 if(fld->field_fixed == 0){// has string or sequence
68 size = 0;
69 for(i=0;i<element_number;i++){
70 size += ltt_event_refresh_fields(offsetRoot+size,size,
71 fld->child[0], evD+size);
72 }
73 }else size = fld->field_size;
74 }else if(type->type_class == LTT_SEQUENCE){
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
81 size = 0;
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);
85 }
86 size += size1;
87 }
88 }else if(type->type_class == LTT_STRING){
89 size = strlen((char*)evD) + 1; //include end : '\0'
90 }else if(type->type_class == LTT_STRUCT){
91 element_number = (int) type->element_number;
92 if(fld->field_fixed == 0){
93 offset1 = offsetRoot;
94 offset2 = 0;
95 for(i=0;i<element_number;i++){
96 size=ltt_event_refresh_fields(offset1,offset2,fld->child[i],evD+offset2);
97 offset1 += size;
98 offset2 += size;
99 }
100 size = offset2;
101 }else size = fld->field_size;
102 }
103
104 fld->offset_root = offsetRoot;
105 fld->offset_parent = offsetParent;
106 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
107 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
108 fld->field_size = size;
109
110 return size;
111 }
112
113 /*****************************************************************************
114 *Function name
115 * ltt_event_eventtype_id: get event type id
116 * (base id + position of the event)
117 *Input params
118 * e : an instance of an event type
119 *Return value
120 * unsigned : event type id
121 ****************************************************************************/
122
123 unsigned ltt_event_eventtype_id(LttEvent *e)
124 {
125 return (unsigned) e->event_id;
126 }
127
128 /*****************************************************************************
129 *Function name
130 * ltt_event_facility : get the facility of the event
131 *Input params
132 * e : an instance of an event type
133 *Return value
134 * LttFacility * : the facility of the event
135 ****************************************************************************/
136
137 LttFacility *ltt_event_facility(LttEvent *e)
138 {
139 LttTrace * trace = e->tracefile->trace;
140 unsigned id = e->event_id;
141 return ltt_trace_facility_by_id(trace,id);
142 }
143
144 /*****************************************************************************
145 *Function name
146 * ltt_event_eventtype : get the event type of the event
147 *Input params
148 * e : an instance of an event type
149 *Return value
150 * LttEventType * : the event type of the event
151 ****************************************************************************/
152
153 LttEventType *ltt_event_eventtype(LttEvent *e)
154 {
155 LttFacility* facility = ltt_event_facility(e);
156 if(!facility) return NULL;
157 return facility->events[e->event_id - facility->base_id];
158 }
159
160 /*****************************************************************************
161 *Function name
162 * ltt_event_field : get the root field of the event
163 *Input params
164 * e : an instance of an event type
165 *Return value
166 * LttField * : the root field of the event
167 ****************************************************************************/
168
169 LttField *ltt_event_field(LttEvent *e)
170 {
171 LttField * field;
172 LttEventType * event_type = ltt_event_eventtype(e);
173 if(!event_type) return NULL;
174 field = event_type->root_field;
175 if(!field) return NULL;
176
177 //check if the field need refresh
178 if(e->which_block != event_type->latest_block ||
179 e->which_event != event_type->latest_event){
180
181 event_type->latest_block = e->which_block;
182 event_type->latest_event = e->which_event;
183
184 if(field->field_fixed == 1)return field;
185
186 //refresh the field
187 ltt_event_refresh_fields(0, 0, field, e->data);
188 }
189 return field;
190 }
191
192 /*****************************************************************************
193 *Function name
194 * ltt_event_time : get the time of the event
195 *Input params
196 * e : an instance of an event type
197 *Return value
198 * LttTime : the time of the event
199 ****************************************************************************/
200
201 LttTime ltt_event_time(LttEvent *e)
202 {
203 return e->event_time;
204 }
205
206 /*****************************************************************************
207 *Function name
208 * ltt_event_time : get the cycle count of the event
209 *Input params
210 * e : an instance of an event type
211 *Return value
212 * LttCycleCount : the cycle count of the event
213 ****************************************************************************/
214
215 LttCycleCount ltt_event_cycle_count(LttEvent *e)
216 {
217 return e->event_cycle_count;
218 }
219
220 /*****************************************************************************
221 *Function name
222 * ltt_event_position : get the event's position
223 *Input params
224 * e : an instance of an event type
225 * ep : a pointer to event's position structure
226 ****************************************************************************/
227
228 void ltt_event_position(LttEvent *e, LttEventPosition *ep)
229 {
230 ep->block_num = e->which_block;
231 ep->event_num = e->which_event;
232 ep->event_time = e->event_time;
233 ep->event_cycle_count = e->event_cycle_count;
234 ep->heart_beat_number = e->tracefile->cur_heart_beat_number;
235 ep->old_position = TRUE;
236 ep->event_offset = e->data - e->tracefile->buffer - EVENT_HEADER_SIZE ;
237 ep->tf = e->tracefile;
238
239 /* This is a workaround for fast position seek */
240 ep->last_event_pos = e->last_event_pos;
241 ep->prev_block_end_time = e->prev_block_end_time;
242 ep->prev_event_time = e->prev_event_time;
243 ep->pre_cycle_count = e->pre_cycle_count;
244 ep->count = e->count;
245 /* end of workaround */
246 }
247
248 LttEventPosition * ltt_event_position_new()
249 {
250 return g_new(LttEventPosition, 1);
251 }
252
253 /*****************************************************************************
254 *Function name
255 * ltt_event_position_get : get the block number and index of the event
256 *Input params
257 * ep : a pointer to event's position structure
258 * block_number : the block number of the event
259 * index_in_block : the index of the event within the block
260 ****************************************************************************/
261
262 void ltt_event_position_get(LttEventPosition *ep,
263 unsigned *block_number, unsigned *index_in_block, LttTracefile ** tf)
264 {
265 *block_number = ep->block_num;
266 *index_in_block = ep->event_num;
267 *tf = ep->tf;
268 }
269
270 /*****************************************************************************
271 *Function name
272 * ltt_event_position_set : set the block number and index of the event
273 * It does put the old_position gboolean to FALSE, as it is impossible
274 * to know the quick position to seek in the tracefile.
275 *Input params
276 * ep : a pointer to event's position structure
277 * block_number : the block number of the event
278 * index_in_block : the index of the event within the block
279 ****************************************************************************/
280
281 void ltt_event_position_set(LttEventPosition *ep,
282 unsigned block_number, unsigned index_in_block)
283 {
284 if(ep->block_num != block_number || ep->event_num != index_in_block)
285 ep->old_position = FALSE;
286
287 ep->block_num = block_number;
288 ep->event_num = index_in_block;
289
290 }
291
292 /*****************************************************************************
293 * Function name
294 * ltt_event_position_compare : compare two positions
295 * A NULL value is infinite.
296 * Input params
297 * ep1 : a pointer to event's position structure
298 * ep2 : a pointer to event's position structure
299 * Return
300 * -1 is ep1 < ep2
301 * 1 if ep1 > ep2
302 * 0 if ep1 == ep2
303 ****************************************************************************/
304
305
306 gint ltt_event_position_compare(const LttEventPosition *ep1,
307 const LttEventPosition *ep2)
308 {
309 if(ep1->tf != ep2->tf)
310 g_error("ltt_event_position_compare on different tracefiles makes no sense");
311 if(ep1 == NULL && ep2 == NULL)
312 return 0;
313 if(ep1 != NULL && ep2 == NULL)
314 return -1;
315 if(ep1 == NULL && ep2 != NULL)
316 return 1;
317
318 if(ep1->block_num < ep2->block_num)
319 return -1;
320 if(ep1->block_num > ep2->block_num)
321 return 1;
322 if(ep1->event_num < ep2->event_num)
323 return -1;
324 if(ep1->event_num > ep2->event_num)
325 return 1;
326 return 0;
327 }
328
329 /*****************************************************************************
330 * Function name
331 * ltt_event_event_position_compare : compare two positions, one in event,
332 * other in position opaque structure.
333 * Input params
334 * event : a pointer to event structure
335 * ep : a pointer to event's position structure
336 * Return
337 * -1 is event < ep
338 * 1 if event > ep
339 * 0 if event == ep
340 ****************************************************************************/
341
342 gint ltt_event_event_position_compare(const LttEvent *event,
343 const LttEventPosition *ep)
344 {
345 if(event == NULL && ep == NULL)
346 return 0;
347 if(event != NULL && ep == NULL)
348 return -1;
349 if(event == NULL && ep != NULL)
350 return 1;
351
352 g_assert(event->tracefile == ep->tf);
353
354 if(event->which_block < ep->block_num)
355 return -1;
356 if(event->which_block > ep->block_num)
357 return 1;
358 if(event->which_event < ep->event_num)
359 return -1;
360 if(event->which_event > ep->event_num)
361 return 1;
362 return 0;
363 }
364
365 /*****************************************************************************
366 * Function name
367 * ltt_event_position_copy : copy position
368 * Input params
369 * src : a pointer to event's position structure source
370 * dest : a pointer to event's position structure dest
371 * Return
372 * void
373 ****************************************************************************/
374 void ltt_event_position_copy(LttEventPosition *dest,
375 const LttEventPosition *src)
376 {
377 if(src == NULL)
378 dest = NULL;
379 else
380 *dest = *src;
381 }
382
383
384 /*****************************************************************************
385 *Function name
386 * ltt_event_cpu_i: get the cpu id where the event happens
387 *Input params
388 * e : an instance of an event type
389 *Return value
390 * unsigned : the cpu id
391 ****************************************************************************/
392
393 unsigned ltt_event_cpu_id(LttEvent *e)
394 {
395 char * c1, * c2, * c3;
396 c1 = strrchr(e->tracefile->name,'\\');
397 c2 = strrchr(e->tracefile->name,'/');
398 if(c1 == NULL && c2 == NULL){
399 return (unsigned)atoi(e->tracefile->name);
400 }else if(c1 == NULL){
401 c2++;
402 return (unsigned)atoi(c2);
403 }else if(c2 == NULL){
404 c1++;
405 return (unsigned)atoi(c1);
406 }else{
407 c3 = (c1 > c2) ? c1 : c2;
408 c3++;
409 return (unsigned)atoi(c3);
410 }
411 }
412
413 /*****************************************************************************
414 *Function name
415 * ltt_event_data : get the raw data for the event
416 *Input params
417 * e : an instance of an event type
418 *Return value
419 * void * : pointer to the raw data for the event
420 ****************************************************************************/
421
422 void *ltt_event_data(LttEvent *e)
423 {
424 return e->data;
425 }
426
427 /*****************************************************************************
428 *Function name
429 * ltt_event_field_element_number
430 * : The number of elements in a sequence field is specific
431 * to each event. This function returns the number of
432 * elements for an array or sequence field in an event.
433 *Input params
434 * e : an instance of an event type
435 * f : a field of the instance
436 *Return value
437 * unsigned : the number of elements for an array/sequence field
438 ****************************************************************************/
439
440 unsigned ltt_event_field_element_number(LttEvent *e, LttField *f)
441 {
442 if(f->field_type->type_class != LTT_ARRAY &&
443 f->field_type->type_class != LTT_SEQUENCE)
444 return 0;
445
446 if(f->field_type->type_class == LTT_ARRAY)
447 return f->field_type->element_number;
448 return (unsigned) getIntNumber(f->sequ_number_size, e + f->offset_root);
449 }
450
451 /*****************************************************************************
452 *Function name
453 * ltt_event_field_element_select
454 * : Set the currently selected element for a sequence or
455 * array field
456 *Input params
457 * e : an instance of an event type
458 * f : a field of the instance
459 * i : the ith element
460 ****************************************************************************/
461
462 void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i)
463 {
464 unsigned element_number;
465 LttField *fld;
466 unsigned int k;
467 int size;
468 void *evD;
469
470 if(f->field_type->type_class != LTT_ARRAY &&
471 f->field_type->type_class != LTT_SEQUENCE)
472 return ;
473
474 element_number = ltt_event_field_element_number(e,f);
475 /* Sanity check for i : 1..n only, and must be lower or equal element_number
476 */
477 if(element_number < i || i == 0) return;
478
479 fld = f->child[0];
480
481 evD = e->data + f->offset_root;
482 size = 0;
483 for(k=0;k<i;k++){
484 size += ltt_event_refresh_fields(f->offset_root+size,size, fld, evD+size);
485 }
486 f->current_element = i - 1;
487 }
488
489 /*****************************************************************************
490 * These functions extract data from an event after architecture specific
491 * conversions
492 ****************************************************************************/
493
494 unsigned ltt_event_get_unsigned(LttEvent *e, LttField *f)
495 {
496 int revFlag = e->tracefile->trace->my_arch_endian ==
497 e->tracefile->trace->system_description->endian ? 0:1;
498 LttTypeEnum t = f->field_type->type_class;
499
500 g_assert(t == LTT_UINT || t == LTT_ENUM);
501
502 if(f->field_size == 1){
503 guint8 x = *(guint8 *)(e->data + f->offset_root);
504 return (unsigned int) x;
505 }else if(f->field_size == 2){
506 guint16 x = *(guint16 *)(e->data + f->offset_root);
507 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
508 return (unsigned int) (revFlag ? GUINT16_FROM_BE(x): x);
509 else
510 return (unsigned int) (revFlag ? GUINT16_FROM_LE(x): x);
511 }else if(f->field_size == 4){
512 guint32 x = *(guint32 *)(e->data + f->offset_root);
513 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
514 return (unsigned int) (revFlag ? GUINT32_FROM_BE(x): x);
515 else
516 return (unsigned int) (revFlag ? GUINT32_FROM_LE(x): x);
517 }else if(f->field_size == 8){
518 guint64 x = *(guint64 *)(e->data + f->offset_root);
519 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
520 return (unsigned int) (revFlag ? GUINT64_FROM_BE(x): x);
521 else
522 return (unsigned int) (revFlag ? GUINT64_FROM_LE(x): x);
523 }
524 g_critical("ltt_event_get_unsigned : field size %i unknown", f->field_size);
525 return 0;
526 }
527
528 int ltt_event_get_int(LttEvent *e, LttField *f)
529 {
530 int revFlag = e->tracefile->trace->my_arch_endian ==
531 e->tracefile->trace->system_description->endian ? 0:1;
532
533 g_assert(f->field_type->type_class == LTT_INT);
534
535 if(f->field_size == 1){
536 gint8 x = *(gint8 *)(e->data + f->offset_root);
537 return (int) x;
538 }else if(f->field_size == 2){
539 gint16 x = *(gint16 *)(e->data + f->offset_root);
540 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
541 return (int) (revFlag ? GINT16_FROM_BE(x): x);
542 else
543 return (int) (revFlag ? GINT16_FROM_LE(x): x);
544 }else if(f->field_size == 4){
545 gint32 x = *(gint32 *)(e->data + f->offset_root);
546 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
547 return (int) (revFlag ? GINT32_FROM_BE(x): x);
548 else
549 return (int) (revFlag ? GINT32_FROM_LE(x): x);
550 }else if(f->field_size == 8){
551 gint64 x = *(gint64 *)(e->data + f->offset_root);
552 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
553 return (int) (revFlag ? GINT64_FROM_BE(x): x);
554 else
555 return (int) (revFlag ? GINT64_FROM_LE(x): x);
556 }
557 g_critical("ltt_event_get_int : field size %i unknown", f->field_size);
558 return 0;
559 }
560
561 unsigned long ltt_event_get_long_unsigned(LttEvent *e, LttField *f)
562 {
563 int revFlag = e->tracefile->trace->my_arch_endian ==
564 e->tracefile->trace->system_description->endian ? 0:1;
565 LttTypeEnum t = f->field_type->type_class;
566
567 g_assert(t == LTT_UINT || t == LTT_ENUM);
568
569 if(f->field_size == 1){
570 guint8 x = *(guint8 *)(e->data + f->offset_root);
571 return (unsigned long) x;
572 }else if(f->field_size == 2){
573 guint16 x = *(guint16 *)(e->data + f->offset_root);
574 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
575 return (unsigned long) (revFlag ? GUINT16_FROM_BE(x): x);
576 else
577 return (unsigned long) (revFlag ? GUINT16_FROM_LE(x): x);
578 }else if(f->field_size == 4){
579 guint32 x = *(guint32 *)(e->data + f->offset_root);
580 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
581 return (unsigned long) (revFlag ? GUINT32_FROM_BE(x): x);
582 else
583 return (unsigned long) (revFlag ? GUINT32_FROM_LE(x): x);
584 }else if(f->field_size == 8){
585 guint64 x = *(guint64 *)(e->data + f->offset_root);
586 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
587 return (unsigned long) (revFlag ? GUINT64_FROM_BE(x): x);
588 else
589 return (unsigned long) (revFlag ? GUINT64_FROM_LE(x): x);
590 }
591 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f->field_size);
592 return 0;
593 }
594
595 long int ltt_event_get_long_int(LttEvent *e, LttField *f)
596 {
597 int revFlag = e->tracefile->trace->my_arch_endian ==
598 e->tracefile->trace->system_description->endian ? 0:1;
599
600 g_assert( f->field_type->type_class == LTT_INT);
601
602 if(f->field_size == 1){
603 gint8 x = *(gint8 *)(e->data + f->offset_root);
604 return (long) x;
605 }else if(f->field_size == 2){
606 gint16 x = *(gint16 *)(e->data + f->offset_root);
607 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
608 return (long) (revFlag ? GINT16_FROM_BE(x): x);
609 else
610 return (long) (revFlag ? GINT16_FROM_LE(x): x);
611 }else if(f->field_size == 4){
612 gint32 x = *(gint32 *)(e->data + f->offset_root);
613 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
614 return (long) (revFlag ? GINT32_FROM_BE(x): x);
615 else
616 return (long) (revFlag ? GINT32_FROM_LE(x): x);
617 }else if(f->field_size == 8){
618 gint64 x = *(gint64 *)(e->data + f->offset_root);
619 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
620 return (long) (revFlag ? GINT64_FROM_BE(x): x);
621 else
622 return (long) (revFlag ? GINT64_FROM_LE(x): x);
623 }
624 g_critical("ltt_event_get_long_int : field size %i unknown", f->field_size);
625 return 0;
626 }
627
628 float ltt_event_get_float(LttEvent *e, LttField *f)
629 {
630 int revFlag = e->tracefile->trace->my_arch_endian ==
631 e->tracefile->trace->system_description->endian ? 0:1;
632
633 g_assert(f->field_type->type_class == LTT_FLOAT && f->field_size == 4);
634
635 if(revFlag == 0) return *(float *)(e->data + f->offset_root);
636 else{
637 guint32 aInt;
638 memcpy((void*)&aInt, e->data + f->offset_root, 4);
639 aInt = ___swab32(aInt);
640 return *((float*)&aInt);
641 }
642 }
643
644 double ltt_event_get_double(LttEvent *e, LttField *f)
645 {
646 int revFlag = e->tracefile->trace->my_arch_endian ==
647 e->tracefile->trace->system_description->endian ? 0:1;
648
649 g_assert(f->field_type->type_class == LTT_FLOAT && f->field_size == 8);
650
651 if(revFlag == 0) return *(double *)(e->data + f->offset_root);
652 else{
653 guint64 aInt;
654 memcpy((void*)&aInt, e->data + f->offset_root, 8);
655 aInt = ___swab64(aInt);
656 return *((double *)&aInt);
657 }
658 }
659
660 /*****************************************************************************
661 * The string obtained is only valid until the next read from
662 * the same tracefile.
663 ****************************************************************************/
664
665 char *ltt_event_get_string(LttEvent *e, LttField *f)
666 {
667 g_assert(f->field_type->type_class == LTT_STRING);
668
669 return (char*)g_strdup((char*)(e->data + f->offset_root));
670 }
This page took 0.055705 seconds and 4 git commands to generate.