network byte order + state multitraces fix
[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 * 2006 Mathieu Desnoyers
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License Version 2.1 as published by the Free Software Foundation.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <glib.h>
28
29 #include <asm/types.h>
30 #include <byteswap.h>
31
32 #include "parser.h"
33 #include <ltt/ltt.h>
34 #include "ltt-private.h"
35 #include <ltt/event.h>
36 #include <ltt/trace.h>
37 #include <ltt/ltt-types.h>
38
39
40
41 void compute_fields_offsets(LttTracefile *tf,
42 LttFacility *fac, LttField *field, off_t *offset, void *root);
43
44
45 LttEvent *ltt_event_new()
46 {
47 return g_new(LttEvent, 1);
48 }
49
50 void ltt_event_destroy(LttEvent *event)
51 {
52 g_free(event);
53 }
54
55
56 /*****************************************************************************
57 *Function name
58 * ltt_event_eventtype_id: get event type id
59 * (base id + position of the event)
60 *Input params
61 * e : an instance of an event type
62 *Return value
63 * unsigned : event type id
64 ****************************************************************************/
65
66 unsigned ltt_event_eventtype_id(const LttEvent *e)
67 {
68 return (unsigned) e->event_id;
69 }
70
71 /*****************************************************************************
72 *Function name
73 * ltt_event_facility : get the facility of the event
74 *Input params
75 * e : an instance of an event type
76 *Return value
77 * LttFacility * : the facility of the event
78 ****************************************************************************/
79
80 LttFacility *ltt_event_facility(const LttEvent *e)
81 {
82 LttTrace * trace = e->tracefile->trace;
83 unsigned id = e->facility_id;
84 LttFacility *facility = ltt_trace_facility_by_id(trace,id);
85
86 g_assert(facility->exists);
87
88 return facility;
89 }
90
91 /*****************************************************************************
92 *Function name
93 * ltt_event_facility_id : get the facility id of the event
94 *Input params
95 * e : an instance of an event type
96 *Return value
97 * unsigned : the facility of the event
98 ****************************************************************************/
99
100 unsigned ltt_event_facility_id(const LttEvent *e)
101 {
102 return e->facility_id;
103 }
104
105 /*****************************************************************************
106 *Function name
107 * ltt_event_eventtype : get the event type of the event
108 *Input params
109 * e : an instance of an event type
110 *Return value
111 * LttEventType * : the event type of the event
112 ****************************************************************************/
113
114 LttEventType *ltt_event_eventtype(const LttEvent *e)
115 {
116 LttFacility* facility = ltt_event_facility(e);
117 if(!facility) return NULL;
118 return &g_array_index(facility->events, LttEventType, e->event_id);
119 }
120
121
122 /*****************************************************************************
123 *Function name
124 * ltt_event_time : get the time of the event
125 *Input params
126 * e : an instance of an event type
127 *Return value
128 * LttTime : the time of the event
129 ****************************************************************************/
130
131 LttTime ltt_event_time(const LttEvent *e)
132 {
133 return e->event_time;
134 }
135
136 /*****************************************************************************
137 *Function name
138 * ltt_event_time : get the cycle count of the event
139 *Input params
140 * e : an instance of an event type
141 *Return value
142 * LttCycleCount : the cycle count of the event
143 ****************************************************************************/
144
145 LttCycleCount ltt_event_cycle_count(const LttEvent *e)
146 {
147 return e->tsc;
148 }
149
150
151
152 /*****************************************************************************
153 *Function name
154 * ltt_event_position_get : get the event position data
155 *Input params
156 * e : an instance of an event type
157 * ep : a pointer to event's position structure
158 * tf : tracefile pointer
159 * block : current block
160 * offset : current offset
161 * tsc : current tsc
162 ****************************************************************************/
163 void ltt_event_position_get(LttEventPosition *ep, LttTracefile **tf,
164 guint *block, guint *offset, guint64 *tsc)
165 {
166 *tf = ep->tracefile;
167 *block = ep->block;
168 *offset = ep->offset;
169 *tsc = ep->tsc;
170 }
171
172
173 /*****************************************************************************
174 *Function name
175 * ltt_event_position : get the event's position
176 *Input params
177 * e : an instance of an event type
178 * ep : a pointer to event's position structure
179 ****************************************************************************/
180
181 void ltt_event_position(LttEvent *e, LttEventPosition *ep)
182 {
183 ep->tracefile = e->tracefile;
184 ep->block = e->block;
185 ep->offset = e->offset;
186 ep->tsc = e->tsc;
187 }
188
189 LttEventPosition * ltt_event_position_new()
190 {
191 return g_new(LttEventPosition, 1);
192 }
193
194
195 /*****************************************************************************
196 * Function name
197 * ltt_event_position_compare : compare two positions
198 * A NULL value is infinite.
199 * Input params
200 * ep1 : a pointer to event's position structure
201 * ep2 : a pointer to event's position structure
202 * Return
203 * -1 is ep1 < ep2
204 * 1 if ep1 > ep2
205 * 0 if ep1 == ep2
206 ****************************************************************************/
207
208
209 gint ltt_event_position_compare(const LttEventPosition *ep1,
210 const LttEventPosition *ep2)
211 {
212 if(ep1 == NULL && ep2 == NULL)
213 return 0;
214 if(ep1 != NULL && ep2 == NULL)
215 return -1;
216 if(ep1 == NULL && ep2 != NULL)
217 return 1;
218
219 if(ep1->tracefile != ep2->tracefile)
220 g_error("ltt_event_position_compare on different tracefiles makes no sense");
221
222 if(ep1->block < ep2->block)
223 return -1;
224 if(ep1->block > ep2->block)
225 return 1;
226 if(ep1->offset < ep2->offset)
227 return -1;
228 if(ep1->offset > ep2->offset)
229 return 1;
230 return 0;
231 }
232
233 /*****************************************************************************
234 * Function name
235 * ltt_event_position_copy : copy position
236 * Input params
237 * src : a pointer to event's position structure source
238 * dest : a pointer to event's position structure dest
239 * Return
240 * void
241 ****************************************************************************/
242 void ltt_event_position_copy(LttEventPosition *dest,
243 const LttEventPosition *src)
244 {
245 if(src == NULL)
246 dest = NULL;
247 else
248 *dest = *src;
249 }
250
251
252
253 LttTracefile *ltt_event_position_tracefile(LttEventPosition *ep)
254 {
255 return ep->tracefile;
256 }
257
258 /*****************************************************************************
259 *Function name
260 * ltt_event_cpu_i: get the cpu id where the event happens
261 *Input params
262 * e : an instance of an event type
263 *Return value
264 * unsigned : the cpu id
265 ****************************************************************************/
266
267 unsigned ltt_event_cpu_id(LttEvent *e)
268 {
269 return e->tracefile->cpu_num;
270 }
271
272 /*****************************************************************************
273 *Function name
274 * ltt_event_data : get the raw data for the event
275 *Input params
276 * e : an instance of an event type
277 *Return value
278 * void * : pointer to the raw data for the event
279 ****************************************************************************/
280
281 void *ltt_event_data(LttEvent *e)
282 {
283 return e->data;
284 }
285
286 /*****************************************************************************
287 *Function name
288 * ltt_event_field_element_number
289 * : The number of elements in a sequence field is specific
290 * to each event. This function returns the number of
291 * elements for an array or sequence field in an event.
292 *Input params
293 * e : an instance of an event type
294 * f : a field of the instance
295 *Return value
296 * unsigned : the number of elements for an array/sequence field
297 ****************************************************************************/
298 guint64 ltt_event_field_element_number(LttEvent *e, LttField *f)
299 {
300 if(f->field_type.type_class != LTT_ARRAY &&
301 f->field_type.type_class != LTT_SEQUENCE)
302 return 0;
303
304 if(f->field_type.type_class == LTT_ARRAY)
305 return f->field_type.size;
306 return ltt_event_get_long_unsigned(e, &g_array_index(f->field_type.fields,
307 LttField, 0));
308 }
309
310 /*****************************************************************************
311 *Function name
312 * ltt_event_field_element_select
313 * : Set the currently selected element for a sequence or
314 * array field
315 * O(1) because of offset array.
316 *Input params
317 * e : an instance of an event type
318 * f : a field of the instance
319 * i : the ith element (0, ...)
320 *returns : the child field, at the right index, updated.
321 ****************************************************************************/
322 LttField *ltt_event_field_element_select(LttEvent *e, LttField *f, gulong i)
323 {
324 gulong element_number;
325 LttField *field;
326 unsigned int k;
327 size_t size;
328 LttEventType *event_type;
329 off_t new_offset;
330
331 if(f->field_type.type_class != LTT_ARRAY &&
332 f->field_type.type_class != LTT_SEQUENCE)
333 return NULL;
334
335 element_number = ltt_event_field_element_number(e,f);
336 event_type = ltt_event_eventtype(e);
337 /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number
338 */
339 if(i >= element_number) return NULL;
340
341 if(f->field_type.type_class == LTT_ARRAY) {
342 field = &g_array_index(f->field_type.fields, LttField, 0);
343 } else {
344 field = &g_array_index(f->field_type.fields, LttField, 1);
345 }
346
347 if(field->field_size != 0) {
348 if(f->array_offset + (i * field->field_size) == field->offset_root)
349 return field; /* fixed length child, already at the right offset */
350 else
351 new_offset = f->array_offset + (i * field->field_size);
352 } else {
353 /* Var. len. child */
354 new_offset = g_array_index(f->dynamic_offsets, off_t, i);
355 }
356 compute_fields_offsets(e->tracefile,
357 ltt_event_facility(e), field, &new_offset, e->data);
358
359 return field;
360 }
361
362
363 off_t ltt_event_field_offset(LttEvent *e, LttField *f)
364 {
365 return f->offset_root;
366 }
367
368
369
370 /*****************************************************************************
371 * These functions extract data from an event after architecture specific
372 * conversions
373 ****************************************************************************/
374 guint32 ltt_event_get_unsigned(LttEvent *e, LttField *f)
375 {
376 gboolean reverse_byte_order;
377 if(unlikely(f->field_type.network)) {
378 reverse_byte_order = (g_ntohs(0x1) != 0x1);
379 } else {
380 reverse_byte_order = LTT_GET_BO(e->tracefile);
381 }
382
383 switch(f->field_size) {
384 case 1:
385 {
386 guint8 x = *(guint8 *)(e->data + f->offset_root);
387 return (guint32) x;
388 }
389 break;
390 case 2:
391 return (guint32)ltt_get_uint16(reverse_byte_order, e->data + f->offset_root);
392 break;
393 case 4:
394 return (guint32)ltt_get_uint32(reverse_byte_order, e->data + f->offset_root);
395 break;
396 case 8:
397 default:
398 g_critical("ltt_event_get_unsigned : field size %i unknown", f->field_size);
399 return 0;
400 break;
401 }
402 }
403
404 gint32 ltt_event_get_int(LttEvent *e, LttField *f)
405 {
406 gboolean reverse_byte_order;
407 if(unlikely(f->field_type.network)) {
408 reverse_byte_order = (g_ntohs(0x1) != 0x1);
409 } else {
410 reverse_byte_order = LTT_GET_BO(e->tracefile);
411 }
412
413 switch(f->field_size) {
414 case 1:
415 {
416 gint8 x = *(gint8 *)(e->data + f->offset_root);
417 return (gint32) x;
418 }
419 break;
420 case 2:
421 return (gint32)ltt_get_int16(reverse_byte_order, e->data + f->offset_root);
422 break;
423 case 4:
424 return (gint32)ltt_get_int32(reverse_byte_order, e->data + f->offset_root);
425 break;
426 case 8:
427 default:
428 g_critical("ltt_event_get_int : field size %i unknown", f->field_size);
429 return 0;
430 break;
431 }
432 }
433
434 guint64 ltt_event_get_long_unsigned(LttEvent *e, LttField *f)
435 {
436 gboolean reverse_byte_order;
437 if(unlikely(f->field_type.network)) {
438 reverse_byte_order = (g_ntohs(0x1) != 0x1);
439 } else {
440 reverse_byte_order = LTT_GET_BO(e->tracefile);
441 }
442
443 switch(f->field_size) {
444 case 1:
445 {
446 guint8 x = *(guint8 *)(e->data + f->offset_root);
447 return (guint64) x;
448 }
449 break;
450 case 2:
451 return (guint64)ltt_get_uint16(reverse_byte_order, e->data + f->offset_root);
452 break;
453 case 4:
454 return (guint64)ltt_get_uint32(reverse_byte_order, e->data + f->offset_root);
455 break;
456 case 8:
457 return ltt_get_uint64(reverse_byte_order, e->data + f->offset_root);
458 break;
459 default:
460 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f->field_size);
461 return 0;
462 break;
463 }
464 }
465
466 gint64 ltt_event_get_long_int(LttEvent *e, LttField *f)
467 {
468 gboolean reverse_byte_order;
469 if(unlikely(f->field_type.network)) {
470 reverse_byte_order = (g_ntohs(0x1) != 0x1);
471 } else {
472 reverse_byte_order = LTT_GET_BO(e->tracefile);
473 }
474
475 switch(f->field_size) {
476 case 1:
477 {
478 gint8 x = *(gint8 *)(e->data + f->offset_root);
479 return (gint64) x;
480 }
481 break;
482 case 2:
483 return (gint64)ltt_get_int16(reverse_byte_order, e->data + f->offset_root);
484 break;
485 case 4:
486 return (gint64)ltt_get_int32(reverse_byte_order, e->data + f->offset_root);
487 break;
488 case 8:
489 return ltt_get_int64(reverse_byte_order, e->data + f->offset_root);
490 break;
491 default:
492 g_critical("ltt_event_get_long_int : field size %i unknown", f->field_size);
493 return 0;
494 break;
495 }
496 }
497
498 float ltt_event_get_float(LttEvent *e, LttField *f)
499 {
500 gboolean reverse_byte_order;
501 if(unlikely(f->field_type.network)) {
502 reverse_byte_order = (g_ntohs(0x1) != 0x1);
503 } else {
504 g_assert(LTT_HAS_FLOAT(e->tracefile));
505 reverse_byte_order = LTT_GET_FLOAT_BO(e->tracefile);
506 }
507
508 g_assert(f->field_type.type_class == LTT_FLOAT && f->field_size == 4);
509
510 if(reverse_byte_order == 0) return *(float *)(e->data + f->offset_root);
511 else{
512 void *ptr = e->data + f->offset_root;
513 guint32 value = bswap_32(*(guint32*)ptr);
514 return *(float*)&value;
515 }
516 }
517
518 double ltt_event_get_double(LttEvent *e, LttField *f)
519 {
520 gboolean reverse_byte_order;
521 if(unlikely(f->field_type.network)) {
522 reverse_byte_order = (g_ntohs(0x1) != 0x1);
523 } else {
524 g_assert(LTT_HAS_FLOAT(e->tracefile));
525 reverse_byte_order = LTT_GET_FLOAT_BO(e->tracefile);
526 }
527
528 if(f->field_size == 4)
529 return ltt_event_get_float(e, f);
530
531 g_assert(f->field_type.type_class == LTT_FLOAT && f->field_size == 8);
532
533 if(reverse_byte_order == 0) return *(double *)(e->data + f->offset_root);
534 else {
535 void *ptr = e->data + f->offset_root;
536 guint64 value = bswap_64(*(guint64*)ptr);
537 return *(double*)&value;
538 }
539 }
540
541 /*****************************************************************************
542 * The string obtained is only valid until the next read from
543 * the same tracefile.
544 ****************************************************************************/
545 char *ltt_event_get_string(LttEvent *e, LttField *f)
546 {
547 g_assert(f->field_type.type_class == LTT_STRING);
548
549 return (gchar*)g_strdup((gchar*)(e->data + f->offset_root));
550 }
551
552 /*****************************************************************************
553 *Function name
554 * compute_fields_offsets : set the precomputable offset of the fields
555 *Input params
556 * fac : facility
557 * field : the field
558 * offset : pointer to the current offset, must be incremented
559 ****************************************************************************/
560
561
562 void compute_fields_offsets(LttTracefile *tf,
563 LttFacility *fac, LttField *field, off_t *offset, void *root)
564 {
565 LttType *type = &field->field_type;
566
567 switch(type->type_class) {
568 case LTT_INT_FIXED:
569 case LTT_UINT_FIXED:
570 case LTT_POINTER:
571 case LTT_CHAR:
572 case LTT_UCHAR:
573 case LTT_SHORT:
574 case LTT_USHORT:
575 case LTT_INT:
576 case LTT_UINT:
577 case LTT_LONG:
578 case LTT_ULONG:
579 case LTT_SIZE_T:
580 case LTT_SSIZE_T:
581 case LTT_OFF_T:
582 case LTT_FLOAT:
583 case LTT_ENUM:
584 if(field->fixed_root == FIELD_VARIABLE) {
585 /* Align offset on type size */
586 *offset += ltt_align(*offset, get_alignment(field),
587 fac->alignment);
588 /* remember offset */
589 field->offset_root = *offset;
590 /* Increment offset */
591 *offset += field->field_size;
592 } else {
593 //g_debug("type before offset : %llu %llu %u\n", *offset,
594 // field->offset_root,
595 // field->field_size);
596 *offset = field->offset_root;
597 *offset += field->field_size;
598 //g_debug("type after offset : %llu\n", *offset);
599 }
600 break;
601 case LTT_STRING:
602 if(field->fixed_root == FIELD_VARIABLE) {
603 field->offset_root = *offset;
604 }
605 *offset += strlen((gchar*)(root+*offset)) + 1;
606 /* Realign the data */
607 *offset += ltt_align(*offset, fac->pointer_size,
608 fac->alignment);
609 break;
610 case LTT_ARRAY:
611 g_assert(type->fields->len == 1);
612 {
613 off_t local_offset;
614 LttField *child = &g_array_index(type->fields, LttField, 0);
615 if(field->fixed_root == FIELD_VARIABLE) {
616 *offset += ltt_align(*offset, get_alignment(field),
617 fac->alignment);
618 /* remember offset */
619 field->offset_root = *offset;
620 field->array_offset = *offset;
621 }
622
623 if(field->field_size != 0) {
624 /* Increment offset */
625 /* field_size is the array size in bytes */
626 *offset = field->offset_root + field->field_size;
627 } else {
628 guint i;
629 *offset = field->array_offset;
630 field->dynamic_offsets = g_array_set_size(field->dynamic_offsets,
631 0);
632 for(i=0; i<type->size; i++) {
633 g_array_append_val(field->dynamic_offsets, *offset);
634 compute_fields_offsets(tf, fac, child, offset, root);
635 }
636 }
637 // local_offset = field->array_offset;
638 // /* Set the offset at position 0 */
639 // compute_fields_offsets(tf, fac, child, &local_offset, root);
640 }
641 break;
642 case LTT_SEQUENCE:
643 g_assert(type->fields->len == 2);
644 {
645 off_t local_offset;
646 LttField *child;
647 guint i;
648 guint num_elem;
649 if(field->fixed_root == FIELD_VARIABLE) {
650 *offset += ltt_align(*offset, get_alignment(field),
651 fac->alignment);
652 /* remember offset */
653 field->offset_root = *offset;
654
655 child = &g_array_index(type->fields, LttField, 0);
656 compute_fields_offsets(tf, fac, child, offset, root);
657 child = &g_array_index(type->fields, LttField, 1);
658 *offset += ltt_align(*offset, get_alignment(child),
659 fac->alignment);
660 field->array_offset = *offset;
661
662 } else {
663 child = &g_array_index(type->fields, LttField, 1);
664 }
665 *offset = field->array_offset;
666 field->dynamic_offsets = g_array_set_size(field->dynamic_offsets,
667 0);
668 num_elem = ltt_event_field_element_number(&tf->event, field);
669 for(i=0; i<num_elem; i++) {
670 g_array_append_val(field->dynamic_offsets, *offset);
671 compute_fields_offsets(tf, fac, child, offset, root);
672 }
673 g_assert(num_elem == field->dynamic_offsets->len);
674
675 /* Realign the data */
676 *offset += ltt_align(*offset, fac->pointer_size,
677 fac->alignment);
678
679 // local_offset = field->array_offset;
680 // /* Set the offset at position 0 */
681 // compute_fields_offsets(tf, fac, child, &local_offset, root);
682 }
683 break;
684 case LTT_STRUCT:
685 {
686 LttField *child;
687 guint i;
688 gint ret=0;
689 if(field->fixed_root == FIELD_VARIABLE) {
690 *offset += ltt_align(*offset, get_alignment(fac, field),
691 fac->alignment);
692 /* remember offset */
693 field->offset_root = *offset;
694 } else {
695 *offset = field->offset_root;
696 }
697 for(i=0; i<type->fields->len; i++) {
698 child = &g_array_index(type->fields, LttField, i);
699 compute_fields_offsets(tf, fac, child, offset, root);
700 }
701 }
702 break;
703 case LTT_UNION:
704 {
705 LttField *child;
706 guint i;
707 gint ret=0;
708 if(field->fixed_root == FIELD_VARIABLE) {
709 *offset += ltt_align(*offset, get_alignment(field),
710 fac->alignment);
711 /* remember offset */
712 field->offset_root = *offset;
713 }
714 for(i=0; i<type->fields->len; i++) {
715 *offset = field->offset_root;
716 child = &g_array_index(type->fields, LttField, i);
717 compute_fields_offsets(tf, fac, child, offset, root);
718 }
719 *offset = field->offset_root + field->field_size;
720 }
721 break;
722 case LTT_NONE:
723 default:
724 g_error("compute_fields_offsets : unknown type");
725 }
726
727 }
728
729
730 /*****************************************************************************
731 *Function name
732 * compute_offsets : set the dynamically computable offsets of an event type
733 *Input params
734 * tf : tracefile
735 * event : event type
736 *
737 ****************************************************************************/
738 void compute_offsets(LttTracefile *tf, LttFacility *fac,
739 LttEventType *event, off_t *offset, void *root)
740 {
741 guint i;
742
743 /* compute all variable offsets */
744 for(i=0; i<event->fields->len; i++) {
745 //g_debug("computing offset %u of %u\n", i, event->fields->len-1);
746 LttField *field = &g_array_index(event->fields, LttField, i);
747 compute_fields_offsets(tf, fac, field, offset, root);
748 }
749
750 }
751
This page took 0.044419 seconds and 4 git commands to generate.