LTT_EVENT_SOFT_IRQ_EXIT,
LTT_EVENT_SCHEDCHANGE,
LTT_EVENT_FORK,
+ LTT_EVENT_KERNEL_THREAD,
LTT_EVENT_EXIT,
LTT_EVENT_FREE,
LTT_EVENT_EXEC,
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->name = name;
//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);
LttTime *timestamp)
{
LttvProcessState *process = lttv_state_find_process(ts, cpu, pid);
+ LttvExecutionState *es;
/* Put ltt_time_zero creation time for unexisting processes */
- if(unlikely(process == NULL)) process = lttv_state_create_process(ts,
+ if(unlikely(process == NULL)) {
+ process = lttv_state_create_process(ts,
NULL, cpu, pid, LTTV_STATE_UNNAMED, timestamp);
+ /* We are not sure is it's a kernel thread or normal thread, put the
+ * bottom stack state to unknown */
+ es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
+ es->t = LTTV_STATE_MODE_UNKNOWN;
+ }
return 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];
LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
the wrongly attributed statistics. */
//This test only makes sense once the state is known and if there is no
- //missing events.
+ //missing events. We need to silently ignore schedchange coming after a
+ //process_free, or it causes glitches. (FIXME)
//if(unlikely(process->pid != pid_out)) {
// g_assert(process->pid == 0);
//}
else process->state->s = LTTV_STATE_WAIT;
process->state->change = s->parent.timestamp;
}
-
- if(state_out == 32)
+
+ if(state_out == 32)
exit_process(s, process); /* EXIT_DEAD */
/* see sched.h for states */
}
&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);
return FALSE;
}
+/* We stamp a newly created process as kernel_thread */
+static gboolean process_kernel_thread(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+ LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
+ LttvTraceHookByFacility *thf = (LttvTraceHookByFacility *)hook_data;
+ guint pid;
+ guint cpu = s->cpu;
+ LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
+ LttvProcessState *process;
+ LttvExecutionState *es;
+
+ /* PID */
+ pid = ltt_event_get_unsigned(e, thf->f1);
+
+ process = lttv_state_find_process(ts, ANY_CPU, pid);
+ es = &g_array_index(process->execution_stack, LttvExecutionState, 0);
+ es->t = LTTV_STATE_SYSCALL;
+ process->kernel_thread = 1;
+
+ return FALSE;
+}
static gboolean process_exit(void *hook_data, void *call_data)
{
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];
break;
}
}
- if(i == num_cpus) /* process is not scheduled */
- exit_process(s, process);
+ //if(i == num_cpus) /* process is not scheduled */
+ //exit_process(s, process); // do nothing : wait for the schedchange to
+ //delete the process.
}
return FALSE;
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;
/* Find the eventtype id for the following events and register the
associated by id hooks. */
- hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 14);
- hooks = g_array_set_size(hooks, 14);
+ hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 15);
+ hooks = g_array_set_size(hooks, 15);
ret = lttv_trace_find_hook(ts->parent.t,
LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_SYSCALL_ENTRY,
process_fork, NULL, &g_array_index(hooks, LttvTraceHook, 9));
g_assert(!ret);
+ ret = lttv_trace_find_hook(ts->parent.t,
+ LTT_FACILITY_PROCESS, LTT_EVENT_KERNEL_THREAD,
+ LTT_FIELD_PID, 0, 0,
+ process_kernel_thread, NULL, &g_array_index(hooks, LttvTraceHook, 10));
+ g_assert(!ret);
+
ret = lttv_trace_find_hook(ts->parent.t,
LTT_FACILITY_PROCESS, LTT_EVENT_EXIT,
LTT_FIELD_PID, 0, 0,
- process_exit, NULL, &g_array_index(hooks, LttvTraceHook, 10));
+ process_exit, NULL, &g_array_index(hooks, LttvTraceHook, 11));
g_assert(!ret);
ret = lttv_trace_find_hook(ts->parent.t,
LTT_FACILITY_PROCESS, LTT_EVENT_FREE,
LTT_FIELD_PID, 0, 0,
- process_free, NULL, &g_array_index(hooks, LttvTraceHook, 11));
+ process_free, NULL, &g_array_index(hooks, LttvTraceHook, 12));
g_assert(!ret);
ret = lttv_trace_find_hook(ts->parent.t,
LTT_FACILITY_FS, LTT_EVENT_EXEC,
LTT_FIELD_FILENAME, 0, 0,
- process_exec, NULL, &g_array_index(hooks, LttvTraceHook, 12));
+ process_exec, NULL, &g_array_index(hooks, LttvTraceHook, 13));
g_assert(!ret);
/* statedump-related hooks */
ret = lttv_trace_find_hook(ts->parent.t,
LTT_FACILITY_STATEDUMP, LTT_EVENT_ENUM_PROCESS_STATE,
LTT_FIELD_PID, LTT_FIELD_PARENT_PID, LTT_FIELD_NAME,
- enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, 13));
+ enum_process_state, NULL, &g_array_index(hooks, LttvTraceHook, 14));
g_assert(!ret);
}
}
}
- lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
+ lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
*(val.v_pointer) = hooks;
}
}
nb_trace = lttv_traceset_number(traceset);
for(i = 0 ; i < nb_trace ; i++) {
ts = LTTV_TRACE_STATE(self->parent.traces[i]);
- lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
+ lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
hooks = *(val.v_pointer);
/* Remove these hooks from each event_by_id hooks list */
return FALSE;
}
+guint lttv_state_current_cpu(LttvTracefileState *tfs)
+{
+ return tfs->cpu;
+}
+
+
+
#if 0
static gboolean block_start(void *hook_data, void *call_data)
{
LTT_EVENT_SOFT_IRQ_EXIT = g_quark_from_string("soft_irq_exit");
LTT_EVENT_SCHEDCHANGE = g_quark_from_string("schedchange");
LTT_EVENT_FORK = g_quark_from_string("fork");
+ LTT_EVENT_KERNEL_THREAD = g_quark_from_string("kernel_thread");
LTT_EVENT_EXIT = g_quark_from_string("exit");
LTT_EVENT_FREE = g_quark_from_string("free");
LTT_EVENT_EXEC = g_quark_from_string("exec");