X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Fltt%2Ftracefile.c;h=a2cf1822f850b55213eda1f178613e0120466163;hb=3de8060d28ffe56a57855df01849cac2e93dafd0;hp=021e2b4e897b92b0dc18679d95b172f334a280d6;hpb=a3999b493f2735815c7a75ef367899973c312450;p=lttv.git diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c index 021e2b4e..a2cf1822 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 @@ -221,6 +223,7 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) * (or is set to 0 if the trace has no float (kernel trace)) */ tf->float_word_order = any->float_word_order; tf->has_alignment = any->has_alignment; + tf->has_heartbeat = any->has_heartbeat; if(t) { t->arch_type = ltt_get_uint32(LTT_GET_BO(tf), @@ -231,7 +234,7 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) t->ltt_major_version = any->major_version; 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); @@ -272,7 +317,10 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) t->start_time.tv_nsec *= 1000; /* microsec to nanosec */ t->start_time_from_tsc = ltt_time_from_uint64( - (double)t->start_tsc * 1000000.0 / (double)t->start_freq); + (double)t->start_tsc + * (1000000000.0 / tf->trace->freq_scale) + / (double)t->start_freq); + t->compact_event_bits = 0; } } break; @@ -646,9 +694,9 @@ void get_absolute_pathname(const gchar *pathname, gchar * abs_pathname) int get_tracefile_name_number(gchar *raw_name, GQuark *name, guint *num, - guint *tid, - guint *pgid, - guint64 *creation) + guint *tid, + guint *pgid, + guint64 *creation) { guint raw_name_len = strlen(raw_name); gchar char_name[PATH_MAX]; @@ -656,83 +704,84 @@ int get_tracefile_name_number(gchar *raw_name, int underscore_pos; long int cpu_num; gchar *endptr; - gchar *tmpptr; + gchar *tmpptr; for(i=raw_name_len-1;i>=0;i--) { if(raw_name[i] == '_') break; } if(i==-1) { /* Either not found or name length is 0 */ - /* This is a userspace tracefile */ - strncpy(char_name, raw_name, raw_name_len); - *name = g_quark_from_string(char_name); - *num = 0; /* unknown cpu */ - for(i=0;id_name[0] == '.') continue; - - strncpy(path_ptr, entry->d_name, PATH_MAX - path_len); - strncpy(rel_path_ptr, entry->d_name, PATH_MAX - rel_path_len); - - ret = stat(path, &stat_buf); - if(ret == -1) { - perror(path); - continue; - } - - g_debug("Tracefile file or directory : %s\n", path); - + while((entry = readdir(dir)) != NULL) { + + if(entry->d_name[0] == '.') continue; + + strncpy(path_ptr, entry->d_name, PATH_MAX - path_len); + strncpy(rel_path_ptr, entry->d_name, PATH_MAX - rel_path_len); + + ret = stat(path, &stat_buf); + if(ret == -1) { + perror(path); + continue; + } + + g_debug("Tracefile file or directory : %s\n", path); + if(strcmp(rel_path, "/eventdefs") == 0) continue; - if(S_ISDIR(stat_buf.st_mode)) { + if(S_ISDIR(stat_buf.st_mode)) { - g_debug("Entering subdirectory...\n"); - ret = open_tracefiles(trace, path, rel_path); - if(ret < 0) continue; - } else if(S_ISREG(stat_buf.st_mode)) { - GQuark name; + g_debug("Entering subdirectory...\n"); + ret = open_tracefiles(trace, path, rel_path); + if(ret < 0) continue; + } else if(S_ISREG(stat_buf.st_mode)) { + GQuark name; guint num, tid, pgid; - guint64 creation; + guint64 creation; GArray *group; num = tid = pgid = 0; - creation = 0; + creation = 0; if(get_tracefile_name_number(rel_path, &name, &num, &tid, &pgid, &creation)) continue; /* invalid name */ - g_debug("Opening file.\n"); + g_debug("Opening file.\n"); if(ltt_tracefile_open(trace, path, &tmp_tf)) { g_info("Error opening tracefile %s", path); @@ -878,10 +927,14 @@ static int open_tracefiles(LttTrace *trace, gchar *root_path, tmp_tf.cpu_online = 1; tmp_tf.cpu_num = num; tmp_tf.name = name; - tmp_tf.tid = tid; - tmp_tf.pgid = pgid; - tmp_tf.creation = creation; - + 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. @@ -898,12 +951,12 @@ static int open_tracefiles(LttTrace *trace, gchar *root_path, group = g_array_set_size(group, num+1); g_array_index (group, LttTracefile, num) = tmp_tf; - } - } - - closedir(dir); + } + } + + closedir(dir); - return 0; + return 0; } /* ltt_get_facility_description @@ -924,8 +977,8 @@ static int ltt_get_facility_description(LttFacility *f, const gchar *text; guint textlen; gint err; - gint arch_spec; - gint fac_name_len; + gint arch_spec; + gint fac_name_len; text = g_quark_to_string(t->pathname); textlen = strlen(text); @@ -939,20 +992,20 @@ static int ltt_get_facility_description(LttFacility *f, strcat(desc_file_name, text); text = g_quark_to_string(f->name); - fac_name_len = strlen(text); + fac_name_len = strlen(text); textlen+=fac_name_len; if(textlen >= PATH_MAX) goto name_error; strcat(desc_file_name, text); - /* arch specific facilities are named like this : name_arch */ - if(fac_name_len+1 < sizeof("_arch")) - arch_spec = 0; - else { - if(!strcmp(&text[fac_name_len+1-sizeof("_arch")], "_arch")) - arch_spec = 1; - else - arch_spec = 0; - } + /* arch specific facilities are named like this : name_arch */ + if(fac_name_len+1 < sizeof("_arch")) + arch_spec = 0; + else { + if(!strcmp(&text[fac_name_len+1-sizeof("_arch")], "_arch")) + arch_spec = 1; + else + arch_spec = 0; + } #if 0 text = "_"; @@ -967,44 +1020,47 @@ static int ltt_get_facility_description(LttFacility *f, textlen=strlen(desc_file_name); #endif //0 - - if(arch_spec) { - switch(t->arch_type) { - case LTT_ARCH_TYPE_I386: - text = "_i386"; - break; - case LTT_ARCH_TYPE_PPC: - text = "_ppc"; - break; - case LTT_ARCH_TYPE_SH: - text = "_sh"; - break; - case LTT_ARCH_TYPE_S390: - text = "_s390"; - break; - case LTT_ARCH_TYPE_MIPS: - text = "_mips"; - break; - case LTT_ARCH_TYPE_ARM: - text = "_arm"; - break; - case LTT_ARCH_TYPE_PPC64: - text = "_ppc64"; - break; - case LTT_ARCH_TYPE_X86_64: - text = "_x86_64"; - break; - case LTT_ARCH_TYPE_C2: - text = "_c2"; - break; - default: - g_error("Trace from unsupported architecture."); - } - textlen+=strlen(text); - if(textlen >= PATH_MAX) goto name_error; - strcat(desc_file_name, text); - } - + + if(arch_spec) { + switch(t->arch_type) { + case LTT_ARCH_TYPE_I386: + text = "_i386"; + break; + case LTT_ARCH_TYPE_PPC: + text = "_ppc"; + break; + case LTT_ARCH_TYPE_SH: + text = "_sh"; + break; + case LTT_ARCH_TYPE_S390: + text = "_s390"; + break; + case LTT_ARCH_TYPE_MIPS: + text = "_mips"; + break; + case LTT_ARCH_TYPE_ARM: + text = "_arm"; + break; + case LTT_ARCH_TYPE_PPC64: + text = "_ppc64"; + break; + case LTT_ARCH_TYPE_X86_64: + text = "_x86_64"; + break; + case LTT_ARCH_TYPE_C2: + text = "_c2"; + break; + case LTT_ARCH_TYPE_POWERPC: + text = "_powerpc"; + break; + default: + g_error("Trace from unsupported architecture."); + } + textlen+=strlen(text); + if(textlen >= PATH_MAX) goto name_error; + strcat(desc_file_name, text); + } + text = ".xml"; textlen+=strlen(text); if(textlen >= PATH_MAX) goto name_error; @@ -1078,7 +1134,7 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) g_debug("Doing LTT_EVENT_FACILITY_LOAD of facility %s", fac_name); pos = (tf->event.data + strlen(fac_name) + 1); - pos += ltt_align((size_t)pos, sizeof(guint32), tf->has_alignment); + pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment); fac_load_data = (struct LttFacilityLoad *)pos; fac = &g_array_index (tf->trace->facilities_by_num, LttFacility, @@ -1091,8 +1147,8 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) fac->id = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->id); fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->pointer_size); - fac->int_size = ltt_get_uint32(LTT_GET_BO(tf), - &fac_load_data->int_size); + fac->int_size = ltt_get_uint32(LTT_GET_BO(tf), + &fac_load_data->int_size); fac->long_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->long_size); fac->size_t_size = ltt_get_uint32(LTT_GET_BO(tf), @@ -1134,7 +1190,7 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) g_debug("Doing LTT_EVENT_STATE_DUMP_FACILITY_LOAD of facility %s", fac_name); pos = (tf->event.data + strlen(fac_name) + 1); - pos += ltt_align((size_t)pos, sizeof(guint32), tf->has_alignment); + pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment); fac_state_dump_load_data = (struct LttStateDumpFacilityLoad *)pos; fac = &g_array_index (tf->trace->facilities_by_num, LttFacility, @@ -1148,8 +1204,8 @@ static int ltt_process_facility_tracefile(LttTracefile *tf) &fac_state_dump_load_data->id); fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_state_dump_load_data->pointer_size); - fac->int_size = ltt_get_uint32(LTT_GET_BO(tf), - &fac_state_dump_load_data->int_size); + fac->int_size = ltt_get_uint32(LTT_GET_BO(tf), + &fac_state_dump_load_data->int_size); fac->long_size = ltt_get_uint32(LTT_GET_BO(tf), &fac_state_dump_load_data->long_size); fac->size_t_size = ltt_get_uint32(LTT_GET_BO(tf), @@ -1178,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.", @@ -1212,11 +1271,11 @@ LttTrace *ltt_trace_open(const gchar *pathname) GArray *group; int i, ret; struct ltt_block_start_header *header; - DIR *dir; - struct dirent *entry; + DIR *dir; + struct dirent *entry; guint control_found = 0; guint eventdefs_found = 0; - struct stat stat_buf; + struct stat stat_buf; gchar path[PATH_MAX]; t = g_new(LttTrace, 1); @@ -1228,21 +1287,21 @@ LttTrace *ltt_trace_open(const gchar *pathname) g_datalist_init(&t->tracefiles); /* Test to see if it looks like a trace */ - dir = opendir(abs_path); - if(dir == NULL) { - perror(abs_path); - goto open_error; - } - while((entry = readdir(dir)) != NULL) { + dir = opendir(abs_path); + if(dir == NULL) { + perror(abs_path); + goto open_error; + } + while((entry = readdir(dir)) != NULL) { strcpy(path, abs_path); strcat(path, "/"); strcat(path, entry->d_name); - ret = stat(path, &stat_buf); - if(ret == -1) { - perror(path); - continue; - } - if(S_ISDIR(stat_buf.st_mode)) { + ret = stat(path, &stat_buf); + if(ret == -1) { + perror(path); + continue; + } + if(S_ISDIR(stat_buf.st_mode)) { if(strcmp(entry->d_name, "control") == 0) { control_found = 1; } @@ -1292,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 */ @@ -1665,9 +1748,9 @@ int ltt_tracefile_seek_position(LttTracefile *tf, const LttEventPosition *ep) { tf->event.offset = ep->offset; - /* Put back the event real tsc */ - tf->event.tsc = ep->tsc; - tf->buffer.tsc = ep->tsc; + /* Put back the event real tsc */ + tf->event.tsc = ep->tsc; + tf->buffer.tsc = ep->tsc; err = ltt_tracefile_read_update_event(tf); if(err) goto fail; @@ -1685,27 +1768,27 @@ fail: LttTime ltt_interpolate_time_from_tsc(LttTracefile *tf, guint64 tsc) { LttTime time; - - if(tsc > tf->trace->start_tsc) { - time = ltt_time_from_uint64( - (double)(tsc - tf->trace->start_tsc) - * (1000000000.0 / tf->trace->freq_scale) - / (double)tf->trace->start_freq); - time = ltt_time_add(tf->trace->start_time_from_tsc, time); - } else { - time = ltt_time_from_uint64( - (double)(tf->trace->start_tsc - tsc) - * (1000000000.0 / tf->trace->freq_scale) - / (double)tf->trace->start_freq); - time = ltt_time_sub(tf->trace->start_time_from_tsc, time); - } + + if(tsc > tf->trace->start_tsc) { + time = ltt_time_from_uint64( + (double)(tsc - tf->trace->start_tsc) + * (1000000000.0 / tf->trace->freq_scale) + / (double)tf->trace->start_freq); + time = ltt_time_add(tf->trace->start_time_from_tsc, time); + } else { + time = ltt_time_from_uint64( + (double)(tf->trace->start_tsc - tsc) + * (1000000000.0 / tf->trace->freq_scale) + / (double)tf->trace->start_freq); + time = ltt_time_sub(tf->trace->start_time_from_tsc, time); + } return time; } /* Calculate the real event time based on the buffer boundaries */ LttTime ltt_interpolate_time(LttTracefile *tf, LttEvent *event) { - return ltt_interpolate_time_from_tsc(tf, tf->buffer.tsc); + return ltt_interpolate_time_from_tsc(tf, tf->buffer.tsc); } @@ -1813,48 +1896,100 @@ 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); + /* Align the head */ + if(!tf->compact) + pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment); + else { + g_assert(tf->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; - } - pos += sizeof(guint32); - } else { - event->tsc = ltt_get_uint64(LTT_GET_BO(tf), pos); - tf->buffer.tsc = event->tsc; - pos += sizeof(guint64); - } - event->event_time = ltt_interpolate_time(tf, event); - event->facility_id = *(guint8*)pos; - pos += sizeof(guint8); + if(tf->has_heartbeat) { + event->timestamp = ltt_get_uint32(LTT_GET_BO(tf), + pos); + 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->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); - - /* Align the head */ - pos += ltt_align((size_t)pos, tf->trace->arch_size, tf->has_alignment); + 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 */ + 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; @@ -1922,18 +2057,18 @@ static gint map_block(LttTracefile * tf, guint block_num) &header->begin.cycle_count); tf->buffer.begin.freq = ltt_get_uint64(LTT_GET_BO(tf), &header->begin.freq); - if(tf->buffer.begin.freq == 0) - tf->buffer.begin.freq = tf->trace->start_freq; + if(tf->buffer.begin.freq == 0) + tf->buffer.begin.freq = tf->trace->start_freq; tf->buffer.begin.timestamp = ltt_interpolate_time_from_tsc(tf, - tf->buffer.begin.cycle_count); + tf->buffer.begin.cycle_count); #if 0 - ltt_time_add( + ltt_time_add( ltt_time_from_uint64( (double)(tf->buffer.begin.cycle_count - tf->trace->start_tsc) * 1000000.0 / (double)tf->trace->start_freq), - tf->trace->start_time_from_tsc); + tf->trace->start_time_from_tsc); #endif //0 #if 0 @@ -1950,15 +2085,15 @@ static gint map_block(LttTracefile * tf, guint block_num) &header->end.cycle_count); tf->buffer.end.freq = ltt_get_uint64(LTT_GET_BO(tf), &header->end.freq); - if(tf->buffer.end.freq == 0) - tf->buffer.end.freq = tf->trace->start_freq; - + if(tf->buffer.end.freq == 0) + tf->buffer.end.freq = tf->trace->start_freq; + tf->buffer.lost_size = ltt_get_uint32(LTT_GET_BO(tf), &header->lost_size); tf->buffer.end.timestamp = ltt_interpolate_time_from_tsc(tf, - tf->buffer.end.cycle_count); + tf->buffer.end.cycle_count); #if 0 - ltt_time_add( + ltt_time_add( ltt_time_from_uint64( (double)(tf->buffer.end.cycle_count - tf->trace->start_tsc) * 1000000.0 @@ -1998,90 +2133,108 @@ map_error: void ltt_update_event_size(LttTracefile *tf) { off_t size = 0; - - /* Specific handling of core events : necessary to read the facility control - * tracefile. */ LttFacility *f = ltt_trace_get_facility_by_num(tf->trace, tf->event.facility_id); - - if(likely(tf->event.facility_id == LTT_FACILITY_CORE)) { - switch((enum ltt_core_events)tf->event.event_id) { - case LTT_EVENT_FACILITY_LOAD: - size = strlen((char*)tf->event.data) + 1; - //g_debug("Update Event facility load of facility %s", (char*)tf->event.data); - size += ltt_align(size, sizeof(guint32), tf->has_alignment); - size += sizeof(struct LttFacilityLoad); - break; - case LTT_EVENT_FACILITY_UNLOAD: - //g_debug("Update Event facility unload"); - size = sizeof(struct LttFacilityUnload); - break; - case LTT_EVENT_STATE_DUMP_FACILITY_LOAD: - size = strlen((char*)tf->event.data) + 1; - size += ltt_align(size, sizeof(guint32), tf->has_alignment); - //g_debug("Update Event facility load state dump of facility %s", - // (char*)tf->event.data); - size += sizeof(struct LttStateDumpFacilityLoad); - break; - case LTT_EVENT_HEARTBEAT: - //g_debug("Update Event heartbeat"); - size = sizeof(TimeHeartbeat); - break; - default: - g_warning("Error in getting event size : tracefile %s, " - "unknown event id %hhu in core facility.", - g_quark_to_string(tf->name), - tf->event.event_id); - goto event_id_error; - - } - } else { - if(!f->exists) { + char *tscdata; + + if(!f->exists) { + /* Specific handling of core events : necessary to read the facility control + * tracefile. */ + + if(likely(tf->event.facility_id == LTT_FACILITY_CORE)) { + switch((enum ltt_core_events)tf->event.event_id) { + case LTT_EVENT_FACILITY_LOAD: + size = strlen((char*)tf->event.data) + 1; + //g_debug("Update Event facility load of facility %s", (char*)tf->event.data); + size += ltt_align(size, sizeof(guint32), tf->has_alignment); + size += sizeof(struct LttFacilityLoad); + break; + case LTT_EVENT_FACILITY_UNLOAD: + //g_debug("Update Event facility unload"); + size = sizeof(struct LttFacilityUnload); + break; + case LTT_EVENT_STATE_DUMP_FACILITY_LOAD: + size = strlen((char*)tf->event.data) + 1; + size += ltt_align(size, sizeof(guint32), tf->has_alignment); + //g_debug("Update Event facility load state dump of facility %s", + // (char*)tf->event.data); + size += sizeof(struct LttStateDumpFacilityLoad); + break; + case LTT_EVENT_HEARTBEAT: + //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.", + g_quark_to_string(tf->name), + tf->event.event_id); + goto event_id_error; + + } + goto no_offset; /* Skip the field computation */ + } else { g_warning("Unknown facility %hhu (0x%hhx) in tracefile %s", tf->event.facility_id, tf->event.facility_id, g_quark_to_string(tf->name)); goto facility_error; } + } - LttEventType *event_type = - ltt_facility_eventtype_get(f, tf->event.event_id); + LttEventType *event_type = + ltt_facility_eventtype_get(f, tf->event.event_id); - if(!event_type) { - g_warning("Unknown event id %hhu in facility %s in tracefile %s", - tf->event.event_id, - g_quark_to_string(f->name), - g_quark_to_string(tf->name)); - goto event_type_error; - } - - /* Compute the dynamic offsets */ - compute_offsets(tf, f, event_type, &size, tf->event.data); - - //g_debug("Event root field : f.e %hhu.%hhu size %zd", - // tf->event.facility_id, - // tf->event.event_id, size); + if(!event_type) { + g_warning("Unknown event id %hhu in facility %s in tracefile %s", + tf->event.event_id, + g_quark_to_string(f->name), + g_quark_to_string(tf->name)); + goto event_type_error; } + /* Compute the dynamic offsets */ + compute_offsets(tf, f, event_type, &size, tf->event.data); + + //g_debug("Event root field : f.e %hhu.%hhu size %zd", + // tf->event.facility_id, + // tf->event.event_id, size); + +no_offset: tf->event.data_size = size; /* Check consistency between kernel and LTTV structure sizes */ - if(tf->event.event_size == 0xFFFF) { - /* 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.event_size == 0xFFFF) { + /* Event size too big to fit in the event size field */ + tf->event.event_size = tf->event.data_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; facility_error: event_type_error: event_id_error: - if(tf->event.event_size == 0xFFFF) { - g_error("Cannot jump over an unknown event bigger than 0xFFFE bytes"); - } - /* The facility is unknown : use the kernel information about this event - * to jump over it. */ + if(tf->event.event_size == 0xFFFF) { + g_error("Cannot jump over an unknown event bigger than 0xFFFE bytes"); + } + /* The facility is unknown : use the kernel information about this event + * to jump over it. */ tf->event.data_size = tf->event.event_size; } @@ -2228,10 +2381,11 @@ off_t get_alignment(LttField *field) case LTT_FLOAT: case LTT_ENUM: /* Align offset on type size */ + g_assert(field->field_size != 0); return field->field_size; break; case LTT_STRING: - return 0; + return 1; break; case LTT_ARRAY: g_assert(type->fields->len == 1); @@ -2243,7 +2397,7 @@ off_t get_alignment(LttField *field) case LTT_SEQUENCE: g_assert(type->fields->len == 2); { - off_t localign = 0; + off_t localign = 1; LttField *child = &g_array_index(type->fields, LttField, 0); localign = max(localign, get_alignment(child)); @@ -2258,7 +2412,7 @@ off_t get_alignment(LttField *field) case LTT_UNION: { guint i; - off_t localign = 0; + off_t localign = 1; for(i=0; ifields->len; i++) { LttField *child = &g_array_index(type->fields, LttField, i); @@ -2270,8 +2424,8 @@ off_t get_alignment(LttField *field) case LTT_NONE: default: g_error("get_alignment : unknown type"); + return -1; } - } /***************************************************************************** @@ -2382,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: @@ -2459,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); @@ -2488,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; } @@ -2510,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; } @@ -2552,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; } } @@ -2614,6 +2784,12 @@ void preset_field_type_size(LttTracefile *tf, LttEventType *event_type, size_t max_size; switch(type->type_class) { + case LTT_INT_FIXED: + case LTT_UINT_FIXED: + case LTT_CHAR: + case LTT_UCHAR: + case LTT_SHORT: + case LTT_USHORT: case LTT_INT: case LTT_UINT: case LTT_FLOAT: @@ -2714,8 +2890,8 @@ void preset_field_type_size(LttTracefile *tf, LttEventType *event_type, max_size = max(max_size, field->child[i]->field_size); } if(final_child_status != FIELD_FIXED) { - g_error("LTTV does not support variable size fields in unions."); - /* This will stop the application. */ + g_error("LTTV does not support variable size fields in unions."); + /* This will stop the application. */ *fixed_root = final_child_status; *fixed_parent = final_child_status; field->field_size = 0; @@ -2725,6 +2901,9 @@ void preset_field_type_size(LttTracefile *tf, LttEventType *event_type, field->fixed_size = FIELD_FIXED; } break; + case LTT_NONE: + g_error("unexpected type NONE"); + break; } } @@ -2771,10 +2950,10 @@ gint check_fields_compatibility(LttEventType *event_type1, different = 1; goto end; } - if(type1->network != type2->network) { - different = 1; - goto end; - } + if(type1->network != type2->network) { + different = 1; + goto end; + } switch(type1->type_class) { case LTT_INT_FIXED: @@ -2843,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: @@ -2892,6 +3071,13 @@ gint check_fields_compatibility(LttEventType *event_type1, } switch(type1->type_class) { + case LTT_INT_FIXED: + case LTT_UINT_FIXED: + case LTT_POINTER: + case LTT_CHAR: + case LTT_UCHAR: + case LTT_SHORT: + case LTT_USHORT: case LTT_INT: case LTT_UINT: case LTT_FLOAT: @@ -3082,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"); }