void compute_fields_offsets(LttTracefile *tf,
- LttFacility *fac, LttField *field, off_t *offset, void *root);
+ LttFacility *fac, LttField *field, off_t *offset, void *root, guint is_compact);
LttEvent *ltt_event_new()
new_offset = g_array_index(f->dynamic_offsets, off_t, i);
}
compute_fields_offsets(e->tracefile,
- ltt_event_facility(e), field, &new_offset, e->data);
+ ltt_event_facility(e), field, &new_offset, e->data, 0);
return field;
}
void compute_fields_offsets(LttTracefile *tf,
- LttFacility *fac, LttField *field, off_t *offset, void *root)
+ LttFacility *fac, LttField *field, off_t *offset, void *root, guint is_compact)
{
LttType *type = &field->field_type;
+ if(unlikely(is_compact)) {
+ g_assert(field->field_size != 0);
+ /* FIXME THIS IS A HUUUUUGE hack :
+ * offset is between the compact_data field in struct LttEvent
+ * and the address of the field root in the memory map.
+ * ark. Both will stay at the same addresses while the event
+ * is readable, so it's ok.
+ */
+ field->offset_root = (unsigned long)(&tf->event.compact_data)
+ - (unsigned long)root;
+ field->fixed_root = FIELD_FIXED;
+ return;
+ }
+
switch(type->type_class) {
case LTT_INT_FIXED:
case LTT_UINT_FIXED:
0);
for(i=0; i<type->size; i++) {
g_array_append_val(field->dynamic_offsets, *offset);
- compute_fields_offsets(tf, fac, child, offset, root);
+ compute_fields_offsets(tf, fac, child, offset, root, is_compact);
}
}
// local_offset = field->array_offset;
field->offset_root = *offset;
child = &g_array_index(type->fields, LttField, 0);
- compute_fields_offsets(tf, fac, child, offset, root);
+ compute_fields_offsets(tf, fac, child, offset, root, is_compact);
child = &g_array_index(type->fields, LttField, 1);
*offset += ltt_align(*offset, get_alignment(child),
fac->alignment);
num_elem = ltt_event_field_element_number(&tf->event, field);
for(i=0; i<num_elem; i++) {
g_array_append_val(field->dynamic_offsets, *offset);
- compute_fields_offsets(tf, fac, child, offset, root);
+ compute_fields_offsets(tf, fac, child, offset, root, is_compact);
}
g_assert(num_elem == field->dynamic_offsets->len);
}
for(i=0; i<type->fields->len; i++) {
child = &g_array_index(type->fields, LttField, i);
- compute_fields_offsets(tf, fac, child, offset, root);
+ compute_fields_offsets(tf, fac, child, offset, root, is_compact);
}
}
break;
for(i=0; i<type->fields->len; i++) {
*offset = field->offset_root;
child = &g_array_index(type->fields, LttField, i);
- compute_fields_offsets(tf, fac, child, offset, root);
+ compute_fields_offsets(tf, fac, child, offset, root, is_compact);
}
*offset = field->offset_root + field->field_size;
}
for(i=0; i<event->fields->len; i++) {
//g_debug("computing offset %u of %u\n", i, event->fields->len-1);
LttField *field = &g_array_index(event->fields, LttField, i);
- compute_fields_offsets(tf, fac, field, offset, root);
+ if(event->has_compact_data && i == 0)
+ compute_fields_offsets(tf, fac, field, offset, root, 1);
+ else
+ compute_fields_offsets(tf, fac, field, offset, root, 0);
}
}
event_type->index = i;
event_type->facility = f;
+ event_type->has_compact_data = parser_event->compact_data;
+
event_type->fields = g_array_sized_new(FALSE, TRUE,
sizeof(LttField), parser_event->fields.position);
event_type->fields =
LttFacility * facility; //the facility that contains the event type
GArray * fields; //event's fields (LttField)
GData *fields_by_name;
+ int has_compact_data; //event header contains compact data (first field)
};
/* Structure LttEvent and LttEventPosition must begin with the _exact_ same
guint data_size;
guint event_size; //event_size field of the header :
//used to verify data_size from facility.
+ uint32_t compact_data;
int count; //the number of overflow of cycle count
gint64 overflow_nsec; //precalculated nsec for overflows
LttTime start_time;
LttTime start_time_from_tsc;
GArray *compact_facilities;
+ uint8_t compact_event_bits;
GData *tracefiles; //tracefiles groups
};
**************************************************************************/
void getTypeAttributes(parse_file_t *in, type_descriptor_t *t,
- sequence_t * unnamed_types, table_t * named_types)
+ sequence_t * unnamed_types, table_t * named_types)
{
char * token;
int car;
t->fmt = NULL;
t->size = 0;
t->custom_write = 0;
- t->network = 0;
+ t->network = 0;
while(1) {
token = getToken(in);
t->size = getSize(in);
} else if(!strcmp("custom_write", token)) {
t->custom_write = 1;
- } else if(!strcmp("byte_order",token)) {
- getEqual(in);
- car = seekNextChar(in);
- if(car == EOF) in->error(in,"byte order was expected (network?)");
- else if(car == '\"') token = getQuotedString(in);
- else token = getName(in);
- if(!strcmp("network", token)) {
- t->network = 1;
- }
- } else if(!strcmp("write",token)) {
- getEqual(in);
- car = seekNextChar(in);
- if(car == EOF) in->error(in,"write type was expected (custom?)");
- else if(car == '\"') token = getQuotedString(in);
- else token = getName(in);
- if(!strcmp("custom", token)) {
- t->custom_write = 1;
- }
- }
- }
+ } else if(!strcmp("byte_order",token)) {
+ getEqual(in);
+ car = seekNextChar(in);
+ if(car == EOF) in->error(in,"byte order was expected (network?)");
+ else if(car == '\"') token = getQuotedString(in);
+ else token = getName(in);
+ if(!strcmp("network", token)) {
+ t->network = 1;
+ }
+ } else if(!strcmp("write",token)) {
+ getEqual(in);
+ car = seekNextChar(in);
+ if(car == EOF) in->error(in,"write type was expected (custom?)");
+ else if(car == '\"') token = getQuotedString(in);
+ else token = getName(in);
+ if(!strcmp("custom", token)) {
+ t->custom_write = 1;
+ }
+ }
+ }
}
/**************************************************************************
ev->param_buffer = 0;
ev->no_instrument_function = 0;
ev->high_priority = 0;
+ ev->force = 0;
+ ev->compact_data = 0;
while(1) {
token = getToken(in);
ev->no_instrument_function = 1;
else if(!strcmp(token, "high_priority"))
ev->high_priority = 1;
+ else if(!strcmp(token, "force"))
+ ev->force = 1;
+ else if(!strcmp(token, "compact_data"))
+ ev->compact_data = 1;
}
}
}
fac->name = NULL;
fac->arch = NULL;
- fac->user = 0;
+ fac->align = 1;
+ fac->user = 0;
while(1) {
token = getToken(in);
getEqual(in);
car = seekNextChar(in);
if(car == '\"') fac->arch = allocAndCopy(getQuotedString(in));
- else fac->arch = allocAndCopy(getName(in));
- }
+ else fac->arch = allocAndCopy(getName(in));
+ } else if(!strcmp("align", token)) {
+ getEqual(in);
+ fac->align = getSize(in);
+ }
+
}
}
if(strcmp("event",token) == 0){
ev = (event_t*) memAlloc(sizeof(event_t));
sequence_push(&(fac->events),ev);
- parseEvent(in,ev, &(fac->unnamed_types), &(fac->named_types));
+ parseEvent(fac, in, ev, &(fac->unnamed_types), &(fac->named_types));
}else if(strcmp("type",token) == 0){
- parseTypeDefinition(in, &(fac->unnamed_types), &(fac->named_types));
+ parseTypeDefinition(fac, in, &(fac->unnamed_types), &(fac->named_types));
}else if(in->type == FORWARDSLASH){
break;
}else in->error(in,"event or type token expected\n");
/*****************************************************************************
*Function name
* parseEvent : generate event from event definition
- *Input params
+ *Input params
+ * fac : facility holding the event
* in : input file handle
* ev : new event
* unnamed_types : array of unamed types
* ev : new event (parameters are passed to it)
****************************************************************************/
-void parseEvent(parse_file_t *in, event_t * ev, sequence_t * unnamed_types,
+void parseEvent(facility_t *fac, parse_file_t *in, event_t * ev, sequence_t * unnamed_types,
table_t * named_types)
{
char *token;
field_t *f;
+ ev->fac = fac;
sequence_init(&(ev->fields));
//<event name=eventtype_name>
getEventAttributes(in, ev);
if(strcmp("field",token))in->error(in,"expecting a field");
f = (field_t *)memAlloc(sizeof(field_t));
sequence_push(&(ev->fields),f);
- parseFields(in, f, unnamed_types, named_types, 1);
+ parseFields(fac, in, f, unnamed_types, named_types, 1);
break;
default:
in->error(in, "expecting </event> or <field >");
*Function name
* parseField : get field infomation from buffer
*Input params
+ * fac : facility holding the field
* in : input file handle
* f : field
* unnamed_types : array of unamed types
* tag : is field surrounded by a <field> </field> tag ?
****************************************************************************/
-void parseFields(parse_file_t *in, field_t *f,
+void parseFields(facility_t *fac, parse_file_t *in, field_t *f,
sequence_t * unnamed_types,
table_t * named_types,
int tag)
{
char * token;
+ f->fac = fac;
if(tag) {
//<field name=field_name> <description> <type> </field>
getFieldAttributes(in, f);
//<int size=...>
getLAnglebracket(in);
- f->type = parseType(in,NULL, unnamed_types, named_types);
+ f->type = parseType(fac, in,NULL, unnamed_types, named_types);
if(tag) {
getLAnglebracket(in);
* type name:
* type(name,type)
*Input params
+ * fac : facility
* in : input file handle
* inType : a type descriptor
* unnamed_types : array of unamed types
* type_descriptor* : a type descriptor
****************************************************************************/
-type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
+type_descriptor_t *parseType(facility_t *fac, parse_file_t *in, type_descriptor_t *inType,
sequence_t * unnamed_types, table_t * named_types)
{
char *token;
sequence_push(unnamed_types,t);
}
else t = inType;
+ t->fac = fac;
token = getName(in);
f = (field_t *)memAlloc(sizeof(field_t));
sequence_push(&(t->fields),f);
- parseFields(in, f, unnamed_types, named_types, 1);
+ parseFields(fac, in, f, unnamed_types, named_types, 1);
//next field
getLAnglebracket(in);
while(strcmp("field",token) == 0){
f = (field_t *)memAlloc(sizeof(field_t));
sequence_push(&(t->fields),f);
- parseFields(in, f, unnamed_types, named_types, 1);
+ parseFields(fac, in, f, unnamed_types, named_types, 1);
//next field
getLAnglebracket(in);
f->name = NULL;
sequence_push(&(t->fields),f);
- parseFields(in, f, unnamed_types, named_types, 0);
+ parseFields(fac, in, f, unnamed_types, named_types, 0);
//getLAnglebracket(in); //<type struct>
//t->nested_type = parseType(in, NULL, unnamed_types, named_types);
f = (field_t *)memAlloc(sizeof(field_t));
f->name = NULL;
sequence_push(&(t->fields),f);
- parseFields(in, f, unnamed_types, named_types, 0);
+ parseFields(fac, in, f, unnamed_types, named_types, 0);
//getLAnglebracket(in); //<subtype>
/* subfield */
f = (field_t *)memAlloc(sizeof(field_t));
f->name = NULL;
sequence_push(&(t->fields),f);
- parseFields(in, f, unnamed_types, named_types, 0);
+ parseFields(fac, in, f, unnamed_types, named_types, 0);
//getLAnglebracket(in); //<type sequence>
//t->length_type = parseType(in, NULL, unnamed_types, named_types);
*Function name
* parseTypeDefinition : get type information from type definition
*Input params
+ * fac : facility
* in : input file handle
* unnamed_types : array of unamed types
* named_types : array of named types
*****************************************************************************/
-void parseTypeDefinition(parse_file_t * in, sequence_t * unnamed_types,
+void parseTypeDefinition(facility_t *fac, parse_file_t * in, sequence_t * unnamed_types,
table_t * named_types)
{
char *token;
token = getName(in);
//MD ??if(strcmp("struct",token))in->error(in,"not a valid type definition");
ungetToken(in);
- parseType(in,t, unnamed_types, named_types);
+ parseType(fac, in,t, unnamed_types, named_types);
//</type>
getLAnglebracket(in);
NONE
} data_type_t;
+typedef struct _facility facility_t;
+typedef struct _event event_t;
+
typedef struct _type_descriptor {
+ facility_t *fac;
char * type_name; //used for named type
data_type_t type;
char *fmt;
} type_descriptor_t;
-
/* Fields within types or events */
typedef struct _field{
+ facility_t *fac;
char *name;
char *description;
type_descriptor_t *type;
/* Events definitions */
-typedef struct _event {
+struct _event {
+ facility_t *fac;
char *name;
char *description;
//type_descriptor_t *type;
- sequence_t fields; /* event fields */
+ sequence_t fields; /* event fields */
int per_trace; /* Is the event able to be logged to a specific trace ? */
int per_tracefile; /* Must we log this event in a specific tracefile ? */
- int param_buffer; /* For userspace tracing : takes a buffer as parameter? */
- int no_instrument_function;
- int high_priority;
-} event_t;
+ int param_buffer; /* For userspace tracing : takes a buffer as parameter? */
+ int no_instrument_function;
+ int high_priority;
+ int force;
+ int compact_data;
+};
-typedef struct _facility {
+struct _facility {
char * name;
- char * capname;
- char * arch;
+ char * capname;
+ char * arch;
+ int align; /* Alignment : default 1, 0 no alignment. */
char * description;
sequence_t events;
sequence_t unnamed_types; //FIXME : remove
table_t named_types;
- unsigned int checksum;
- int user; /* Is this a userspace facility ? */
-} facility_t;
+ unsigned int checksum;
+ int user; /* Is this a userspace facility ? */
+};
int getSizeindex(unsigned int value);
unsigned long long int getSize(parse_file_t *in);
unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type);
void parseFacility(parse_file_t *in, facility_t * fac);
-void parseEvent(parse_file_t *in, event_t *ev, sequence_t * unnamed_types,
+void parseEvent(facility_t *fac, parse_file_t *in, event_t *ev, sequence_t * unnamed_types,
table_t * named_types);
-void parseTypeDefinition(parse_file_t *in,
+void parseTypeDefinition(facility_t *fac, parse_file_t *in,
sequence_t * unnamed_types, table_t * named_types);
-type_descriptor_t *parseType(parse_file_t *in,
+type_descriptor_t *parseType(facility_t *fac, parse_file_t *in,
type_descriptor_t *t, sequence_t * unnamed_types, table_t * named_types);
-void parseFields(parse_file_t *in, field_t *f,
+void parseFields(facility_t *fac, parse_file_t *in, field_t *f,
sequence_t * unnamed_types,
table_t * named_types,
int tag);
unsigned ltt_trace_facility_number(LttTrace *t);
-LttFacility *ltt_trace_facility_get(LttTrace *t, unsigned i);
-
LttFacility * ltt_trace_facility_by_id(LttTrace * trace, guint8 id);
/* Returns an array of indexes (guint) that matches the facility name */
#include <glib.h>
#include <malloc.h>
#include <sys/mman.h>
+#include <string.h>
// For realpath
#include <limits.h>
(double)t->start_tsc
* (1000000000.0 / tf->trace->freq_scale)
/ (double)t->start_freq);
+ t->compact_event_bits = 0;
}
}
break;
tf->tsc_lsb_truncate = vheader->tsc_lsb_truncate;
tf->tscbits = vheader->tscbits;
tf->tsc_msb_cutoff = 32 - tf->tsc_lsb_truncate - tf->tscbits;
- tf->tsc_mask = ((1ULL << (tf->tscbits))-1);
- tf->tsc_mask = tf->tsc_mask << tf->tsc_lsb_truncate;
+ tf->tsc_mask = ((1ULL << (tf->tscbits))-1);
+ tf->tsc_mask = tf->tsc_mask << tf->tsc_lsb_truncate;
tf->tsc_mask_next_bit = (1ULL<<(tf->tscbits));
tf->tsc_mask_next_bit = tf->tsc_mask_next_bit << tf->tsc_lsb_truncate;
if(t) {
(double)t->start_tsc
* (1000000000.0 / tf->trace->freq_scale)
/ (double)t->start_freq);
+ t->compact_event_bits = 0;
}
}
break;
if(!t->compact_facilities)
t->compact_facilities = ltt_trace_facility_get_by_name(t,
g_quark_from_string("flight-compact"));
-
+ /* FIXME : currently does not support unload/load of compact
+ * facility during tracing. Should check for the currently loaded
+ * version of the facility. */
+ g_assert(t->compact_facilities);
+ g_assert(t->compact_facilities->len == 1);
+ {
+ guint facility_id = g_array_index(t->compact_facilities, guint, 0);
+ LttFacility *fac = ltt_trace_facility_by_id(t, facility_id);
+ unsigned int num = ltt_facility_eventtype_number(fac);
+ /* Could be done much quicker, but not on much used code path */
+ if(num) {
+ t->compact_event_bits = 1;
+ while(num >>= 1)
+ t->compact_event_bits++;
+ } else
+ t->compact_event_bits = 0;
+ }
+
return t;
/* Error handling */
tf->buffer.tsc = (tf->buffer.tsc&0xFFFFFFFF00000000ULL)
| (guint64)event->timestamp;
event->tsc = tf->buffer.tsc;
+ event->compact_data = 0;
}
} else {
/* Compact header */
/* We keep the LSB of the previous timestamp, to make sure
* we never go back */
event->event_id = event->timestamp >> tf->tscbits;
+ event->event_id = event->event_id & ((1 << tf->trace->compact_event_bits) - 1);
+ event->compact_data = event->timestamp >>
+ (tf->trace->compact_event_bits + tf->tscbits);
+ //printf("tsc bits %u, ev bits %u init data %u\n",
+ // tf->tscbits, tf->trace->compact_event_bits, event->compact_data);
+ /* Put the compact data back in original endianness */
+ event->compact_data = ltt_get_uint32(LTT_GET_BO(tf), &event->compact_data);
event->event_size = 0xFFFF;
- printf("Found compact event %d\n", event->event_id);
+ //printf("Found compact event %d\n", event->event_id);
+ //printf("Compact data %d\n", event->compact_data);
event->timestamp = event->timestamp << tf->tsc_lsb_truncate;
event->timestamp = event->timestamp & tf->tsc_mask;
- printf("timestamp 0x%lX\n", event->timestamp);
- printf("mask 0x%llX\n", tf->tsc_mask);
- printf("mask_next 0x%llX\n", tf->tsc_mask_next_bit);
- printf("previous tsc 0x%llX\n", tf->buffer.tsc);
- printf("previous tsc&mask 0x%llX\n", tf->tsc_mask&tf->buffer.tsc);
- printf("previous tsc&(~mask) 0x%llX\n", tf->buffer.tsc&(~tf->tsc_mask));
+ //printf("timestamp 0x%lX\n", event->timestamp);
+ //printf("mask 0x%llX\n", tf->tsc_mask);
+ //printf("mask_next 0x%llX\n", tf->tsc_mask_next_bit);
+ //printf("previous tsc 0x%llX\n", tf->buffer.tsc);
+ //printf("previous tsc&mask 0x%llX\n", tf->tsc_mask&tf->buffer.tsc);
+ //printf("previous tsc&(~mask) 0x%llX\n", tf->buffer.tsc&(~tf->tsc_mask));
if(event->timestamp < (tf->tsc_mask&tf->buffer.tsc)) {
- printf("wrap\n");
+ //printf("wrap\n");
tf->buffer.tsc = ((tf->buffer.tsc&(~tf->tsc_mask))
+ tf->tsc_mask_next_bit)
| (guint64)event->timestamp;
event->tsc = tf->buffer.tsc;
} else {
- printf("no wrap\n");
+ //printf("no wrap\n");
/* no overflow */
tf->buffer.tsc = (tf->buffer.tsc&(~tf->tsc_mask))
| (guint64)event->timestamp;
event->tsc = tf->buffer.tsc;
}
- printf("current tsc 0x%llX\n", tf->buffer.tsc);
- g_assert(tf->trace->compact_facilities);
- /* FIXME : currently does not support unload/load of compact
- * facility during tracing. Should check for the currently loaded
- * version of the facility. */
- g_assert(tf->trace->compact_facilities->len == 1);
+ //printf("current tsc 0x%llX\n", tf->buffer.tsc);
event->facility_id = g_array_index(tf->trace->compact_facilities, guint, 0);
}
pos += sizeof(guint32);
} else {
event->tsc = ltt_get_uint64(LTT_GET_BO(tf), pos);
tf->buffer.tsc = event->tsc;
+ event->compact_data = 0;
pos += sizeof(guint64);
}
event->event_time = ltt_interpolate_time(tf, event);
****************************************************************************/
-gint precompute_fields_offsets(LttFacility *fac, LttField *field, off_t *offset)
+gint precompute_fields_offsets(LttFacility *fac, LttField *field, off_t *offset, gint is_compact)
{
LttType *type = &field->field_type;
+
+ if(unlikely(is_compact)) {
+ g_assert(field->field_size != 0);
+ /* FIXME THIS IS A HUUUUUGE hack :
+ * offset is between the compact_data field in struct LttEvent
+ * and the address of the field root in the memory map.
+ * ark. Both will stay at the same addresses while the event
+ * is readable, so it's ok.
+ */
+ field->offset_root = 0;
+ field->fixed_root = FIELD_FIXED;
+ return 0;
+ }
switch(type->type_class) {
case LTT_INT_FIXED:
field->fixed_root = FIELD_FIXED;
child = &g_array_index(type->fields, LttField, 0);
- ret = precompute_fields_offsets(fac, child, offset);
+ ret = precompute_fields_offsets(fac, child, offset, is_compact);
g_assert(ret == 0); /* Seq len cannot have variable len */
child = &g_array_index(type->fields, LttField, 1);
for(i=0; i< type->fields->len; i++) {
child = &g_array_index(type->fields, LttField, i);
- ret = precompute_fields_offsets(fac, child, offset);
+ ret = precompute_fields_offsets(fac, child, offset, is_compact);
if(ret) break;
}
for(i=0; i< type->fields->len; i++) {
*offset = field->offset_root;
child = &g_array_index(type->fields, LttField, i);
- ret = precompute_fields_offsets(fac, child, offset);
+ ret = precompute_fields_offsets(fac, child, offset, is_compact);
if(ret) break;
}
/* Precompute all known offsets */
for(i=0; i<event->fields->len; i++) {
LttField *field = &g_array_index(event->fields, LttField, i);
- ret = precompute_fields_offsets(fac, field, &offset);
+ if(event->has_compact_data && i == 0)
+ ret = precompute_fields_offsets(fac, field, &offset, 1);
+ else
+ ret = precompute_fields_offsets(fac, field, &offset, 0);
if(ret) break;
}
}
break;
case LTT_NONE:
default:
- g_error("precompute_fields_offsets : unknown type");
+ g_error("check_fields_compatibility : unknown type");
}
end: