From 7df20ca43b06343b299d2a79512a44441f148f1d Mon Sep 17 00:00:00 2001 From: compudj Date: Sat, 9 Sep 2006 00:57:58 +0000 Subject: [PATCH] precomputed states almost ok, needs testing git-svn-id: http://ltt.polymtl.ca/svn@2088 04897980-b3bd-0310-b5e0-8ef037075253 --- ltt/branches/poly/lttv/lttv/state.c | 182 ++++++++++++++---- ltt/branches/poly/lttv/lttv/state.h | 1 + .../lttv/modules/gui/controlflow/eventhooks.c | 7 +- .../lttv/modules/gui/detailedevents/events.c | 7 +- .../modules/gui/histogram/histoeventhooks.c | 5 +- .../lttvwindow/lttvwindow/lttvwindowtraces.c | 1 - .../poly/lttv/modules/text/precomputeState.c | 5 +- 7 files changed, 166 insertions(+), 42 deletions(-) diff --git a/ltt/branches/poly/lttv/lttv/state.c b/ltt/branches/poly/lttv/lttv/state.c index 7770e9ab..914ab728 100644 --- a/ltt/branches/poly/lttv/lttv/state.c +++ b/ltt/branches/poly/lttv/lttv/state.c @@ -30,6 +30,16 @@ #include #include +/* Comment : + * Mathieu Desnoyers + * usertrace is there only to be able to update the current CPU of the + * usertraces when there is a schedchange. it is a way to link the ProcessState + * to the associated usertrace. Link only created upon thread creation. + * + * The cpu id is necessary : it gives us back the current ProcessState when we + * are considering data from the usertrace. + */ + #define PREALLOCATED_EXECUTION_STACK 10 /* Facilities Quarks */ @@ -143,6 +153,8 @@ static void free_saved_state(LttvTraceState *tcs); static void lttv_state_free_process_table(GHashTable *processes); +static void lttv_trace_states_read_raw(LttvTraceState *tcs, FILE *fp, + GPtrArray *quarktable); void lttv_state_save(LttvTraceState *self, LttvAttribute *container) { @@ -280,6 +292,82 @@ static void free_usertrace_key(gpointer data) g_free(data); } +#define MAX_STRING_LEN 4096 + +static void +state_load_saved_states(LttvTraceState *tcs) +{ + FILE *fp; + GPtrArray *quarktable; + char *trace_path; + char path[PATH_MAX]; + guint count; + guint i; + tcs->has_precomputed_states = FALSE; + GQuark q; + gchar *string; + gint hdr; + gchar buf[MAX_STRING_LEN]; + guint len; + + trace_path = g_quark_to_string(ltt_trace_name(tcs->parent.t)); + strncpy(path, trace_path, PATH_MAX-1); + count = strnlen(trace_path, PATH_MAX-1); + // quarktable : open, test + strncat(path, "/precomputed/quarktable", PATH_MAX-count-1); + fp = fopen(path, "r"); + if(!fp) return; + quarktable = g_ptr_array_sized_new(4096); + + /* Index 0 is null */ + hdr = fgetc(fp); + if(hdr == EOF) return; + g_assert(hdr == HDR_QUARKS); + q = 1; + do { + hdr = fgetc(fp); + if(hdr == EOF) break; + g_assert(hdr == HDR_QUARK); + g_ptr_array_set_size(quarktable, q+1); + i=0; + while(1) { + fread(&buf[i], sizeof(gchar), 1, fp); + if(buf[i] == '\0' || feof(fp)) break; + i++; + } + len = strnlen(buf, MAX_STRING_LEN-1); + g_ptr_array_index (quarktable, q) = g_new(gchar, len+1); + strncpy(g_ptr_array_index (quarktable, q), buf, len+1); + q++; + } while(1); + + fclose(fp); + // saved_states : open, test + strncpy(path, trace_path, PATH_MAX-1); + count = strnlen(trace_path, PATH_MAX-1); + strncat(path, "/precomputed/states", PATH_MAX-count-1); + fp = fopen(path, "r"); + if(!fp) return; + + hdr = fgetc(fp); + if(hdr != HDR_TRACE) goto end; + + lttv_trace_states_read_raw(tcs, fp, quarktable); + + tcs->has_precomputed_states = TRUE; + +end: + fclose(fp); + + /* Free the quarktable */ + for(i=0; ilen; i++) { + string = g_ptr_array_index (quarktable, i); + g_free(string); + } + g_ptr_array_free(quarktable, TRUE); + return; +} + static void init(LttvTracesetState *self, LttvTraceset *ts) { @@ -324,21 +412,6 @@ init(LttvTracesetState *self, LttvTraceset *ts) LttvTracefileContext*, j)); tfcs->tracefile_name = ltt_tracefile_name(tfcs->parent.tf); tfcs->cpu = ltt_tracefile_cpu(tfcs->parent.tf); -#if 0 - 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 if(ltt_tracefile_tid(tfcs->parent.tf) != 0) { /* It's a Usertrace */ guint tid = ltt_tracefile_tid(tfcs->parent.tf); @@ -357,6 +430,8 @@ init(LttvTracesetState *self, LttvTraceset *ts) } } + /* See if the trace has saved states */ + state_load_saved_states(tcs); } } @@ -579,6 +654,7 @@ static void write_process_state_raw(gpointer key, gpointer value, fwrite(&es->s, sizeof(es->s), 1, fp); fwrite(&es->entry, sizeof(es->entry), 1, fp); fwrite(&es->change, sizeof(es->change), 1, fp); + fwrite(&es->cum_cpu_time, sizeof(es->cum_cpu_time), 1, fp); #if 0 fprintf(fp, " t), g_quark_to_string(es->n), @@ -677,17 +753,19 @@ void lttv_state_write_raw(LttvTraceState *self, LttTime t, FILE *fp) /* Read process state from a file */ /* Called because a HDR_PROCESS was found */ -static void read_process_state_raw(LttvTraceState *self, FILE *fp) +static void read_process_state_raw(LttvTraceState *self, FILE *fp, + GPtrArray *quarktable) { LttvExecutionState *es; LttvProcessState *process, *parent_process; LttvProcessState tmp; + GQuark tmpq; guint i; - guint64 address; + guint64 *address; guint cpu; - /* TOOD : check return value */ + /* TODO : check return value */ fread(&tmp.type, sizeof(tmp.type), 1, fp); fread(&tmp.name, sizeof(tmp.name), 1, fp); fread(&tmp.brand, sizeof(tmp.brand), 1, fp); @@ -704,28 +782,58 @@ static void read_process_state_raw(LttvTraceState *self, FILE *fp) /* We must link to the parent */ parent_process = lttv_state_find_process_or_create(self, ANY_CPU, tmp.ppid, <t_time_zero); - process = lttv_state_find_process_or_create(self, ANY_CPU, tmp.pid, - &tmp.insertion_time); + process = lttv_state_find_process_or_create(self, tmp.cpu, tmp.pid, + &tmp.creation_time); } + process->insertion_time = tmp.insertion_time; process->creation_time = tmp.creation_time; - process->type = tmp.type; - process->brand = tmp.brand; + process->type = g_quark_from_string( + (gchar*)g_ptr_array_index(quarktable, tmp.type)); process->tgid = tmp.tgid; - process->cpu = tmp.cpu; + process->ppid = tmp.ppid; + process->brand = g_quark_from_string( + (gchar*)g_ptr_array_index(quarktable, tmp.brand)); + process->name = + g_quark_from_string((gchar*)g_ptr_array_index(quarktable, tmp.name)); do { if(feof(fp) || ferror(fp)) goto end_loop; gint hdr = fgetc(fp); + if(hdr == EOF) goto end_loop; switch(hdr) { case HDR_ES: + process->execution_stack = + g_array_set_size(process->execution_stack, + process->execution_stack->len + 1); + es = &g_array_index(process->execution_stack, LttvExecutionState, + process->execution_stack->len-1); + + fread(&es->t, sizeof(es->t), 1, fp); + es->t = g_quark_from_string( + (gchar*)g_ptr_array_index(quarktable, es->t)); + fread(&es->n, sizeof(es->n), 1, fp); + es->n = g_quark_from_string( + (gchar*)g_ptr_array_index(quarktable, es->n)); + fread(&es->s, sizeof(es->s), 1, fp); + es->s = g_quark_from_string( + (gchar*)g_ptr_array_index(quarktable, es->s)); + fread(&es->entry, sizeof(es->entry), 1, fp); + fread(&es->change, sizeof(es->change), 1, fp); + fread(&es->cum_cpu_time, sizeof(es->cum_cpu_time), 1, fp); break; case HDR_USER_STACK: + process->user_stack = g_array_set_size(process->user_stack, + process->user_stack->len + 1); + address = &g_array_index(process->user_stack, guint64, + process->user_stack->len-1); + fread(address, sizeof(address), 1, fp); + process->current_function = *address; break; case HDR_USERTRACE: - break; - case HDR_PROCESS_STATE: + fread(&tmpq, sizeof(tmpq), 1, fp); + fread(&process->usertrace->cpu, sizeof(process->usertrace->cpu), 1, fp); break; default: ungetc(hdr, fp); @@ -739,11 +847,10 @@ end_loop: /* Called because a HDR_PROCESS_STATE was found */ /* Append a saved state to the trace states */ -void lttv_state_read_raw(LttvTraceState *self, FILE *fp) +void lttv_state_read_raw(LttvTraceState *self, FILE *fp, GPtrArray *quarktable) { guint i, nb_tracefile, nb_block, offset; guint64 tsc; - LttTracefile *tf; LttvTracefileState *tfcs; LttEventPosition *ep; @@ -766,11 +873,12 @@ void lttv_state_read_raw(LttvTraceState *self, FILE *fp) do { if(feof(fp) || ferror(fp)) goto end_loop; hdr = fgetc(fp); + if(hdr == EOF) goto end_loop; switch(hdr) { case HDR_PROCESS: /* Call read_process_state_raw */ - read_process_state_raw(self, fp); + read_process_state_raw(self, fp, quarktable); break; case HDR_TRACEFILE: case HDR_TRACESET: @@ -782,9 +890,8 @@ void lttv_state_read_raw(LttvTraceState *self, FILE *fp) case HDR_USERTRACE: case HDR_PROCESS_STATE: case HDR_CPU: - g_error("Error while parsing saved state file :" - " unexpected data header %d", - hdr); + ungetc(hdr, fp); + goto end_loop; break; default: g_error("Error while parsing saved state file : unknown data header %d", @@ -822,7 +929,7 @@ end_loop: fread(&nb_block, sizeof(nb_block), 1, fp); fread(&offset, sizeof(offset), 1, fp); fread(&tsc, sizeof(tsc), 1, fp); - ltt_event_position_set(ep, tf, nb_block, offset, tsc); + ltt_event_position_set(ep, tfcs->parent.tf, nb_block, offset, tsc); gint ret = ltt_tracefile_seek_position(tfcs->parent.tf, ep); g_assert(ret == 0); } @@ -845,18 +952,20 @@ end_loop: } /* Called when a HDR_TRACE is found */ -void lttv_trace_states_read_raw(LttvTraceState *tcs, FILE *fp) +void lttv_trace_states_read_raw(LttvTraceState *tcs, FILE *fp, + GPtrArray *quarktable) { int hdr; do { if(feof(fp) || ferror(fp)) goto end_loop; hdr = fgetc(fp); + if(hdr == EOF) goto end_loop; switch(hdr) { case HDR_PROCESS_STATE: /* Call read_process_state_raw */ - lttv_state_read_raw(tcs, fp); + lttv_state_read_raw(tcs, fp, quarktable); break; case HDR_TRACEFILE: case HDR_TRACESET: @@ -2368,6 +2477,8 @@ void lttv_state_add_event_hooks(LttvTracesetState *self) for(i = 0 ; i < nb_trace ; i++) { ts = (LttvTraceState *)self->parent.traces[i]; + if(ts->has_precomputed_states) continue; + /* Find the eventtype id for the following events and register the associated by id hooks. */ @@ -2543,6 +2654,9 @@ void lttv_state_remove_event_hooks(LttvTracesetState *self) nb_trace = lttv_traceset_number(traceset); for(i = 0 ; i < nb_trace ; i++) { ts = LTTV_TRACE_STATE(self->parent.traces[i]); + + if(ts->has_precomputed_states) continue; + lttv_attribute_find(ts->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); hooks = *(val.v_pointer); diff --git a/ltt/branches/poly/lttv/lttv/state.h b/ltt/branches/poly/lttv/lttv/state.h index f0313848..1c20095f 100644 --- a/ltt/branches/poly/lttv/lttv/state.h +++ b/ltt/branches/poly/lttv/lttv/state.h @@ -295,6 +295,7 @@ struct _LttvTraceState { /* Array of per cpu running process */ LttvProcessState **running_process; + gboolean has_precomputed_states; }; struct _LttvTraceStateClass { diff --git a/ltt/branches/poly/lttv/modules/gui/controlflow/eventhooks.c b/ltt/branches/poly/lttv/modules/gui/controlflow/eventhooks.c index cac372ca..65f47eec 100644 --- a/ltt/branches/poly/lttv/modules/gui/controlflow/eventhooks.c +++ b/ltt/branches/poly/lttv/modules/gui/controlflow/eventhooks.c @@ -122,6 +122,7 @@ static void request_background_data(ControlFlowData *control_flow_data) gint num_traces = lttv_traceset_number(tsc->ts); gint i; LttvTrace *trace; + LttvTraceState *tstate; LttvHooks *background_ready_hook = lttv_hooks_new(); @@ -131,8 +132,10 @@ static void request_background_data(ControlFlowData *control_flow_data) for(i=0;its, i); + tstate = LTTV_TRACE_STATE(tsc->traces[i]); - if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE) { + if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE + && !tstate->has_precomputed_states) { if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"), trace) == FALSE) { @@ -159,7 +162,7 @@ static void request_background_data(ControlFlowData *control_flow_data) control_flow_data->background_info_waiting++; } } else { - /* Data ready. Be its nature, this viewer doesn't need to have + /* Data ready. By its nature, this viewer doesn't need to have * its data ready hook called there, because a background * request is always linked with a redraw. */ diff --git a/ltt/branches/poly/lttv/modules/gui/detailedevents/events.c b/ltt/branches/poly/lttv/modules/gui/detailedevents/events.c index 41d72ae8..dcd2cf99 100644 --- a/ltt/branches/poly/lttv/modules/gui/detailedevents/events.c +++ b/ltt/branches/poly/lttv/modules/gui/detailedevents/events.c @@ -556,6 +556,7 @@ static void request_background_data(EventViewerData *event_viewer_data) gint num_traces = lttv_traceset_number(tsc->ts); gint i; LttvTrace *trace; + LttvTraceState *tstate; LttvHooks *background_ready_hook = lttv_hooks_new(); @@ -565,8 +566,10 @@ static void request_background_data(EventViewerData *event_viewer_data) for(i=0;its, i); + tstate = LTTV_TRACE_STATE(tsc->traces[i]); - if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE) { + if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE + && !tstate->has_precomputed_states) { if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"), trace) == FALSE) { @@ -593,7 +596,7 @@ static void request_background_data(EventViewerData *event_viewer_data) event_viewer_data->background_info_waiting++; } } else { - /* Data ready. Be its nature, this viewer doesn't need to have + /* Data ready. By its nature, this viewer doesn't need to have * its data ready hook called htere, because a background * request is always linked with a redraw. */ diff --git a/ltt/branches/poly/lttv/modules/gui/histogram/histoeventhooks.c b/ltt/branches/poly/lttv/modules/gui/histogram/histoeventhooks.c index 96382c87..b315a3a4 100644 --- a/ltt/branches/poly/lttv/modules/gui/histogram/histoeventhooks.c +++ b/ltt/branches/poly/lttv/modules/gui/histogram/histoeventhooks.c @@ -121,6 +121,7 @@ static void histo_request_background_data(HistoControlFlowData *histocontrol_flo gint num_traces = lttv_traceset_number(tsc->ts); gint i; LttvTrace *trace; + LttvTraceState *tstate; LttvHooks *histo_background_ready_hook = lttv_hooks_new(); @@ -130,8 +131,10 @@ static void histo_request_background_data(HistoControlFlowData *histocontrol_flo for(i=0;its, i); + tstate = LTTV_TRACE_STATE(tsc->traces[i]); - if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE) { + if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE + && !tstate->has_precomputed_states) { if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"), trace) == FALSE) { diff --git a/ltt/branches/poly/lttv/modules/gui/lttvwindow/lttvwindow/lttvwindowtraces.c b/ltt/branches/poly/lttv/modules/gui/lttvwindow/lttvwindow/lttvwindowtraces.c index f83c1f1e..26cf0f3b 100644 --- a/ltt/branches/poly/lttv/modules/gui/lttvwindow/lttvwindow/lttvwindowtraces.c +++ b/ltt/branches/poly/lttv/modules/gui/lttvwindow/lttvwindow/lttvwindowtraces.c @@ -211,7 +211,6 @@ void lttvwindowtraces_add_trace(LttvTrace *trace) value = lttv_attribute_add(attribute, LTTV_NOTIFY_CURRENT, LTTV_POINTER); - } /* Remove a trace from the global attributes */ diff --git a/ltt/branches/poly/lttv/modules/text/precomputeState.c b/ltt/branches/poly/lttv/modules/text/precomputeState.c index f9c2f31e..6853d445 100644 --- a/ltt/branches/poly/lttv/modules/text/precomputeState.c +++ b/ltt/branches/poly/lttv/modules/text/precomputeState.c @@ -80,7 +80,8 @@ static gboolean write_traceset_header(void *hook_data, void *call_data) /* Print the trace set header */ if(a_raw) { /* TODO : Write a header that will check for ILP size and endianness */ - fputc(HDR_TRACESET, a_file); + //fputc(HDR_TRACESET, a_file); + g_assert(lttv_traceset_number(tc->ts) == 1); /* Only one trace in traceset */ } else { fprintf(a_file,"\n", lttv_traceset_number(tc->ts)); @@ -276,6 +277,6 @@ static void destroy() LTTV_MODULE("precomputeState", "Precompute states", \ - "Precompute states in a trace, XML output.", \ + "Precompute states in a trace, XML or binary output.", \ init, destroy, "stats", "batchAnalysis", "option", "print") -- 2.34.1