From: compudj Date: Tue, 30 Aug 2005 16:19:39 +0000 (+0000) Subject: seek n forward and backward implemented in trace context X-Git-Tag: v0.12.20~2399 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=0bd2f89c122b8ead4c0bec1fbe25956393995622;p=lttv.git seek n forward and backward implemented in trace context git-svn-id: http://ltt.polymtl.ca/svn@1090 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/ltt/branches/poly/lttv/lttv/module.c b/ltt/branches/poly/lttv/lttv/module.c index bc4f3de0..aab28bca 100644 --- a/ltt/branches/poly/lttv/lttv/module.c +++ b/ltt/branches/poly/lttv/lttv/module.c @@ -237,8 +237,8 @@ LttvLibrary *lttv_library_load(char *name, GError **error) return l; } - -static void library_unload(LttvLibrary *l) +/* Returns < 0 if still in use, 0 if freed */ +static gint library_unload(LttvLibrary *l) { guint i; @@ -249,13 +249,13 @@ static void library_unload(LttvLibrary *l) if(l->locked_loaded > 0) { g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: locked loaded", l->info.name); - return; + return 1; } if(l->info.load_count > 0) { g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: load count %d", l->info.name, l->info.load_count); - return; + return l->info.load_count; } /* Check if all its modules have been released */ @@ -265,7 +265,7 @@ static void library_unload(LttvLibrary *l) if(m->info.use_count > 0) { g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,"Unload library %s: module %s used", l->info.name, m->info.name); - return; + return 1; } } @@ -278,15 +278,21 @@ static void library_unload(LttvLibrary *l) /* insure that module.c will be finalized */ finish_destroy(); + return 0; } -void lttv_library_unload(LttvLibrary *l) +gint lttv_library_unload(LttvLibrary *l) { /* In the case where we wait for a module to release, the load count is 0 * and should not be decremented. */ - if(l->info.load_count != 0) l->info.load_count--; - library_unload(l); + if(l->info.load_count != 0) { + l->info.load_count--; + return l->info.load_count; + } else { + library_unload(l); + return 0; + } } @@ -296,10 +302,10 @@ static void library_lock_loaded(LttvLibrary *l) } -static void library_unlock_loaded(LttvLibrary *l) +static gint library_unlock_loaded(LttvLibrary *l) { l->locked_loaded--; - library_unload(l); + return library_unload(l); } @@ -571,8 +577,8 @@ static void destroy() m = (LttvModule *)(l->modules->pdata[j]); while(m->info.require_count > 0) lttv_module_release(m); } - library_unlock_loaded(l); - while(l->info.load_count > 0) lttv_library_unload(l); + if(library_unlock_loaded(l) > 0) + while(lttv_library_unload(l) > 0); /* If the number of librairies loaded have changed, restart from the * beginning */ diff --git a/ltt/branches/poly/lttv/lttv/module.h b/ltt/branches/poly/lttv/lttv/module.h index 68791a2d..67931405 100644 --- a/ltt/branches/poly/lttv/lttv/module.h +++ b/ltt/branches/poly/lttv/lttv/module.h @@ -111,7 +111,8 @@ LttvModule *lttv_module_prerequisite_get(LttvModule *m, unsigned i); LttvLibrary *lttv_library_load(char *name, GError **error); -void lttv_library_unload(LttvLibrary *l); +/* Returns 0 if library is unloaded, > 0 otherwise */ +gint lttv_library_unload(LttvLibrary *l); /* Obtain information about the library */ diff --git a/ltt/branches/poly/lttv/lttv/state.c b/ltt/branches/poly/lttv/lttv/state.c index 8574778a..49fdf382 100644 --- a/ltt/branches/poly/lttv/lttv/state.c +++ b/ltt/branches/poly/lttv/lttv/state.c @@ -1276,6 +1276,11 @@ static gboolean process_free(void *hook_data, void *call_data) if(likely(process != NULL)) { /* release_task is happening at kernel level : we can now safely release * the data structure of the process */ + guint num_cpus = ltt_trace_get_num_cpu(ts->parent.t); + guint i; + for(i=0; i< num_cpus; i++) { + g_assert(process != ts->running_process[i]); + } exit_process(s, process); } diff --git a/ltt/branches/poly/lttv/lttv/stats.c b/ltt/branches/poly/lttv/lttv/stats.c index bd9c1e6c..abee8199 100644 --- a/ltt/branches/poly/lttv/lttv/stats.c +++ b/ltt/branches/poly/lttv/lttv/stats.c @@ -89,7 +89,7 @@ static void lttv_stats_init(LttvTracesetStats *self) LTTV_STATS_USE_COUNT, LTTV_UINT, &v); - *(v.v_uint)++; + (*(v.v_uint))++; if(*(v.v_uint) == 1) { g_assert(lttv_attribute_get_number(self->stats) == 0); } @@ -106,7 +106,7 @@ static void lttv_stats_init(LttvTracesetStats *self) lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT, LTTV_UINT, &v); - *(v.v_uint)++; + (*(v.v_uint))++; if(*(v.v_uint) == 1) { g_assert(lttv_attribute_get_number(tcs->stats) == 0); } @@ -151,7 +151,7 @@ static void lttv_stats_fini(LttvTracesetStats *self) lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT, LTTV_UINT, &v); - *(v.v_uint)--; + (*(v.v_uint))--; if(*(v.v_uint) == 0) { lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS); @@ -166,7 +166,7 @@ static void lttv_stats_fini(LttvTracesetStats *self) lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT, LTTV_UINT, &v); - *(v.v_uint)--; + (*(v.v_uint))--; if(*(v.v_uint) == 0) { lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS); diff --git a/ltt/branches/poly/lttv/lttv/tracecontext.c b/ltt/branches/poly/lttv/lttv/tracecontext.c index 6f1e7b58..305d736c 100644 --- a/ltt/branches/poly/lttv/lttv/tracecontext.c +++ b/ltt/branches/poly/lttv/lttv/tracecontext.c @@ -28,7 +28,7 @@ #include #include - +#define min(a,b) (((a)<(b))?(a):(b)) gint compare_tracefile(gconstpointer a, gconstpointer b) @@ -1079,6 +1079,8 @@ void lttv_traceset_context_position_save(const LttvTracesetContext *self, pos->tfc = g_array_set_size(pos->tfc, 0); pos->ep = g_array_set_size(pos->ep, 0); + + pos->timestamp = ltt_time_infinite; for(i=0; itraces[i]->tracefiles; @@ -1273,3 +1275,197 @@ void lttv_process_traceset_get_sync_data(LttvTracesetContext *tsc) lttv_traceset_context_position_save(tsc, tsc->sync_position); } +struct seek_back_data { + guint first_event; /* Index of the first event in the array : we will always + overwrite at this position : this is a circular array. + */ + guint events_found; + GPtrArray *array; /* array of LttvTracesetContextPositions pointers */ +}; + +static gint seek_back_event_hook(void *hook_data, void* call_data) +{ + struct seek_back_data *sd = (struct seek_back_data*)hook_data; + LttvTracefileContext *tfc = (LttvTracefileContext*)call_data; + LttvTracesetContext *tsc = tfc->t_context->ts_context; + LttvTracesetContextPosition *pos; + + if(sd->events_found < sd->array->len) { + pos = (LttvTracesetContextPosition*)g_ptr_array_index (sd->array, + sd->events_found); + } else { + pos = (LttvTracesetContextPosition*)g_ptr_array_index (sd->array, + sd->first_event); + } + + lttv_traceset_context_position_save(tsc, pos); + + if(sd->first_event >= sd->array->len - 1) sd->first_event = 0; + else sd->first_event++; + + sd->events_found = min(sd->array->len, sd->events_found + 1); + + return FALSE; +} + + +/* Seek back n events back from the current position. + * + * Parameters : + * @self The trace set context + * @n number of events to jump over + * @first_offset The initial offset value used. Hint : try about 100000ns. + * + * Return value : the number of events found (might be lower than the number + * requested if beginning of traceset is reached). + * + * The first search will go back first_offset and try to find the last n events + * matching the filter. If there are not enough, it will try to go back from the + * new trace point from first_offset*2, and so on, until beginning of trace or n + * events are found. + * + * Note : this function does not take in account the LttvFilter : use the + * similar function found in state.c instead. + * + * Note2 : the caller must make sure that the LttvTracesetContext does not + * contain any hook, as process_traceset_middle is used in this routine. + */ +guint lttv_process_traceset_seek_n_backward(LttvTracesetContext *self, + guint n, LttTime first_offset) +{ + guint i; + LttvTracesetContextPosition *next_iter_end_pos = + lttv_traceset_context_position_new(); + LttvTracesetContextPosition *end_pos = lttv_traceset_context_position_new(); + LttTime time; + LttTime time_offset; + struct seek_back_data sd; + LttvHooks *hooks = lttv_hooks_new(); + + sd.first_event = 0; + sd.events_found = 0; + sd.array = g_ptr_array_sized_new(n); + g_ptr_array_set_size(sd.array, n); + for(i=0;itime_span.end_time) > 0) { + time = self->time_span.end_time; + } + time_offset = first_offset; + + lttv_hooks_add(hooks, seek_back_event_hook, &sd, LTTV_PRIO_DEFAULT); + + lttv_process_traceset_begin(self, NULL, NULL, NULL, hooks, NULL); + + while(1) { + /* stop criteria : - n events found + * - time < beginning of trace */ + if(ltt_time_compare(time, self->time_span.start_time) < 0) break; + if(sd.events_found == n) break; + + lttv_traceset_context_position_copy(end_pos, next_iter_end_pos); + + /* We must seek the traceset back to time - time_offset */ + /* this time becomes the new reference time */ + time = ltt_time_sub(time, time_offset); + + lttv_process_traceset_seek_time(self, time); + lttv_traceset_context_position_save(self, next_iter_end_pos); + + /* Process the traceset, calling a hook which adds events + * to the array, overwriting the tail. It changes first_event and + * events_found too. */ + /* We would like to have a clean context here : no other hook than our's */ + + lttv_process_traceset_middle(self, ltt_time_infinite, + G_MAXUINT, end_pos); + + time_offset = ltt_time_mul(time_offset, BACKWARD_SEEK_MUL); + } + + lttv_traceset_context_position_destroy(end_pos); + lttv_traceset_context_position_destroy(next_iter_end_pos); + + lttv_process_traceset_end(self, NULL, NULL, NULL, hooks, NULL); + + if(sd.events_found > 0) { + /* Seek the traceset to the first event in the circular array */ + LttvTracesetContextPosition *pos = + (LttvTracesetContextPosition*)g_ptr_array_index (sd.array, + sd.first_event); + g_assert(lttv_process_traceset_seek_position(self, pos) == 0); + } + + for(i=0;ievent_count++; + + if(sd->event_count >= sd->n) + return TRUE; + else + return FALSE; +} + +/* Seek back n events forward from the current position + * + * Parameters : + * @self the trace set context + * @n number of events to jump over + * + * returns : the number of events jumped over (may be less than requested if end + * of traceset reached) */ +guint lttv_process_traceset_seek_n_forward(LttvTracesetContext *self, + guint n) +{ + struct seek_forward_data sd; + sd.event_count = 0; + sd.n = n; + LttvHooks *hooks = lttv_hooks_new(); + + lttv_hooks_add(hooks, seek_forward_event_hook, &sd, LTTV_PRIO_DEFAULT); + + lttv_process_traceset_begin(self, NULL, NULL, NULL, hooks, NULL); + + /* it will end on the end of traceset, or the fact that the + * hook returns TRUE. + */ + lttv_process_traceset_middle(self, ltt_time_infinite, + G_MAXUINT, NULL); + + /* Here, our position is either the end of traceset, or the exact position + * after n events : leave it like this. */ + + lttv_process_traceset_end(self, NULL, NULL, NULL, hooks, NULL); + + lttv_hooks_destroy(hooks); + + return sd.event_count; +} + + diff --git a/ltt/branches/poly/lttv/lttv/tracecontext.h b/ltt/branches/poly/lttv/lttv/tracecontext.h index 429a9016..f1396463 100644 --- a/ltt/branches/poly/lttv/lttv/tracecontext.h +++ b/ltt/branches/poly/lttv/lttv/tracecontext.h @@ -335,4 +335,16 @@ void lttv_process_traceset_synchronize_tracefiles(LttvTracesetContext *tsc); void lttv_process_traceset_get_sync_data(LttvTracesetContext *tsc); +/* Seek n events forward and backward (without filtering) : only use these where + * necessary : the seek backward is costy. */ + +#define BACKWARD_SEEK_MUL 2 /* Multiplication factor of time_offset between + backward seek iterations */ + +guint lttv_process_traceset_seek_n_forward(LttvTracesetContext *self, + guint n); + +guint lttv_process_traceset_seek_n_backward(LttvTracesetContext *self, + guint n, LttTime first_offset); + #endif // PROCESSTRACE_H