type_descriptor_t *td;
LttType *type;
- field->name = g_quark_from_string(fld->name);
+ if(fld->name)
+ field->name = g_quark_from_string(fld->name);
+ else
+ fld->name = 0;
+
if(fld->description) {
len = strlen(fld->description);
field->description = g_new(gchar, len+1);
GQuark long_name; //tracefile complete filename
GQuark name; //tracefile name
guint cpu_num; //cpu number of the tracefile
+ guint tid; //Usertrace tid, else 0
+ guint pgid; //Usertrace pgid, else 0
+ guint64 creation; //Usertrace creation, else 0
LttTrace * trace; //trace containing the tracefile
int fd; //file descriptor
off_t file_size; //file size
/* get the cpu number of the tracefile */
-guint ltt_tracefile_num(LttTracefile *tf);
+guint ltt_tracefile_cpu(LttTracefile *tf);
+
+/* For usertrace */
+guint ltt_tracefile_tid(LttTracefile *tf);
+guint ltt_tracefile_pgid(LttTracefile *tf);
+guint64 ltt_tracefile_creation(LttTracefile *tf);
+
LttTrace *ltt_tracefile_get_trace(LttTracefile *tf);
guint64 ltt_get_uint(gboolean reverse_byte_order, gint size, void *data);
+LttTime ltt_interpolate_time_from_tsc(LttTracefile *tf, guint64 tsc);
+
#endif // TRACE_H
* The left side is the name, the right side is the number.
*/
-int get_tracefile_name_number(const gchar *raw_name,
+int get_tracefile_name_number(gchar *raw_name,
GQuark *name,
- guint *num)
+ guint *num,
+ guint *tid,
+ guint *pgid,
+ guint64 *creation)
{
guint raw_name_len = strlen(raw_name);
gchar char_name[PATH_MAX];
int underscore_pos;
long int cpu_num;
gchar *endptr;
+ gchar *tmpptr;
for(i=raw_name_len-1;i>=0;i--) {
if(raw_name[i] == '_') break;
}
- if(i==0) /* Either not found or name length is 0 */
- return -1;
- underscore_pos = i;
+ 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;i<raw_name_len;i++) {
+ if(raw_name[i] == '/') {
+ break;
+ }
+ }
+ i++;
+ for(;i<raw_name_len;i++) {
+ if(raw_name[i] == '/') {
+ break;
+ }
+ }
+ i++;
+ for(;i<raw_name_len;i++) {
+ if(raw_name[i] == '-') {
+ break;
+ }
+ }
+ if(i == raw_name_len) return -1;
+ i++;
+ tmpptr = &raw_name[i];
+ for(;i<raw_name_len;i++) {
+ if(raw_name[i] == '.') {
+ raw_name[i] = ' ';
+ break;
+ }
+ }
+ *tid = strtoul(tmpptr, &endptr, 10);
+ if(endptr == tmpptr)
+ return -1; /* No digit */
+ if(*tid == ULONG_MAX)
+ return -1; /* underflow / overflow */
+ i++;
+ tmpptr = &raw_name[i];
+ for(;i<raw_name_len;i++) {
+ if(raw_name[i] == '.') {
+ raw_name[i] = ' ';
+ break;
+ }
+ }
+ *pgid = strtoul(tmpptr, &endptr, 10);
+ if(endptr == tmpptr)
+ return -1; /* No digit */
+ if(*pgid == ULONG_MAX)
+ return -1; /* underflow / overflow */
+ i++;
+ tmpptr = &raw_name[i];
+ *creation = strtoull(tmpptr, &endptr, 10);
+ if(endptr == tmpptr)
+ return -1; /* No digit */
+ if(*creation == G_MAXUINT64)
+ return -1; /* underflow / overflow */
+ } else {
+ underscore_pos = i;
- cpu_num = strtol(raw_name+underscore_pos+1, &endptr, 10);
+ cpu_num = strtol(raw_name+underscore_pos+1, &endptr, 10);
- if(endptr == raw_name+underscore_pos+1)
- return -1; /* No digit */
- if(cpu_num == LONG_MIN || cpu_num == LONG_MAX)
- return -1; /* underflow / overflow */
-
- strncpy(char_name, raw_name, underscore_pos);
-
- char_name[underscore_pos] = '\0';
+ if(endptr == raw_name+underscore_pos+1)
+ return -1; /* No digit */
+ if(cpu_num == LONG_MIN || cpu_num == LONG_MAX)
+ return -1; /* underflow / overflow */
+
+ strncpy(char_name, raw_name, underscore_pos);
+ char_name[underscore_pos] = '\0';
+
+ *name = g_quark_from_string(char_name);
+ *num = cpu_num;
+ }
- *name = g_quark_from_string(char_name);
- *num = cpu_num;
return 0;
}
if(ret < 0) continue;
} else if(S_ISREG(stat_buf.st_mode)) {
GQuark name;
- guint num;
+ guint num, tid, pgid;
+ guint64 creation;
GArray *group;
-
- if(get_tracefile_name_number(rel_path, &name, &num))
+ num = tid = pgid = 0;
+ creation = 0;
+ if(get_tracefile_name_number(rel_path, &name, &num, &tid, &pgid, &creation))
continue; /* invalid name */
g_debug("Opening file.\n");
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;
group = g_datalist_id_get_data(&trace->tracefiles, name);
if(group == NULL) {
-guint ltt_tracefile_num(LttTracefile *tf)
+guint ltt_tracefile_cpu(LttTracefile *tf)
{
return tf->cpu_num;
}
+guint ltt_tracefile_tid(LttTracefile *tf)
+{
+ return tf->tid;
+}
+
+guint ltt_tracefile_pgid(LttTracefile *tf)
+{
+ return tf->pgid;
+}
+
+guint64 ltt_tracefile_creation(LttTracefile *tf)
+{
+ return tf->creation;
+}
/*****************************************************************************
* Get the number of blocks in the tracefile
****************************************************************************/
return 1;
}
-/* Calculate the real event time based on the buffer boundaries */
-LttTime ltt_interpolate_time(LttTracefile *tf, LttEvent *event)
+LttTime ltt_interpolate_time_from_tsc(LttTracefile *tf, guint64 tsc)
{
LttTime time;
-
-// time = ltt_time_from_uint64(
-// cycles_2_ns(tf, (guint64)(tf->buffer.tsc - tf->buffer.begin.cycle_count)));
- time = ltt_time_from_uint64(
- (double)(tf->buffer.tsc - tf->trace->start_tsc)
- * (1000000000.0 / tf->trace->freq_scale)
- / (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);
-
+
+ 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);
+}
+
/* Get the current event of the tracefile : valid until the next read */
LttEvent *ltt_tracefile_get_event(LttTracefile *tf)
&header->begin.cycle_count);
tf->buffer.begin.freq = ltt_get_uint64(LTT_GET_BO(tf),
&header->begin.freq);
- tf->buffer.begin.timestamp = ltt_time_add(
+ 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);
+#if 0
+ 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
tf->buffer.end.timestamp = ltt_time_add(
&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;
+
tf->buffer.lost_size = ltt_get_uint32(LTT_GET_BO(tf),
&header->lost_size);
- tf->buffer.end.timestamp = ltt_time_add(
+ tf->buffer.end.timestamp = ltt_interpolate_time_from_tsc(tf,
+ tf->buffer.end.cycle_count);
+#if 0
+ 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);
-
+#endif //0
tf->buffer.tsc = tf->buffer.begin.cycle_count;
tf->event.tsc = tf->buffer.tsc;
tf->buffer.freq = tf->buffer.begin.freq;
g_warning("Time decreasing trace %s tracefile %s cpu %u position %u/0x%x",
g_quark_to_string(ltt_trace_name(ltt_tracefile_get_trace(tracefile))),
g_quark_to_string(ltt_tracefile_name(tracefile)),
- ltt_tracefile_num(tracefile), nb_block, offset);
+ tfs->cpu, nb_block, offset);
g_warning("last time %lu.%lu vs current %lu.%lu",
count_previous_time.tv_sec, count_previous_time.tv_nsec,
time.tv_sec, time.tv_nsec);
g_warning("test %s test", g_quark_to_string(ltt_tracefile_name(tracefile)));
g_string_printf(filename, "%s.%s.%u.trace", a_dump_tracefiles,
- mod_name, ltt_tracefile_num(tracefile));
+ mod_name, ltt_tracefile_cpu(tracefile));
fp = fopen(filename->str, "w");
if(fp == NULL) g_error("Cannot open %s", filename->str);
g_string_free(filename, TRUE);
g_warning("Time decreasing trace %s tracefile %s cpu %u position %u/0x%x",
g_quark_to_string(ltt_trace_name(ltt_tracefile_get_trace(tracefile))),
g_quark_to_string(ltt_tracefile_name(tracefile)),
- ltt_tracefile_num(tracefile), nb_block, offset);
+ ltt_tracefile_cpu(tracefile), nb_block, offset);
g_warning("last time %lu.%lu vs current %lu.%lu",
previous_time.tv_sec, previous_time.tv_nsec,
time.tv_sec, time.tv_nsec);
LttvProcessState* state;
- guint cpu = ltt_tracefile_num(context->tf);
LttvTraceState *ts = (LttvTraceState*)context->t_context;
+ LttvTracefileState *tfs = (LttvTracefileState*)context;
+ guint cpu = tfs->cpu;
state = ts->running_process[cpu];
/*
LttTime time;
- guint cpu = ltt_tracefile_num(tfs->parent.tf);
+ guint cpu = tfs->cpu;
LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
LttvProcessState *process = ts->running_process[cpu];
get_max_time(tcs);
nb_tracefile = tc->tracefiles->len;
-#if 0
+ tcs->processes = NULL;
+ tcs->running_process = g_new(LttvProcessState*,
+ ltt_trace_get_num_cpu(tc->t));
+ restore_init_state(tcs);
for(j = 0 ; j < nb_tracefile ; j++) {
tfcs =
LTTV_TRACEFILE_STATE(g_array_index(tc->tracefiles,
LttvTracefileContext*, j));
tfcs->tracefile_name = ltt_tracefile_name(tfcs->parent.tf);
+ tfcs->cpu = ltt_tracefile_cpu(tfcs->parent.tf);
+
+ if(ltt_tracefile_tid(tfcs->parent.tf) != 0) {
+ /* It's a Usertrace */
+ LttvProcessState *process;
+ LttTime timestamp =
+ ltt_interpolate_time_from_tsc(tfcs->parent.tf,
+ ltt_tracefile_creation(tfcs->parent.tf));
+ process = lttv_state_find_process_or_create(
+ tcs,
+ 0, ltt_tracefile_tid(tfcs->parent.tf),
+ ×tamp);
+ process->usertrace = tfcs;
+ }
}
-#endif //0
- tcs->processes = NULL;
- tcs->running_process = g_new(LttvProcessState*,
- ltt_trace_get_num_cpu(tc->t));
- restore_init_state(tcs);
}
}
{
LttvExecutionState *es;
- guint cpu = ltt_tracefile_num(tfs->parent.tf);
LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
+ guint cpu = tfs->cpu;
#ifdef HASH_TABLE_DEBUG
hash_table_check(ts->processes);
static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
{
- guint cpu = ltt_tracefile_num(tfs->parent.tf);
+ guint cpu = tfs->cpu;
LttvTraceState *ts = (LttvTraceState*)tfs->parent.t_context;
LttvProcessState *process = ts->running_process[cpu];
//process->last_cpu = tfs->cpu_name;
//process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
process->kernel_thread = 0;
+ process->usertrace = NULL;
g_info("Process %u, core %p", process->pid, process);
g_hash_table_insert(tcs->processes, process, process);
static gboolean schedchange(void *hook_data, void *call_data)
{
LttvTracefileState *s = (LttvTracefileState *)call_data;
- guint cpu = ltt_tracefile_num(s->parent.tf);
+ guint cpu = s->cpu;
LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
LttvProcessState *process = ts->running_process[cpu];
LttvProcessState *old_process = ts->running_process[cpu];
&s->parent.timestamp);
process->state->s = LTTV_STATE_RUN;
process->cpu = cpu;
+ if(process->usertrace)
+ process->usertrace->cpu = cpu;
// process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)s)->tf);
process->state->change = s->parent.timestamp;
return FALSE;
guint parent_pid;
guint child_pid;
LttvProcessState *zombie_process;
- guint cpu = ltt_tracefile_num(s->parent.tf);
+ guint cpu = s->cpu;
LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
LttvProcessState *process = ts->running_process[cpu];
LttvProcessState *child_process;
*
* Simply put a correct parent.
*/
- g_assert(0); /* This is a problematic case : the process has been created
- before the fork event */
+ //It can also happen when created by a usertrace. In that case, it's
+ //correct.
+ //g_assert(0); /* This is a problematic case : the process has been created
+ // before the fork event */
child_process->ppid = process->pid;
}
g_assert(child_process->name == LTTV_STATE_UNNAMED);
LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
guint pid;
- guint cpu = ltt_tracefile_num(s->parent.tf);
+ guint cpu = s->cpu;
LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
LttvProcessState *process;
LttvExecutionState *es;
LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
LttField *f;
guint pid;
- guint cpu = ltt_tracefile_num(s->parent.tf);
+ guint cpu = s->cpu;
LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
LttvProcessState *process = ts->running_process[cpu];
LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
//gchar *name;
- guint cpu = ltt_tracefile_num(s->parent.tf);
+ guint cpu = s->cpu;
LttvProcessState *process = ts->running_process[cpu];
/* PID of the process to release */
guint parent_pid;
guint pid;
gchar * command;
- guint cpu = ltt_tracefile_num(s->parent.tf);
+ guint cpu = s->cpu;
LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
LttvProcessState *process = ts->running_process[cpu];
LttvProcessState *parent_process;
return FALSE;
}
+guint lttv_state_current_cpu(LttvTracefileState *tfs)
+{
+ return tfs->cpu;
+}
+
+
+
#if 0
static gboolean block_start(void *hook_data, void *call_data)
{
LttvProcessStatus s;
} LttvExecutionState;
-
typedef struct _LttvProcessState {
guint pid;
guint ppid;
the active or inactive runqueue)*/
gboolean kernel_thread; /* Is this thread a kernel_thread ? */
// guint last_tracefile_index; /* index in the trace for cpu tracefile */
+ LttvTracefileState *usertrace; /* Associated usertrace */
/* opened file descriptors, address map?... */
} LttvProcessState;
//LttvProcessState *process;
GQuark tracefile_name;
+ guint cpu; /* Current cpu of the tracefile */
// guint saved_position;
};
static void update_event_tree(LttvTracefileStats *tfcs)
{
LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
- guint cpu = ltt_tracefile_num(tfcs->parent.parent.tf);
+ guint cpu = tfcs->parent.cpu;
LttvProcessState *process = ts->running_process[cpu];
LttvExecutionState *es = process->state;
static void mode_change(LttvTracefileStats *tfcs)
{
LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
- guint cpu = ltt_tracefile_num(tfcs->parent.parent.tf);
+ guint cpu = tfcs->parent.cpu;
LttvProcessState *process = ts->running_process[cpu];
LttvAttributeValue cpu_time;
static void mode_end(LttvTracefileStats *tfcs)
{
LttvTraceState *ts = (LttvTraceState *)tfcs->parent.parent.t_context;
- guint cpu = ltt_tracefile_num(tfcs->parent.parent.tf);
+ guint cpu = tfcs->parent.cpu;
LttvProcessState *process = ts->running_process[cpu];
LttvAttributeValue elapsed_time, cpu_time;
* draw items from the beginning of the read for it. If it is not
* present, it's a new process and it was not present : it will
* be added after the state update. */
- guint cpu = ltt_tracefile_num(tfc->tf);
+ guint cpu = tfs->cpu;
LttvProcessState *process = ts->running_process[cpu];
/* unknown state, bad current pid */
if(process->pid != pid_out)
process = lttv_state_find_process(ts,
- ltt_tracefile_num(tfc->tf), pid_out);
+ tfs->cpu, pid_out);
if(process != NULL) {
/* Well, the process_out existed : we must get it in the process hash
* be added after the state update. */
LttvProcessState *process;
process = lttv_state_find_process(ts,
- ltt_tracefile_num(tfc->tf), pid_in);
+ tfs->cpu, pid_in);
if(process != NULL) {
/* Well, the process existed : we must get it in the process hash
hashed_process_data = processlist_get_process_data(process_list,
pid_in,
- ltt_tracefile_num(tfc->tf),
+ tfs->cpu,
&birth,
tfc->t_context->index);
if(hashed_process_data == NULL)
processlist_add(process_list,
drawing,
pid_in,
- ltt_tracefile_num(tfc->tf),
+ tfs->cpu,
process->ppid,
&birth,
tfc->t_context->index,
/* Find process pid_in in the list... */
//process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
//process_in = tfs->process;
- guint cpu = ltt_tracefile_num(tfc->tf);
+ guint cpu = tfs->cpu;
process_in = ts->running_process[cpu];
/* It should exist, because we are after the state update. */
#ifdef EXTRA_CHECK
*/
/* For the pid */
//LttvProcessState *process = tfs->process;
- guint cpu = ltt_tracefile_num(tfc->tf);
+ guint cpu = tfs->cpu;
LttvProcessState *process = ts->running_process[cpu];
g_assert(process != NULL);
/* Add process to process list (if not present) */
//LttvProcessState *process = tfs->process;
- guint cpu = ltt_tracefile_num(tfc->tf);
+ guint cpu = tfs->cpu;
LttvProcessState *process = ts->running_process[cpu];
guint pid = process->pid;
LttTime birth;
/* Add process to process list (if not present) */
//LttvProcessState *process = tfs->process;
- guint cpu = ltt_tracefile_num(tfc->tf);
+ guint cpu = tfs->cpu;
LttvProcessState *process = ts->running_process[cpu];
/* It should exist, because we are after the state update. */
LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
- guint cpu = ltt_tracefile_num(tfc->tf);
+ guint cpu = tfs->cpu;
LttvProcessState *process = ts->running_process[cpu];
g_assert(process != NULL);
/* Find process pid_in in the list... */
process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
//process_in = tfs->process;
- //guint cpu = ltt_tracefile_num(tfc->tf);
+ //guint cpu = tfs->cpu;
//process_in = ts->running_process[cpu];
/* It should exist, because we are after the state update. */
#ifdef EXTRA_CHECK
for(i=0;i<tc->tracefiles->len;i++) {
tfc = g_array_index(tc->tracefiles, LttvTracefileContext*, i);
if(ltt_tracefile_name(tfc->tf) == LTT_NAME_CPU
- && ltt_tracefile_num(tfc->tf) == process_info->cpu)
+ && tfs->cpu == process_info->cpu)
break;
}
{
EventViewerData *event_viewer_data = (EventViewerData*)hook_data;
LttvTracefileContext *tfc = (LttvTracefileContext*)call_data;
+ LttvTracefileState *tfs = (LttvTracefileState*)call_data;
LttEvent *e = ltt_tracefile_get_event(tfc->tf);
LttvFilter *filter = event_viewer_data->main_win_filter;
LttEventType *event_type = ltt_event_eventtype(e);
LttTime time = ltt_event_time(e);
- guint cpu = ltt_tracefile_num(tfc->tf);
+ guint cpu = tfs->cpu;
LttvTraceState *ts = (LttvTraceState*)tfc->t_context;
LttvProcessState *process = ts->running_process[cpu];
LttvFilter *filter;
- guint cpu = ltt_tracefile_num(tfs->parent.tf);
+ guint cpu = tfs->cpu;
LttvTraceState *ts = (LttvTraceState*)tfc->t_context;
LttvProcessState *process = ts->running_process[cpu];