#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);
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;
&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;
&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;
/* map block header */
header = mmap(0, header_map_size, PROT_READ,
- MAP_PRIVATE, tf->fd, 0);
+ MAP_PRIVATE, tf->fd, (off_t)offset);
if(header == MAP_FAILED) {
perror("Error in allocating memory for buffer of tracefile");
return -1;
unsigned int i;
LttTracefile *tf;
- if (group->len > 0)
- destroy_marker_data(g_array_index (group, LttTracefile, 0).mdata);
for(i=0; i<group->len; 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);
}
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;
gchar rel_path[PATH_MAX];
gchar *rel_path_ptr;
LttTracefile tmp_tf;
+ struct marker_data **mdata;
if(dir == NULL) {
perror(root_path);
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;
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 */
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");
}
}
g_assert(!ret);
t->num_cpu = group->len;
+ t->drift = 1.;
+ t->offset = 0.;
//ret = allocate_marker_data(t);
//if (ret)
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 */
ret = get_block_offset_size(tf, block_num, &offset, &size);
g_assert(!ret);
+ g_debug("Map block %u, offset %llu, size %u\n", block_num,
+ (unsigned long long)offset, (unsigned int)size);
+
/* Multiple of pages aligned head */
tf->buffer.head = mmap(0, (size_t)size, PROT_READ, MAP_PRIVATE,
tf->fd, (off_t)offset);
tf->buffer.offset = offset;
tf->buffer.size = ltt_get_uint32(LTT_GET_BO(tf),
&header->sb_size);
- g_assert(size == tf->buffer.size);
tf->buffer.data_size = ltt_get_uint32(LTT_GET_BO(tf),
&header->data_size);
tf->buffer.tsc = tf->buffer.begin.cycle_count;
tf->event.tsc = tf->buffer.tsc;
tf->buffer.freq = tf->buffer.begin.freq;
+ g_assert(size == tf->buffer.size);
g_assert(tf->buffer.data_size <= tf->buffer.size);
if (tf->trace->start_freq)
{
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;
+}