X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Fltt%2Ftracefile.c;h=8ac4b5061de96a70269dfedc3a539642d55c11cd;hb=f63ebe5196f36fcf40385d29cfc37288c4d70817;hp=72eb3a6efc0a4af46bb0a21859b373666de68dc7;hpb=c7f86478aa57c32c43c8df1569b1b8f8a584441d;p=lttv.git diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c index 72eb3a6e..8ac4b506 100644 --- a/ltt/branches/poly/ltt/tracefile.c +++ b/ltt/branches/poly/ltt/tracefile.c @@ -34,6 +34,7 @@ #include #include #include +#include // For realpath #include @@ -53,7 +54,8 @@ /* Facility names used in this file */ GQuark LTT_FACILITY_NAME_HEARTBEAT, - LTT_EVENT_NAME_HEARTBEAT; + LTT_EVENT_NAME_HEARTBEAT, + LTT_EVENT_NAME_HEARTBEAT_FULL; GQuark LTT_TRACEFILE_NAME_FACILITIES; #ifndef g_open @@ -232,6 +234,7 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) t->ltt_minor_version = any->minor_version; t->flight_recorder = any->flight_recorder; t->has_heartbeat = any->has_heartbeat; + t->compact_facilities = NULL; } @@ -256,6 +259,48 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) tf->buffer_header_size = sizeof(struct ltt_block_start_header) + sizeof(struct ltt_trace_header_0_7); + tf->tsc_lsb_truncate = 0; + tf->tscbits = 32; + tf->tsc_msb_cutoff = 32 - tf->tsc_lsb_truncate - tf->tscbits; + tf->tsc_mask = (1ULL<<32)-1; + tf->tsc_mask_next_bit = (1ULL<<32); + if(t) { + t->start_freq = ltt_get_uint64(LTT_GET_BO(tf), + &vheader->start_freq); + t->freq_scale = ltt_get_uint32(LTT_GET_BO(tf), + &vheader->freq_scale); + t->start_tsc = ltt_get_uint64(LTT_GET_BO(tf), + &vheader->start_tsc); + t->start_monotonic = ltt_get_uint64(LTT_GET_BO(tf), + &vheader->start_monotonic); + t->start_time.tv_sec = ltt_get_uint64(LTT_GET_BO(tf), + &vheader->start_time_sec); + t->start_time.tv_nsec = ltt_get_uint64(LTT_GET_BO(tf), + &vheader->start_time_usec); + t->start_time.tv_nsec *= 1000; /* microsec to nanosec */ + + t->start_time_from_tsc = ltt_time_from_uint64( + (double)t->start_tsc + * (1000000000.0 / tf->trace->freq_scale) + / (double)t->start_freq); + t->compact_event_bits = 0; + } + } + break; + case 8: + { + struct ltt_trace_header_0_8 *vheader = + (struct ltt_trace_header_0_8 *)header; + tf->buffer_header_size = + sizeof(struct ltt_block_start_header) + + sizeof(struct ltt_trace_header_0_8); + 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_next_bit = (1ULL<<(tf->tscbits)); + tf->tsc_mask_next_bit = tf->tsc_mask_next_bit << tf->tsc_lsb_truncate; if(t) { t->start_freq = ltt_get_uint64(LTT_GET_BO(tf), &vheader->start_freq); @@ -275,6 +320,7 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) (double)t->start_tsc * (1000000000.0 / tf->trace->freq_scale) / (double)t->start_freq); + t->compact_event_bits = 0; } } break; @@ -884,7 +930,11 @@ static int open_tracefiles(LttTrace *trace, gchar *root_path, tmp_tf.tid = tid; tmp_tf.pgid = pgid; tmp_tf.creation = creation; - + if(tmp_tf.name == g_quark_from_string("/compact") + || tmp_tf.name == g_quark_from_string("/flight-compact")) + tmp_tf.compact = 1; + else + tmp_tf.compact = 0; group = g_datalist_id_get_data(&trace->tracefiles, name); if(group == NULL) { /* Elements are automatically cleared when the array is allocated. @@ -1184,10 +1234,13 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) fac_ids, ltt_fac_ids_destroy); } g_array_append_val(fac_ids, fac->id); + g_debug("fac id : %u", fac->id); break; case LTT_EVENT_HEARTBEAT: break; + case LTT_EVENT_HEARTBEAT_FULL: + break; default: g_warning("Error in processing facility file %s, " "unknown event id %hhu in core facility.", @@ -1298,7 +1351,31 @@ LttTrace *ltt_trace_open(const gchar *pathname) if(ltt_process_facility_tracefile(tf)) goto facilities_error; } - + t->compact_facilities = ltt_trace_facility_get_by_name(t, + g_quark_from_string("compact")); + if(!t->compact_facilities) + t->compact_facilities = ltt_trace_facility_get_by_name(t, + g_quark_from_string("flight-compact")); + if (t->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(t->compact_facilities->len == 1); + g_assert(t->compact_facilities); + { + 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 */ @@ -1820,47 +1897,99 @@ int ltt_tracefile_read_update_event(LttTracefile *tf) /* Read event header */ /* Align the head */ - pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment); + if(!tf->compact) + pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment); + else { + g_assert(tf->trace->has_heartbeat); + pos += ltt_align((size_t)pos, sizeof(uint32_t), tf->has_alignment); + } if(tf->trace->has_heartbeat) { event->timestamp = ltt_get_uint32(LTT_GET_BO(tf), pos); - /* 32 bits -> 64 bits tsc */ - /* note : still works for seek and non seek cases. */ - if(event->timestamp < (0xFFFFFFFFULL&tf->buffer.tsc)) { - tf->buffer.tsc = ((tf->buffer.tsc&0xFFFFFFFF00000000ULL) - + 0x100000000ULL) - | (guint64)event->timestamp; - event->tsc = tf->buffer.tsc; - } else { - /* no overflow */ - tf->buffer.tsc = (tf->buffer.tsc&0xFFFFFFFF00000000ULL) - | (guint64)event->timestamp; - event->tsc = tf->buffer.tsc; - } + if(!tf->compact) { + /* 32 bits -> 64 bits tsc */ + /* note : still works for seek and non seek cases. */ + if(event->timestamp < (0xFFFFFFFFULL&tf->buffer.tsc)) { + tf->buffer.tsc = ((tf->buffer.tsc&0xFFFFFFFF00000000ULL) + + 0x100000000ULL) + | (guint64)event->timestamp; + event->tsc = tf->buffer.tsc; + } else { + /* no overflow */ + 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("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)); + if(event->timestamp < (tf->tsc_mask&tf->buffer.tsc)) { + //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"); + /* 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); + 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); - event->facility_id = *(guint8*)pos; - pos += sizeof(guint8); - event->event_id = *(guint8*)pos; - pos += sizeof(guint8); + if(!tf->compact) { + event->facility_id = *(guint8*)pos; + pos += sizeof(guint8); - event->event_size = ltt_get_uint16(LTT_GET_BO(tf), pos); - pos += sizeof(guint16); - + event->event_id = *(guint8*)pos; + pos += sizeof(guint8); + + event->event_size = ltt_get_uint16(LTT_GET_BO(tf), pos); + pos += sizeof(guint16); + } else { + /* Compact event */ + } /* Align the head */ - pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment); + if(!tf->compact) + pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment); event->data = pos; /* get the data size and update the event fields with the current - * information */ + * information. Also update the time if a heartbeat_full event is found. */ ltt_update_event_size(tf); return 0; @@ -2006,6 +2135,7 @@ void ltt_update_event_size(LttTracefile *tf) off_t size = 0; LttFacility *f = ltt_trace_get_facility_by_num(tf->trace, tf->event.facility_id); + char *tscdata; if(!f->exists) { /* Specific handling of core events : necessary to read the facility control @@ -2034,6 +2164,15 @@ void ltt_update_event_size(LttTracefile *tf) //g_debug("Update Event heartbeat"); size = sizeof(TimeHeartbeat); break; + case LTT_EVENT_HEARTBEAT_FULL: + //g_debug("Update Event heartbeat full"); + tscdata = (char*)(tf->event.data); + tf->event.tsc = ltt_get_uint64(LTT_GET_BO(tf), tscdata); + tf->buffer.tsc = tf->event.tsc; + tf->event.event_time = ltt_interpolate_time(tf, &tf->event); + size = sizeof(TimeHeartbeatFull); + size += ltt_align(size, sizeof(guint64), tf->has_alignment); + break; default: g_warning("Error in getting event size : tracefile %s, " "unknown event id %hhu in core facility.", @@ -2078,7 +2217,13 @@ no_offset: /* Event size too big to fit in the event size field */ tf->event.event_size = tf->event.data_size; } - g_assert(tf->event.data_size == tf->event.event_size); + if (tf->event.data_size != tf->event.event_size) { + g_error("Kernel/LTTV event size differs for event %s.%s: kernel %u, LTTV %u", + g_quark_to_string(f->name), g_quark_to_string(event_type->name), + tf->event.event_size, tf->event.data_size); + exit(-1); + } + //g_assert(tf->event.data_size == tf->event.event_size); return; @@ -2391,9 +2536,22 @@ void field_compute_static_size(LttFacility *fac, LttField *field) ****************************************************************************/ -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: @@ -2468,7 +2626,7 @@ gint precompute_fields_offsets(LttFacility *fac, LttField *field, off_t *offset) 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); @@ -2497,7 +2655,7 @@ gint precompute_fields_offsets(LttFacility *fac, LttField *field, off_t *offset) 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; } @@ -2519,7 +2677,7 @@ gint precompute_fields_offsets(LttFacility *fac, LttField *field, off_t *offset) 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; } @@ -2561,7 +2719,10 @@ void precompute_offsets(LttFacility *fac, LttEventType *event) /* Precompute all known offsets */ for(i=0; ifields->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; } } @@ -2861,7 +3022,7 @@ gint check_fields_compatibility(LttEventType *event_type1, break; case LTT_NONE: default: - g_error("precompute_fields_offsets : unknown type"); + g_error("check_fields_compatibility : unknown type"); } end: @@ -3107,6 +3268,7 @@ static void __attribute__((constructor)) init(void) { LTT_FACILITY_NAME_HEARTBEAT = g_quark_from_string("heartbeat"); LTT_EVENT_NAME_HEARTBEAT = g_quark_from_string("heartbeat"); + LTT_EVENT_NAME_HEARTBEAT_FULL = g_quark_from_string("heartbeat_full"); LTT_TRACEFILE_NAME_FACILITIES = g_quark_from_string("/control/facilities"); }