X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=ltt%2Ftracefile.c;h=2dbbbcf119be2573dc1991afe5ad36fecf5ffc7a;hb=f972ab5e81be30df0ef5d690a55a6876c27b1d40;hp=d61f4af879f2425ef243abc63549dbdbd6e5b848;hpb=9355666580b6f4f8fc006e8a89f46833e3cf30ee;p=lttv.git diff --git a/ltt/tracefile.c b/ltt/tracefile.c index d61f4af8..2dbbbcf1 100644 --- a/ltt/tracefile.c +++ b/ltt/tracefile.c @@ -80,8 +80,6 @@ GQuark LTT_TRACEFILE_NAME_METADATA; #define PAGE_MASK (~(page_size-1)) #define PAGE_ALIGN(addr) (((addr)+page_size-1)&PAGE_MASK) -LttTrace *father_trace = NULL; - /* set the offset of the fields belonging to the event, need the information of the archecture */ //void set_fields_offsets(LttTracefile *tf, LttEventType *event_type); @@ -150,9 +148,9 @@ static int parse_trace_header(ltt_subbuffer_header_t *header, break; case 2: switch(header->minor_version) { - case 5: + case 6: { - struct ltt_subbuffer_header_2_5 *vheader = header; + struct ltt_subbuffer_header_2_6 *vheader = header; tf->buffer_header_size = ltt_subbuffer_header_size(); tf->tscbits = 27; tf->eventbits = 5; @@ -164,12 +162,6 @@ static int parse_trace_header(ltt_subbuffer_header_t *header, &vheader->start_freq); t->freq_scale = ltt_get_uint32(LTT_GET_BO(tf), &vheader->freq_scale); - if(father_trace) { - t->start_freq = father_trace->start_freq; - t->freq_scale = father_trace->freq_scale; - } else { - father_trace = t; - } t->start_tsc = ltt_get_uint64(LTT_GET_BO(tf), &vheader->cycle_count_begin); t->start_monotonic = 0; @@ -179,10 +171,9 @@ static int parse_trace_header(ltt_subbuffer_header_t *header, &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->start_time_from_tsc = + ltt_time_from_uint64(tsc_to_uint64(t->freq_scale, + t->start_freq, t->start_tsc)); } } break; @@ -553,12 +544,12 @@ static void ltt_tracefile_group_destroy(gpointer data) unsigned int i; LttTracefile *tf; - if (group->len > 0) - destroy_marker_data(g_array_index (group, LttTracefile, 0).mdata); for(i=0; ilen; i++) { tf = &g_array_index (group, LttTracefile, i); - if(tf->cpu_online) + if(tf->cpu_online) { + destroy_marker_data(tf->mdata); ltt_tracefile_close(tf); + } } g_array_free(group, TRUE); } @@ -594,8 +585,7 @@ static int open_tracefiles(LttTrace *trace, gchar *root_path, gchar *relative_pa DIR *dir = opendir(root_path); struct dirent *entry; struct stat stat_buf; - int ret, i; - struct marker_data *mdata; + int ret; gchar path[PATH_MAX]; int path_len; @@ -605,6 +595,7 @@ static int open_tracefiles(LttTrace *trace, gchar *root_path, gchar *relative_pa gchar rel_path[PATH_MAX]; gchar *rel_path_ptr; LttTracefile tmp_tf; + struct marker_data **mdata; if(dir == NULL) { perror(root_path); @@ -667,7 +658,6 @@ static int open_tracefiles(LttTrace *trace, gchar *root_path, gchar *relative_pa g_debug("Tracefile name is %s and number is %u", g_quark_to_string(name), num); - mdata = NULL; tmp_tf.cpu_online = 1; tmp_tf.cpu_num = num; tmp_tf.name = name; @@ -682,9 +672,6 @@ static int open_tracefiles(LttTrace *trace, gchar *root_path, gchar *relative_pa group = g_array_sized_new (FALSE, TRUE, sizeof(LttTracefile), 10); g_datalist_id_set_data_full(&trace->tracefiles, name, group, ltt_tracefile_group_destroy); - mdata = allocate_marker_data(); - if (!mdata) - g_error("Error in allocating marker data"); } /* Add the per cpu tracefile to the named group */ @@ -692,15 +679,13 @@ static int open_tracefiles(LttTrace *trace, gchar *root_path, gchar *relative_pa if(num+1 > old_len) group = g_array_set_size(group, num+1); - g_assert(group->len > 0); - if (!mdata) - mdata = g_array_index (group, LttTracefile, 0).mdata; - g_array_index (group, LttTracefile, num) = tmp_tf; g_array_index (group, LttTracefile, num).event.tracefile = &g_array_index (group, LttTracefile, num); - for (i = 0; i < group->len; i++) - g_array_index (group, LttTracefile, i).mdata = mdata; + mdata = &g_array_index (group, LttTracefile, num).mdata; + *mdata = allocate_marker_data(); + if (!*mdata) + g_error("Error in allocating marker data"); } } @@ -880,6 +865,8 @@ LttTrace *ltt_trace_open(const gchar *pathname) g_assert(!ret); t->num_cpu = group->len; + t->drift = 1.; + t->offset = 0.; //ret = allocate_marker_data(t); //if (ret) @@ -1162,28 +1149,22 @@ fail: return 1; } +/* + * Convert a value in "TSC scale" to a value in nanoseconds + */ +guint64 tsc_to_uint64(guint32 freq_scale, uint64_t start_freq, guint64 tsc) +{ + return (double) tsc * NANOSECONDS_PER_SECOND * freq_scale / start_freq; +} + /* Given a TSC value, return the LttTime (seconds,nanoseconds) it * corresponds to. */ - 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); - } - return time; + return ltt_time_from_uint64(tsc_to_uint64(tf->trace->freq_scale, + tf->trace->start_freq, tf->trace->drift * tsc + + tf->trace->offset)); } /* Calculate the real event time based on the buffer boundaries */ @@ -1803,3 +1784,138 @@ static __attribute__((constructor)) void init(void) { LTT_TRACEFILE_NAME_METADATA = g_quark_from_string("metadata"); } + +/***************************************************************************** + *Function name + * ltt_tracefile_open_header : based on ltt_tracefile_open but it stops + * when it gets the header + *Input params + * fileName : path to the tracefile + * tf : the tracefile (metadata_0) where the header will be read + *Return value + * ltt_subbuffer_header_t : the header containing the version number + ****************************************************************************/ +static ltt_subbuffer_header_t * ltt_tracefile_open_header(gchar *fileName, LttTracefile *tf) +{ + struct stat lTDFStat; /* Trace data file status */ + ltt_subbuffer_header_t *header; + int page_size = getpagesize(); + + /* open the file */ + tf->long_name = g_quark_from_string(fileName); + tf->fd = open(fileName, O_RDONLY); + if(tf->fd < 0){ + g_warning("Unable to open input data file %s\n", fileName); + goto end; + } + + /* Get the file's status */ + if(fstat(tf->fd, &lTDFStat) < 0){ + g_warning("Unable to get the status of the input data file %s\n", fileName); + goto close_file; + } + + /* Is the file large enough to contain a trace */ + if(lTDFStat.st_size < (off_t)(ltt_subbuffer_header_size())) { + g_print("The input data file %s does not contain a trace\n", fileName); + goto close_file; + } + + /* Temporarily map the buffer start header to get trace information */ + /* Multiple of pages aligned head */ + tf->buffer.head = mmap(0,PAGE_ALIGN(ltt_subbuffer_header_size()), PROT_READ, MAP_PRIVATE, tf->fd, 0); + + if(tf->buffer.head == MAP_FAILED) { + perror("Error in allocating memory for buffer of tracefile"); + goto close_file; + } + g_assert( ( (gulong)tf->buffer.head&(8-1) ) == 0); // make sure it's aligned. + + header = (ltt_subbuffer_header_t *)tf->buffer.head; + + return header; + + close_file: + close(tf->fd); + end: + return 0; +} + + +/***************************************************************************** + *Function name + * get_version : get the trace version from a metadata_0 trace file + *Input params + * pathname : path to the trace + * version_number : the struct that will get the version number + *Return value + * int : 1 if succeed, -1 if error + ****************************************************************************/ +int ltt_get_trace_version(const gchar *pathname, struct LttTraceVersion *version_number) +{ + gchar abs_path[PATH_MAX]; + int ret = 0; + DIR *dir; + struct dirent *entry; + struct stat stat_buf; + gchar path[PATH_MAX]; + + LttTracefile tmp_tf; + LttTrace * t; + ltt_subbuffer_header_t *header; + + t = g_new(LttTrace, 1); + + get_absolute_pathname(pathname, abs_path); + + /* 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) { + strcpy(path, abs_path); + strcat(path, "/"); + strcat(path, entry->d_name); + ret = stat(path, &stat_buf); + if(ret == -1) { + perror(path); + continue; + } + } + + closedir(dir); + dir = opendir(abs_path); + + while((entry = readdir(dir)) != NULL) { + if(entry->d_name[0] == '.') continue; + if(g_strcmp0(entry->d_name, "metadata_0") != 0) continue; + + strcpy(path, abs_path); + strcat(path, "/"); + strcat(path, entry->d_name); + if(ret == -1) { + perror(path); + continue; + } + + header = ltt_tracefile_open_header(path, &tmp_tf); + + if(header == NULL) { + g_info("Error getting the header %s", path); + continue; /* error opening the tracefile : bad magic number ? */ + } + + version_number->ltt_major_version = header->major_version; + version_number->ltt_minor_version = header->minor_version; + } + + return 0; + + open_error: + g_free(t); + return -1; +}