X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Fltt%2Ftracefile.c;h=ad2cf51af5c93f680e3a273da8f580a414957033;hb=a4fa48a2c30e710db39d3a7093961257ead5eb0d;hp=20ba35dec91d9ccb1a628485299824d129e08212;hpb=79257ba540581e198c9d9b047fe0738a25c324ff;p=lttv.git diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c index 20ba35de..ad2cf51a 100644 --- a/ltt/branches/poly/ltt/tracefile.c +++ b/ltt/branches/poly/ltt/tracefile.c @@ -93,7 +93,10 @@ static inline void preset_field_type_size(LttTracefile *tf, static gint map_block(LttTracefile * tf, guint block_num); /* calculate nsec per cycles for current block */ -static double calc_nsecs_per_cycle(LttTracefile * t); +#if 0 +static guint32 calc_nsecs_per_cycle(LttTracefile * t); +static guint64 cycles_2_ns(LttTracefile *tf, guint64 cycles); +#endif //0 /* go to the next event */ static int ltt_seek_next_event(LttTracefile *tf); @@ -191,6 +194,97 @@ guint ltt_trace_get_num_cpu(LttTrace *t) } +/* trace can be NULL + * + * Return value : 0 success, 1 bad tracefile + */ +int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t) +{ + guint32 *magic_number = (guint32*)header; + struct ltt_trace_header_any *any = (struct ltt_trace_header_any *)header; + + if(*magic_number == LTT_MAGIC_NUMBER) + tf->reverse_bo = 0; + else if(*magic_number == LTT_REV_MAGIC_NUMBER) + tf->reverse_bo = 1; + else /* invalid magic number, bad tracefile ! */ + return 1; + + /* Get float byte order : might be different from int byte order + * (or is set to 0 if the trace has no float (kernel trace)) */ + tf->float_word_order = any->float_word_order; + + if(t) { + t->arch_type = ltt_get_uint32(LTT_GET_BO(tf), + &any->arch_type); + t->arch_variant = ltt_get_uint32(LTT_GET_BO(tf), + &any->arch_variant); + t->arch_size = any->arch_size; + 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->has_alignment = any->has_alignment; + t->has_tsc = any->has_tsc; + } + + + switch(any->major_version) { + + case 0: + switch(any->minor_version) { + case 3: + { + tf->buffer_header_size = + sizeof(struct ltt_block_start_header) + + sizeof(struct ltt_trace_header_0_3); + g_warning("Unsupported trace version : %hhu.%hhu", + any->major_version, any->minor_version); + return 1; + } + break; + case 4: + { + struct ltt_trace_header_0_4 *vheader = + (struct ltt_trace_header_0_4 *)header; + tf->buffer_header_size = + sizeof(struct ltt_block_start_header) + + sizeof(struct ltt_trace_header_0_4); + if(t) { + t->start_freq = ltt_get_uint64(LTT_GET_BO(tf), + &vheader->start_freq); + 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 = ltt_get_time(LTT_GET_BO(tf), + &vheader->start_time); + 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); + } + } + break; + default: + g_warning("Unsupported trace version : %hhu.%hhu", + any->major_version, any->minor_version); + return 1; + } + break; + + default: + g_warning("Unsupported trace version : %hhu.%hhu", + any->major_version, any->minor_version); + return 1; + } + + + return 0; +} + + + /***************************************************************************** *Function name * ltt_tracefile_open : open a trace file, construct a LttTracefile @@ -224,7 +318,9 @@ gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) } // Is the file large enough to contain a trace - if(lTDFStat.st_size < (off_t)(sizeof(struct ltt_block_start_header))){ + if(lTDFStat.st_size < + (off_t)(sizeof(struct ltt_block_start_header) + + sizeof(struct ltt_trace_header_any))){ g_print("The input data file %s does not contain a trace\n", fileName); goto close_file; } @@ -232,7 +328,8 @@ gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) /* Temporarily map the buffer start header to get trace information */ /* Multiple of pages aligned head */ tf->buffer.head = mmap(0, - PAGE_ALIGN(sizeof(struct ltt_block_start_header)), PROT_READ, + PAGE_ALIGN(sizeof(struct ltt_block_start_header) + + sizeof(struct ltt_trace_header_any)), PROT_READ, MAP_PRIVATE, tf->fd, 0); if(tf->buffer.head == MAP_FAILED) { perror("Error in allocating memory for buffer of tracefile"); @@ -242,15 +339,10 @@ gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) header = (struct ltt_block_start_header*)tf->buffer.head; - if(header->trace.magic_number == LTT_MAGIC_NUMBER) - tf->reverse_bo = 0; - else if(header->trace.magic_number == LTT_REV_MAGIC_NUMBER) - tf->reverse_bo = 1; - else /* invalid magic number, bad tracefile ! */ + if(parse_trace_header(header->trace, tf, NULL)) { + g_warning("parse_trace_header error"); goto unmap_file; - /* Get float byte order : might be different from int byte order - * (or is set to 0 if the trace has no float (kernel trace)) */ - tf->float_word_order = header->trace.float_word_order; + } //store the size of the file tf->file_size = lTDFStat.st_size; @@ -258,9 +350,11 @@ gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) tf->num_blocks = tf->file_size / tf->buf_size; if(munmap(tf->buffer.head, - PAGE_ALIGN(sizeof(struct ltt_block_start_header)))) { + PAGE_ALIGN(sizeof(struct ltt_block_start_header) + + sizeof(struct ltt_trace_header_any)))) { g_warning("unmap size : %u\n", - PAGE_ALIGN(sizeof(struct ltt_block_start_header))); + PAGE_ALIGN(sizeof(struct ltt_block_start_header) + + sizeof(struct ltt_trace_header_any))); perror("munmap error"); g_assert(0); } @@ -277,9 +371,11 @@ gint ltt_tracefile_open(LttTrace *t, gchar * fileName, LttTracefile *tf) /* Error */ unmap_file: if(munmap(tf->buffer.head, - PAGE_ALIGN(sizeof(struct ltt_block_start_header)))) { + PAGE_ALIGN(sizeof(struct ltt_block_start_header) + + sizeof(struct ltt_trace_header_any)))) { g_warning("unmap size : %u\n", - PAGE_ALIGN(sizeof(struct ltt_block_start_header))); + PAGE_ALIGN(sizeof(struct ltt_block_start_header) + + sizeof(struct ltt_trace_header_any))); perror("munmap error"); g_assert(0); } @@ -737,7 +833,7 @@ static int open_tracefiles(LttTrace *trace, gchar *root_path, /* ltt_get_facility_description * - * Opens the trace corresponding to the requested facility (identified by fac_id + * Opens the file corresponding to the requested facility (identified by fac_id * and checksum). * * The name searched is : %trace root%/eventdefs/facname_checksum.xml @@ -769,7 +865,7 @@ static int ltt_get_facility_description(LttFacility *f, textlen+=strlen(text); if(textlen >= PATH_MAX) goto name_error; strcat(desc_file_name, text); - +#if 0 text = "_"; textlen+=strlen(text); if(textlen >= PATH_MAX) goto name_error; @@ -781,11 +877,12 @@ static int ltt_get_facility_description(LttFacility *f, textlen=strlen(desc_file_name); +#endif //0 text = ".xml"; textlen+=strlen(text); if(textlen >= PATH_MAX) goto name_error; strcat(desc_file_name, text); - + err = ltt_facility_open(f, t, desc_file_name); if(err) goto facility_error; @@ -1048,15 +1145,8 @@ LttTrace *ltt_trace_open(const gchar *pathname) g_assert(group->len > 0); tf = &g_array_index (group, LttTracefile, 0); header = (struct ltt_block_start_header*)tf->buffer.head; - t->arch_type = ltt_get_uint32(LTT_GET_BO(tf), &header->trace.arch_type); - t->arch_variant = ltt_get_uint32(LTT_GET_BO(tf), &header->trace.arch_variant); - t->arch_size = header->trace.arch_size; - t->ltt_major_version = header->trace.major_version; - t->ltt_minor_version = header->trace.minor_version; - t->flight_recorder = header->trace.flight_recorder; - t->has_heartbeat = header->trace.has_heartbeat; - t->has_alignment = header->trace.has_alignment; - t->has_tsc = header->trace.has_tsc; + g_assert(parse_trace_header(header->trace, + tf, t) == 0); t->num_cpu = group->len; @@ -1257,11 +1347,17 @@ void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end) *Get the name of a tracefile ****************************************************************************/ -GQuark ltt_tracefile_name(LttTracefile *tf) +GQuark ltt_tracefile_name(const LttTracefile *tf) { return tf->name; } +GQuark ltt_tracefile_long_name(const LttTracefile *tf) +{ + return tf->long_name; +} + + guint ltt_tracefile_num(LttTracefile *tf) { @@ -1365,16 +1461,16 @@ int ltt_tracefile_seek_time(LttTracefile *tf, LttTime time) if(ret == ERANGE) goto range; /* ERANGE or EPERM */ else if(ret) goto fail; - if(ltt_time_compare(time, tf->event.event_time) >= 0) + if(ltt_time_compare(time, tf->event.event_time) <= 0) goto found; } } else if(ltt_time_compare(time, tf->buffer.begin.timestamp) < 0) { /* go to lower part */ - high = block_num; + high = block_num - 1; } else if(ltt_time_compare(time, tf->buffer.end.timestamp) > 0) { /* go to higher part */ - low = block_num; + low = block_num + 1; } else {/* The event is right in the buffer! (or in the next buffer first event) */ while(1) { @@ -1382,7 +1478,7 @@ int ltt_tracefile_seek_time(LttTracefile *tf, LttTime time) if(ret == ERANGE) goto range; /* ERANGE or EPERM */ else if(ret) goto fail; - if(ltt_time_compare(time, tf->event.event_time) >= 0) + if(ltt_time_compare(time, tf->event.event_time) <= 0) break; } goto found; @@ -1438,10 +1534,13 @@ LttTime ltt_interpolate_time(LttTracefile *tf, LttEvent *event) g_assert(tf->trace->has_tsc); +// time = ltt_time_from_uint64( +// cycles_2_ns(tf, (guint64)(tf->buffer.tsc - tf->buffer.begin.cycle_count))); time = ltt_time_from_uint64( - (guint64)(tf->buffer.tsc - tf->buffer.begin.cycle_count) * - tf->buffer.nsecs_per_cycle); - time = ltt_time_add(tf->buffer.begin.timestamp, time); + (double)(tf->buffer.tsc - tf->trace->start_tsc) * 1000000.0 + / (double)tf->trace->start_freq); + //time = ltt_time_add(tf->buffer.begin.timestamp, time); + time = ltt_time_add(tf->trace->start_time_from_tsc, time); return time; } @@ -1656,25 +1755,53 @@ static gint map_block(LttTracefile * tf, guint block_num) header = (struct ltt_block_start_header*)tf->buffer.head; - tf->buffer.begin.timestamp = ltt_get_time(LTT_GET_BO(tf), - &header->begin.timestamp); - tf->buffer.begin.timestamp.tv_nsec *= NSEC_PER_USEC; - g_debug("block %u begin : %lu.%lu", block_num, - tf->buffer.begin.timestamp.tv_sec, tf->buffer.begin.timestamp.tv_nsec); +#if 0 + tf->buffer.begin.timestamp = ltt_time_add( + ltt_time_from_uint64( + ltt_get_uint64(LTT_GET_BO(tf), + &header->begin.timestamp) + - tf->trace->start_monotonic), + tf->trace->start_time); +#endif //0 + //g_debug("block %u begin : %lu.%lu", block_num, + // tf->buffer.begin.timestamp.tv_sec, tf->buffer.begin.timestamp.tv_nsec); tf->buffer.begin.cycle_count = ltt_get_uint64(LTT_GET_BO(tf), &header->begin.cycle_count); - tf->buffer.end.timestamp = ltt_get_time(LTT_GET_BO(tf), - &header->end.timestamp); - tf->buffer.end.timestamp.tv_nsec *= NSEC_PER_USEC; - g_debug("block %u end : %lu.%lu", block_num, - tf->buffer.end.timestamp.tv_sec, tf->buffer.end.timestamp.tv_nsec); + tf->buffer.begin.freq = ltt_get_uint64(LTT_GET_BO(tf), + &header->begin.freq); + tf->buffer.begin.timestamp = 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); +#if 0 + + tf->buffer.end.timestamp = ltt_time_add( + ltt_time_from_uint64( + ltt_get_uint64(LTT_GET_BO(tf), + &header->end.timestamp) + - tf->trace->start_monotonic), + tf->trace->start_time); +#endif //0 + //g_debug("block %u end : %lu.%lu", block_num, + // tf->buffer.end.timestamp.tv_sec, tf->buffer.end.timestamp.tv_nsec); tf->buffer.end.cycle_count = ltt_get_uint64(LTT_GET_BO(tf), &header->end.cycle_count); + tf->buffer.end.freq = ltt_get_uint64(LTT_GET_BO(tf), + &header->end.freq); tf->buffer.lost_size = ltt_get_uint32(LTT_GET_BO(tf), - &header->lost_size); - + &header->lost_size); + tf->buffer.end.timestamp = ltt_time_add( + ltt_time_from_uint64( + (double)(tf->buffer.end.cycle_count + - tf->trace->start_tsc) * 1000000.0 + / (double)tf->trace->start_freq), + tf->trace->start_time_from_tsc); + tf->buffer.tsc = tf->buffer.begin.cycle_count; tf->event.tsc = tf->buffer.tsc; + tf->buffer.freq = tf->buffer.begin.freq; /* FIXME * eventually support variable buffer size : will need a partial pre-read of @@ -1685,7 +1812,8 @@ static gint map_block(LttTracefile * tf, guint block_num) /* Now that the buffer is mapped, calculate the time interpolation for the * block. */ - tf->buffer.nsecs_per_cycle = calc_nsecs_per_cycle(tf); +// tf->buffer.nsecs_per_cycle = calc_nsecs_per_cycle(tf); + //tf->buffer.cyc2ns_scale = calc_nsecs_per_cycle(tf); /* Make the current event point to the beginning of the buffer : * it means that the event read must get the first event. */ @@ -1714,21 +1842,21 @@ void ltt_update_event_size(LttTracefile *tf) 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); + //g_debug("Update Event facility load of facility %s", (char*)tf->event.data); size += sizeof(struct LttFacilityLoad); break; case LTT_EVENT_FACILITY_UNLOAD: - g_debug("Update 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; - g_debug("Update Event facility load state dump of facility %s", - (char*)tf->event.data); + //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"); + //g_debug("Update Event heartbeat"); size = sizeof(TimeHeartbeat); break; default: @@ -1765,9 +1893,9 @@ void ltt_update_event_size(LttTracefile *tf) else size = 0; - g_debug("Event root field : f.e %hhu.%hhu size %zd", - tf->event.facility_id, - tf->event.event_id, size); + //g_debug("Event root field : f.e %hhu.%hhu size %zd", + // tf->event.facility_id, + // tf->event.event_id, size); } tf->event.data_size = size; @@ -1802,7 +1930,7 @@ static int ltt_seek_next_event(LttTracefile *tf) /* seek over the buffer header if we are at the buffer start */ if(tf->event.offset == 0) { - tf->event.offset += sizeof(struct ltt_block_start_header); + tf->event.offset += tf->buffer_header_size; if(tf->event.offset == tf->buf_size - tf->buffer.lost_size) { ret = ERANGE; @@ -1823,6 +1951,7 @@ static int ltt_seek_next_event(LttTracefile *tf) ret = ERANGE; goto found; } + g_assert(tf->event.offset < tf->buf_size - tf->buffer.lost_size); found: return ret; @@ -1833,34 +1962,33 @@ error: return ENOPROTOOPT; } - +#if 0 /***************************************************************************** *Function name * calc_nsecs_per_cycle : calculate nsecs per cycle for current block + * + * 1.0 / (freq(khz) *1000) * 1000000000 *Input Params * t : tracefile ****************************************************************************/ - -static double calc_nsecs_per_cycle(LttTracefile * tf) +/* from timer_tsc.c */ +#define CYC2NS_SCALE_FACTOR 10 +static guint32 calc_nsecs_per_cycle(LttTracefile * tf) { - LttTime lBufTotalTime; /* Total time for this buffer */ - double lBufTotalNSec; /* Total time for this buffer in nsecs */ - LttCycleCount lBufTotalCycle;/* Total cycles for this buffer */ - - /* Calculate the total time for this buffer */ - lBufTotalTime = ltt_time_sub(tf->buffer.end.timestamp, - tf->buffer.begin.timestamp); - - /* Calculate the total cycles for this bufffer */ - lBufTotalCycle = tf->buffer.end.cycle_count; - lBufTotalCycle -= tf->buffer.begin.cycle_count; - - /* Convert the total time to double */ - lBufTotalNSec = ltt_time_to_double(lBufTotalTime); + //return 1e6 / (double)tf->buffer.freq; + guint32 cpu_mhz = tf->buffer.freq / 1000; + guint32 cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz; - return lBufTotalNSec / (double)lBufTotalCycle; + return cyc2ns_scale; + // return 1e6 / (double)tf->buffer.freq; +} +static guint64 cycles_2_ns(LttTracefile *tf, guint64 cycles) +{ + return (cycles * tf->buffer.cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; } +#endif //0 + #if 0 void setFieldsOffset(LttTracefile *tf, LttEventType *evT,void *evD) { @@ -2429,13 +2557,17 @@ char * ltt_trace_system_description_description (LttSystemDescription * s) } -/* get the start time of the trace */ - -LttTime ltt_trace_system_description_trace_start_time(LttSystemDescription *s) +/* get the NTP corrected start time of the trace */ +LttTime ltt_trace_start_time(LttTrace *t) { - return s->trace_start; + return t->start_time; } +/* get the monotonic start time of the trace */ +LttTime ltt_trace_start_time_monotonic(LttTrace *t) +{ + return t->start_time_from_tsc; +} LttTracefile *ltt_tracefile_new() {