process = (LttvProcessState *)value;
fprintf(fp,
-" <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\">\n",
+" <PROCESS CORE=%p PID=%u TGID=%u PPID=%u TYPE=\"%s\" CTIME_S=%lu CTIME_NS=%lu ITIME_S=%lu ITIME_NS=%lu NAME=\"%s\" BRAND=\"%s\" CPU=\"%u\" FREE_EVENTS=\"%u\">\n",
process, process->pid, process->tgid, process->ppid,
g_quark_to_string(process->type),
process->creation_time.tv_sec,
process->insertion_time.tv_nsec,
g_quark_to_string(process->name),
g_quark_to_string(process->brand),
- process->cpu);
+ process->cpu, process->free_events);
for(i = 0 ; i < process->execution_stack->len; i++) {
es = &g_array_index(process->execution_stack, LttvExecutionState, i);
//fputc('\0', fp);
fwrite(&process->brand, sizeof(process->brand), 1, fp);
fwrite(&process->pid, sizeof(process->pid), 1, fp);
+ fwrite(&process->free_events, sizeof(process->free_events), 1, fp);
fwrite(&process->tgid, sizeof(process->tgid), 1, fp);
fwrite(&process->ppid, sizeof(process->ppid), 1, fp);
fwrite(&process->cpu, sizeof(process->cpu), 1, fp);
fread(&tmp.name, sizeof(tmp.name), 1, fp);
fread(&tmp.brand, sizeof(tmp.brand), 1, fp);
fread(&tmp.pid, sizeof(tmp.pid), 1, fp);
+ fread(&tmp.free_events, sizeof(tmp.free_events), 1, fp);
fread(&tmp.tgid, sizeof(tmp.tgid), 1, fp);
fread(&tmp.ppid, sizeof(tmp.ppid), 1, fp);
fread(&tmp.cpu, sizeof(tmp.cpu), 1, fp);
(gchar*)g_ptr_array_index(quarktable, tmp.brand));
process->name =
g_quark_from_string((gchar*)g_ptr_array_index(quarktable, tmp.name));
-
+ process->free_events = tmp.free_events;
do {
if(feof(fp) || ferror(fp)) goto end_loop;
process->creation_time.tv_nsec);
process->pid_time = g_quark_from_string(buffer);
process->cpu = cpu;
+ process->free_events = 0;
//process->last_cpu = tfs->cpu_name;
//process->last_cpu_index = ltt_tracefile_num(((LttvTracefileContext*)tfs)->tf);
process->execution_stack = g_array_sized_new(FALSE, FALSE,
* has the flag SA_NOCLDWAIT. It can also happen when the child is part
* of a killed thread group, but isn't the leader.
*/
-static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
+static int exit_process(LttvTracefileState *tfs, LttvProcessState *process)
{
LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context);
LttvProcessState key;
+ /* Wait for both schedule with exit dead and process free to happen.
+ * They can happen in any order. */
+ if (++(process->free_events) < 2)
+ return 0;
+
key.pid = process->pid;
key.cpu = process->cpu;
g_hash_table_remove(ts->processes, &key);
g_array_free(process->execution_stack, TRUE);
g_array_free(process->user_stack, TRUE);
g_free(process);
+ return 1;
}
process->state->change = s->parent.timestamp;
}
- if(state_out == 32 || state_out == 64)
- exit_process(s, process); /* EXIT_DEAD || TASK_DEAD */
- /* see sched.h for states */
+ if(state_out == 32 || state_out == 64) { /* EXIT_DEAD || TASK_DEAD */
+ /* see sched.h for states */
+ if (!exit_process(s, process)) {
+ process->state->s = LTTV_STATE_DEAD;
+ process->state->change = s->parent.timestamp;
+ }
+ }
}
}
process = ts->running_process[cpu] =
process = lttv_state_find_process_or_create(ts, ANY_CPU, pid,
<t_time_zero);
- process->execution_stack =
- g_array_set_size(process->execution_stack, 1);
- es = process->state =
- &g_array_index(process->execution_stack, LttvExecutionState, 0);
- es->t = LTTV_STATE_SYSCALL;
+ if (process->state->s != LTTV_STATE_DEAD) {
+ process->execution_stack =
+ g_array_set_size(process->execution_stack, 1);
+ es = process->state =
+ &g_array_index(process->execution_stack, LttvExecutionState, 0);
+ es->t = LTTV_STATE_SYSCALL;
+ }
process->type = LTTV_STATE_KERNEL_THREAD;
return FALSE;
g_assert(release_pid != 0);
process = lttv_state_find_process(ts, ANY_CPU, release_pid);
-
+ if(likely(process != NULL))
+ exit_process(s, process);
+ return FALSE;
+//DISABLED
if(likely(process != NULL)) {
/* release_task is happening at kernel level : we can now safely release
* the data structure of the process */
guint64 current_function;
LttvProcessType type; /* kernel thread or user space ? */
guint target_pid; /* target PID of the current event. */
+ guint free_events; /* 0 : none, 1 : free or exit dead, 2 : should delete */
} LttvProcessState;
#define ANY_CPU 0 /* For clarity sake : a call to lttv_state_find_process for
{ 0, 0x6400, 0x0000, 0x5D00 }, /* COL_ZOMBIE : dark purple */
{ 0, 0x0700, 0x6400, 0x0000 }, /* COL_WAIT_FORK : dark green */
{ 0, 0x8900, 0x0000, 0x8400 }, /* COL_EXIT : "less dark" magenta */
+ { 0, 0x0000, 0x0000, 0x0000 }, /* COL_DEAD : black */
{ 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_MODE_UNKNOWN : white */
{ 0, 0xFFFF, 0xFFFF, 0xFFFF } /* COL_UNNAMED : white */
COL_ZOMBIE, /* dark purple */
COL_WAIT_FORK, /* dark green */
COL_EXIT, /* "less dark" magenta */
+ COL_DEAD, /* black */
COL_MODE_UNKNOWN, /* white */
COL_UNNAMED, /* white */
NUM_COLORS } draw_color;
prop_line.color = drawing_colors[COL_EXIT];
} else if(process->state->s == LTTV_STATE_UNNAMED) {
prop_line.color = drawing_colors[COL_UNNAMED];
+ } else if(process->state->s == LTTV_STATE_DEAD) {
+ prop_line.color = drawing_colors[COL_DEAD];
} else {
g_critical("unknown state : %s", g_quark_to_string(process->state->s));
g_assert(FALSE); /* UNKNOWN STATE */
guint pid_out;
guint pid_in;
+ guint state_out;
{
pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
+ state_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 2));
}
tfc->target_pid = pid_out;
e = ltt_tracefile_get_event(tfc->tf);
LttvFilter *filter = control_flow_data->filter;
- if(filter != NULL && filter->head != NULL)
- if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
- tfc->t_context->t,tfc,NULL,NULL))
- return FALSE;
-
LttTime evtime = ltt_event_time(e);
/* Add process to process list (if not present) */
pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
}
-
- /* Find process pid_in in the list... */
- //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
- //process_in = tfs->process;
- guint cpu = tfs->cpu;
- guint trace_num = ts->parent.index;
- process_in = ts->running_process[cpu];
- /* It should exist, because we are after the state update. */
+ tfc->target_pid = pid_in;
+ if(!filter || !filter->head ||
+ lttv_filter_tree_parse(filter->head,e,tfc->tf,
+ tfc->t_context->t,tfc,NULL,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 = tfs->cpu;
+ guint trace_num = ts->parent.index;
+ process_in = ts->running_process[cpu];
+ /* It should exist, because we are after the state update. */
#ifdef EXTRA_CHECK
- g_assert(process_in != NULL);
+ g_assert(process_in != NULL);
#endif //EXTRA_CHECK
- birth = process_in->creation_time;
-
- hashed_process_data_in = processlist_get_process_data(process_list,
+ birth = process_in->creation_time;
+
+ hashed_process_data_in = processlist_get_process_data(process_list,
+ pid_in,
+ process_in->cpu,
+ &birth,
+ trace_num);
+ if(hashed_process_data_in == NULL)
+ {
+ g_assert(pid_in == 0 || pid_in != process_in->ppid);
+ ProcessInfo *process_info;
+ Drawing_t *drawing = control_flow_data->drawing;
+ /* Process not present */
+ processlist_add(process_list,
+ drawing,
pid_in,
+ process_in->tgid,
process_in->cpu,
+ process_in->ppid,
&birth,
- trace_num);
- if(hashed_process_data_in == NULL)
- {
- g_assert(pid_in == 0 || pid_in != process_in->ppid);
- ProcessInfo *process_info;
- Drawing_t *drawing = control_flow_data->drawing;
- /* Process not present */
- processlist_add(process_list,
- drawing,
- pid_in,
- process_in->tgid,
- process_in->cpu,
- process_in->ppid,
- &birth,
- trace_num,
- process_in->name,
- process_in->brand,
- &pl_height,
- &process_info,
- &hashed_process_data_in);
- gtk_widget_set_size_request(drawing->drawing_area,
- -1,
- pl_height);
- gtk_widget_queue_draw(drawing->drawing_area);
- }
- /* Set the current process */
- process_list->current_hash_data[trace_num][process_in->cpu] =
- hashed_process_data_in;
-
- if(ltt_time_compare(hashed_process_data_in->next_good_time,
- evtime) <= 0)
- {
- TimeWindow time_window =
- lttvwindow_get_time_window(control_flow_data->tab);
-
+ trace_num,
+ process_in->name,
+ process_in->brand,
+ &pl_height,
+ &process_info,
+ &hashed_process_data_in);
+ gtk_widget_set_size_request(drawing->drawing_area,
+ -1,
+ pl_height);
+ gtk_widget_queue_draw(drawing->drawing_area);
+ }
+ /* Set the current process */
+ process_list->current_hash_data[trace_num][process_in->cpu] =
+ hashed_process_data_in;
+
+ if(ltt_time_compare(hashed_process_data_in->next_good_time,
+ evtime) <= 0)
+ {
+ TimeWindow time_window =
+ lttvwindow_get_time_window(control_flow_data->tab);
+
#ifdef EXTRA_CHECK
- if(ltt_time_compare(evtime, time_window.start_time) == -1
- || ltt_time_compare(evtime, time_window.end_time) == 1)
- return FALSE;
+ if(ltt_time_compare(evtime, time_window.start_time) == -1
+ || ltt_time_compare(evtime, time_window.end_time) == 1)
+ return FALSE;
#endif //EXTRA_CHECK
- Drawing_t *drawing = control_flow_data->drawing;
- guint width = drawing->width;
- guint new_x;
-
- convert_time_to_pixels(
- time_window,
- evtime,
- width,
- &new_x);
-
- if(hashed_process_data_in->x.middle != new_x) {
- hashed_process_data_in->x.middle = new_x;
- hashed_process_data_in->x.middle_used = FALSE;
- hashed_process_data_in->x.middle_marked = FALSE;
+ Drawing_t *drawing = control_flow_data->drawing;
+ guint width = drawing->width;
+ guint new_x;
+
+ convert_time_to_pixels(
+ time_window,
+ evtime,
+ width,
+ &new_x);
+
+ if(hashed_process_data_in->x.middle != new_x) {
+ hashed_process_data_in->x.middle = new_x;
+ hashed_process_data_in->x.middle_used = FALSE;
+ hashed_process_data_in->x.middle_marked = FALSE;
+ }
}
}
+
return 0;
}