LttvAttribute *a;
LttvAttribute *ts_a;
TimeInterval *Time_Span;
+ GTree *pqueue;
};
struct _LttvTracesetContextClass {
GType lttv_tracefile_context_get_type (void);
+/* Run through the events in a traceset in sorted order calling all the
+ hooks appropriately. It starts at the current time and runs until end or
+ nb_events are processed. */
+
void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
- unsigned maxNumEvents);
+ unsigned nb_events);
+
+/* Process traceset can also be done in smaller pieces calling begin, middle
+ repeatedly, and end. The middle function return the number of events
+ processed. It may be larger than nb_events if several events have the
+ same timestamp. It will be smaller than nb_events if the end time
+ is reached. */
+
+void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end);
+
+guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end,
+ unsigned nb_events);
+
+void lttv_process_traceset_end(LttvTracesetContext *self);
+
void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start);
guint pid;
guint ppid;
LttTime creation_time;
+ LttTime insertion_time;
GQuark name;
GQuark pid_time;
GArray *execution_stack; /* Array of LttvExecutionState */
LttvExecutionState *state; /* Top of interrupt stack */
+ GQuark last_cpu; /* Last CPU where process was scheduled */
/* opened file descriptors, address map?... */
} LttvProcessState;
-//FIXME : find by pid and birth time : both are necessary to be unique
-LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs, guint pid);
-LttvProcessState *lttv_state_find_process_from_trace(LttvTraceState *ts, guint pid);
+
+LttvProcessState *
+lttv_state_find_process(LttvTracefileState *tfs, guint pid);
+
+LttvProcessState *
+lttv_state_find_process_from_trace(LttvTraceState *ts, GQuark cpu, guint pid);
+
+LttvProcessState *
+lttv_state_find_process_or_create(LttvTracefileState *tfs, guint pid);
+
+LttvProcessState *
+lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent,
+ guint pid);
/* The LttvTracesetState, LttvTraceState and LttvTracefileState types
GQuark *syscall_names;
GQuark *trap_names;
GQuark *irq_names;
- gboolean recompute_state_in_seek;
- gboolean saved_state_ready;
- gboolean saved_state_available;
+ LttTime *max_time_state_recomputed_in_seek;
};
struct _LttvTraceStateClass {
bin_PROGRAMS = lttv
+INCLUDES = \
+ -DPACKAGE_PLUGIN_DIR=\""$(lttvplugindir)"\" \
+ @PACKAGE_CFLAGS@ \
+ $(DEFAULT_INCLUDES)
+
+libdir = ${lttvplugindir}
+
lttv_SOURCES = main.c module.c option.c \
hook.c attribute.c \
iattribute.c processTrace.c \
- state.c stats.c traceset.c
+ state.c stats.c traceset.c
attribute_finalize (LttvAttribute *self)
{
g_hash_table_destroy(self->names);
- g_critical("attribute_finalize()");
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "attribute_finalize()");
g_array_free(self->attributes, TRUE);
G_OBJECT_CLASS(g_type_class_peek_parent(
g_type_class_peek(LTTV_ATTRIBUTE_TYPE)))->finalize(G_OBJECT(self));
void lttv_hooks_destroy(LttvHooks *h)
{
- g_critical("lttv_hooks_destroy()");
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "lttv_hooks_destroy()");
g_array_free(h, TRUE);
}
static void lttv_help(void *hook_data);
+/* This is the handler to specify when we dont need all the debugging
+ messages. It receives the message and does nothing. */
+
+void ignore_and_drop_message(const gchar *log_domain, GLogLevelFlags log_level,
+ const gchar *message, gpointer user_data) {
+}
+
+
/* Since everything is done in modules, the main program only takes care
of the infrastructure. */
g_mem_profile();
#endif
+ g_log_set_handler(NULL, G_LOG_LEVEL_INFO, ignore_and_drop_message, NULL);
+ g_log_set_handler(NULL, G_LOG_LEVEL_DEBUG, ignore_and_drop_message, NULL);
+
g_type_init();
//g_type_init_with_debug_flags (G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS);
/* Initialize the module loading */
- lttv_module_path_add("/usr/lib/lttv/plugins");
+ lttv_module_path_add(PACKAGE_PLUGIN_DIR);
/* Add some built-in options */
lttv_module_path_add(a_module_path);
}
+
void lttv_verbose(void *hook_data)
{
g_log_set_handler(NULL, G_LOG_LEVEL_INFO, g_log_default_handler, NULL);
#include <lttv/module.h>
-#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
-#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
-
struct _LttvModule
{
GModule *module;
void lttv_module_init(int argc, char **argv)
{
- g_info("Init module.c");
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init module.c");
modules = g_hash_table_new(g_str_hash, g_str_equal);
modulesPaths = g_ptr_array_new();
}
{
int i;
- g_info("Destroy module.c");
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy module.c");
/* Unload all modules */
lttv_module_unload_all();
void lttv_module_path_add(const char *name)
{
- g_info("Add module path %s", name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Add module path %s", name);
g_ptr_array_add(modulesPaths,(char*)g_strdup(name));
}
LttvModuleInit init_function;
- g_info("Load module %s", name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Load module %s", name);
/* Try to find the module along all the user specified paths */
for(i = 0 ; i < modulesPaths->len ; i++) {
pathname = g_module_build_path(modulesPaths->pdata[i],name);
- g_info("Try path %s", pathname);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Try path %s", pathname);
gm = g_module_open(pathname,0);
g_free(pathname);
if(gm != NULL) break;
- g_info("Trial failed, %s", g_module_error());
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"Trial failed, %s",g_module_error());
}
/* Try the default system path */
if(gm == NULL) {
pathname = g_module_build_path(NULL,name);
- g_info("Try default path");
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Try default path");
gm = g_module_open(pathname,0);
g_free(pathname);
}
/* Module cannot be found */
if(gm == NULL) {
- g_info("Trial failed, %s", g_module_error());
- g_info("Failed to load %s", name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,"Trial failed, %s",g_module_error());
+ g_warning("Failed to load module %s", name);
return NULL;
}
m = g_hash_table_lookup(modules, module_name);
if(m == NULL) {
- g_info("Module %s (%s) loaded, call its init function", name, module_name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ "Module %s (%s) loaded, call its init function", name, module_name);
/* Module loaded for the first time. Insert it in the table and call the
init function if any. */
/* Module was already opened, check that it really is the same and
undo the extra g_module_open */
- g_info("Module %s (%s) was already loaded, no need to call init function",
- name, module_name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ "Module %s (%s) was already loaded, no need to call init function",
+ name, module_name);
if(m->module != gm) g_error("Two gmodules with the same pathname");
g_module_close(gm);
}
LttvModule *
lttv_module_load(const char *name, int argc, char **argv)
{
- g_info("Load module %s explicitly", name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Load module %s explicitly", name);
LttvModule *m = module_load(name, argc, argv);
if(m != NULL) m->load_count++;
return m;
{
LttvModule *module;
- g_info("Load module %s, as %s is a dependent requiring it", name,
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
+ "Load module %s, as %s is a dependent requiring it", name,
g_module_name(m->module));
module = module_load(name, argc, argv);
if(module != NULL) g_ptr_array_add(module->dependents, m);
/* Decrement the reference count */
- g_info("Unload module %s", g_module_name(m->module));
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload module %s",
+ g_module_name(m->module));
m->ref_count--;
if(m->ref_count > 0) {
- g_info("Module usage count decremented to %d", m->ref_count);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ "Module usage count decremented to %d", m->ref_count);
return;
}
/* We really have to unload the module, first unload its dependents */
len = m->dependents->len;
- g_info("Unload dependent modules");
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload dependent modules");
for(i = 0 ; i < len ; i++) {
module_unload(m->dependents->pdata[i]);
/* Unload the module itself */
- g_info("Call the destroy function and unload the module");
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ "Call the destroy function and unload the module");
if(!g_module_symbol(m->module, "destroy", (gpointer)&destroy_function)) {
g_warning("module (%s) has no destroy function", pathname);
}
void lttv_module_unload(LttvModule *m)
{
- g_info("Explicitly unload module %s", g_module_name(m->module));
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Explicitly unload module %s",
+ g_module_name(m->module));
if(m->load_count <= 0) {
g_error("more unload than load (%s)", g_module_name(m->module));
return;
#include <glib.h>
#include <lttv/option.h>
-#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
-#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
-
typedef struct _LttvOption {
char *long_name;
char char_name;
void lttv_option_init(int argc, char **argv)
{
- g_info("Init option.c");
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init option.c");
options = g_hash_table_new(g_str_hash, g_str_equal);
}
int i;
- g_info("Destroy option.c");
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy option.c");
g_hash_table_foreach(options, list_options, list);
g_hash_table_destroy(options);
{
LttvOption *option;
- g_info("Add option %s", long_name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Add option %s", long_name);
if(g_hash_table_lookup(options, long_name) != NULL) {
g_warning("duplicate option");
return;
{
LttvOption *option = g_hash_table_lookup(options, long_name);
- g_info("Remove option %s", long_name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Remove option %s", long_name);
if(option == NULL) {
g_warning("trying to remove unknown option %s", long_name);
return;
if(rc > 0) {
option = (LttvOption *)(list->pdata[rc - 1]);
- g_info("Option %s encountered", option->long_name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Option %s encountered",
+ option->long_name);
if(option->hook != NULL) {
- g_info("Option %s hook called", option->long_name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Option %s hook called",
+ option->long_name);
option->hook(option->hook_data);
}
i++;
}
else if(rc == POPT_ERROR_BADOPT && i != first_arg) {
- g_info("Option %s not recognized, rescan options with new additions",
- poptBadOption(c,0));
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ "Option %s not recognized, rescan options with new additions",
+ poptBadOption(c,0));
/* Perhaps this option is newly added, restart parsing */
for(i = 0; i < first_arg; i++) {
rc = poptGetNextOpt(c);
option = (LttvOption *)(list->pdata[rc - 1]);
- g_info("Option %s rescanned, skipped", option->long_name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Option %s rescanned, skipped",
+ option->long_name);
}
}
}
-void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
- unsigned maxNumEvents)
+void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end)
{
- GPtrArray *traces = g_ptr_array_new();
-
- GPtrArray *tracefiles = g_ptr_array_new();
-
- GTree *pqueue = g_tree_new(compare_tracefile);
-
- guint i, j, nbi, nbj, id, nb_control, nb_cpu;
-
- LttTrace *trace;
+ guint i, j, nbi, nbj, nb_control, nb_cpu;
LttvTraceContext *tc;
- LttTracefile *tracefile;
-
LttvTracefileContext *tfc;
- LttEvent *event;
-
- unsigned count = 0;
-
- LttTime previous_timestamp = {0, 0};
-
/* Call all before_traceset, before_trace, and before_tracefile hooks.
For all qualifying tracefiles, seek to the start time, create a context,
read one event and insert in the pqueue based on the event time. */
lttv_hooks_call(self->before, self);
nbi = lttv_traceset_number(self->ts);
+ self->pqueue = g_tree_new(compare_tracefile);
for(i = 0 ; i < nbi ; i++) {
tc = self->traces[i];
- trace = tc->t;
if(!lttv_hooks_call_check(tc->check, tc)) {
- g_ptr_array_add(traces, tc);
lttv_hooks_call(tc->before, tc);
- nb_control = ltt_trace_control_tracefile_number(trace);
- nb_cpu = ltt_trace_per_cpu_tracefile_number(trace);
+ nb_control = ltt_trace_control_tracefile_number(tc->t);
+ nb_cpu = ltt_trace_per_cpu_tracefile_number(tc->t);
nbj = nb_control + nb_cpu;
for(j = 0 ; j < nbj ; j++) {
tfc = tc->per_cpu_tracefiles[j - nb_control];
}
- tracefile = tfc->tf;
-
if(!lttv_hooks_call_check(tfc->check, tfc)) {
- g_ptr_array_add(tracefiles, tfc);
lttv_hooks_call(tfc->before, tfc);
if(tfc->e != NULL) {
if(tfc->timestamp.tv_sec < end.tv_sec ||
(tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec)){
- g_tree_insert(pqueue, &(tfc->timestamp), tfc);
+ g_tree_insert(self->pqueue, &(tfc->timestamp), tfc);
}
}
}
}
}
}
+}
+
+
+guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end,
+ unsigned nb_events)
+{
+ GTree *pqueue = self->pqueue;
+
+ guint id;
+
+ LttvTraceContext *tc;
+
+ LttvTracefileContext *tfc;
+
+ LttEvent *event;
+
+ unsigned count = 0;
+
+ LttTime previous_timestamp = {0, 0};
/* Get the next event from the pqueue, call its hooks,
reinsert in the pqueue the following event from the same tracefile
while(TRUE) {
tfc = NULL;
g_tree_foreach(pqueue, get_first, &tfc);
- if(tfc == NULL) break;
+ if(tfc == NULL) return count;
/* Have we reached the maximum number of events specified? However,
continue for all the events with the same time stamp (CHECK?). Then,
empty the queue and break from the loop. */
- count++;
- if(count > maxNumEvents){
- if(tfc->timestamp.tv_sec == previous_timestamp.tv_sec &&
- tfc->timestamp.tv_nsec == previous_timestamp.tv_nsec) {
- count--;
- }else{
- while(TRUE){
- tfc = NULL;
- g_tree_foreach(pqueue, get_first, &tfc);
- if(tfc == NULL) break;
- g_tree_remove(pqueue, &(tfc->timestamp));
- }
- break;
- }
- }
+ if(count >= nb_events &&
+ ltt_time_compare(tfc->timestamp, previous_timestamp) != 0)
+ return count;
+
previous_timestamp = tfc->timestamp;
tfc = g_tree_lookup(pqueue, &(tfc->timestamp));
g_tree_remove(pqueue, &(tfc->timestamp));
+ count++;
if(!lttv_hooks_call(tfc->check_event, tfc)) {
id = ltt_event_eventtype_id(tfc->e);
g_tree_insert(pqueue, &(tfc->timestamp), tfc);
}
}
+}
+
+
+void lttv_process_traceset_end(LttvTracesetContext *self)
+{
+ guint i, j, nbi, nbj, nb_control, nb_cpu;
+
+ LttvTraceContext *tc;
+
+ LttvTracefileContext *tfc;
+
+ /* Call all after_traceset, after_trace, and after_tracefile hooks. */
- /* Call all the after_tracefile, after_trace and after_traceset hooks. */
+ nbi = lttv_traceset_number(self->ts);
- for(i = 0, j = 0 ; i < traces->len ; i++) {
- tc = traces->pdata[i];
- while(j < tracefiles->len) {
- tfc = tracefiles->pdata[j];
+ for(i = 0 ; i < nbi ; i++) {
+ tc = self->traces[i];
- if(tfc->t_context == tc) {
- lttv_hooks_call(tfc->after, tfc);
- j++;
+ /* The check hooks are called again to avoid memorizing the results
+ obtained at the beginning. CHECK if it poses a problem */
+
+ if(!lttv_hooks_call_check(tc->check, tc)) {
+ nb_control = ltt_trace_control_tracefile_number(tc->t);
+ nb_cpu = ltt_trace_per_cpu_tracefile_number(tc->t);
+ nbj = nb_control + nb_cpu;
+
+ for(j = 0 ; j < nbj ; j++) {
+ if(j < nb_control) {
+ tfc = tc->control_tracefiles[j];
+ }
+ else {
+ tfc = tc->per_cpu_tracefiles[j - nb_control];
+ }
+
+ if(!lttv_hooks_call_check(tfc->check, tfc)) {
+ lttv_hooks_call(tfc->after, tfc);
+ }
}
- else break;
+ lttv_hooks_call(tc->after, tc);
}
- lttv_hooks_call(tc->after, tc);
}
-
- g_assert(j == tracefiles->len);
lttv_hooks_call(self->after, self);
- /* Free the traces, tracefiles and pqueue */
+ /* Empty and free the pqueue */
- g_ptr_array_free(tracefiles, TRUE);
- g_ptr_array_free(traces, TRUE);
- g_tree_destroy(pqueue);
+ while(TRUE){
+ tfc = NULL;
+ g_tree_foreach(self->pqueue, get_first, &tfc);
+ if(tfc == NULL) break;
+ g_tree_remove(self->pqueue, &(tfc->timestamp));
+ }
+ g_tree_destroy(self->pqueue);
+}
+
+
+void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
+ unsigned nb_events)
+{
+ lttv_process_traceset_begin(self, end);
+ lttv_process_traceset_middle(self, end, nb_events);
+ lttv_process_traceset_end(self);
}
static void lttv_state_free_process_table(GHashTable *processes);
-static LttvProcessState *create_process(LttvTracefileState *tfs,
- LttvProcessState *parent, guint pid);
void lttv_state_save(LttvTraceState *self, LttvAttribute *container)
{
}
+guint process_hash(gconstpointer key)
+{
+ return ((LttvProcessState *)key)->pid;
+}
+
+
+gboolean process_equal(gconstpointer a, gconstpointer b)
+{
+ LttvProcessState *process_a, *process_b;
+
+ process_a = (LttvProcessState *)a;
+ process_b = (LttvProcessState *)b;
+
+ if(process_a->pid != process_b->pid) return FALSE;
+ if(process_a->pid == 0 &&
+ process_a->last_cpu != process_b->last_cpu) return FALSE;
+ return TRUE;
+}
+
+
static void
restore_init_state(LttvTraceState *self)
{
LttTime null_time = {0,0};
if(self->processes != NULL) lttv_state_free_process_table(self->processes);
- self->processes = g_hash_table_new(g_direct_hash, g_direct_equal);
+ self->processes = g_hash_table_new(process_hash, process_equal);
self->nb_event = 0;
nb_control = ltt_trace_control_tracefile_number(self->parent.t);
tfcs->parent.timestamp = null_time;
tfcs->saved_position = 0;
- tfcs->process = create_process(tfcs, NULL,0);
+ tfcs->process = lttv_state_create_process(tfcs, NULL,0);
+ tfcs->process->state->s = LTTV_STATE_RUN;
+ tfcs->process->last_cpu = tfcs->cpu_name;
}
}
+static LttTime time_zero = {0,0};
static void
init(LttvTracesetState *self, LttvTraceset *ts)
tc = self->parent.traces[i];
tcs = (LttvTraceState *)tc;
tcs->save_interval = 100000;
- tcs->recompute_state_in_seek = TRUE;
- tcs->saved_state_ready = FALSE;
+ tcs->max_time_state_recomputed_in_seek = &time_zero;
fill_name_tables(tcs);
nb_control = ltt_trace_control_tracefile_number(tc->t);
}
new_process->state = &g_array_index(new_process->execution_stack,
LttvExecutionState, new_process->execution_stack->len - 1);
- g_hash_table_insert(new_processes, GUINT_TO_POINTER(new_process->pid),
- new_process);
+ g_hash_table_insert(new_processes, new_process, new_process);
}
static GHashTable *lttv_state_copy_process_table(GHashTable *processes)
{
- GHashTable *new_processes = g_hash_table_new(g_direct_hash, g_direct_equal);
+ GHashTable *new_processes = g_hash_table_new(process_hash, process_equal);
g_hash_table_foreach(processes, copy_process_state, new_processes);
return new_processes;
static void state_restore(LttvTraceState *self, LttvAttribute *container)
{
- guint i, nb_control, nb_per_cpu, nb_tracefile;
+ guint i, nb_control, nb_per_cpu, nb_tracefile, pid;
LttvTracefileState *tfcs;
type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS,
&value);
g_assert(type == LTTV_UINT);
- tfcs->process = lttv_state_find_process(tfcs, *(value.v_uint));
+ pid = *(value.v_uint);
+ tfcs->process = lttv_state_find_process_or_create(tfcs, pid);
+
type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
&value);
g_assert(type == LTTV_POINTER);
}
-static LttvProcessState *create_process(LttvTracefileState *tfs,
- LttvProcessState *parent, guint pid)
+LttvProcessState *
+lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent,
+ guint pid)
{
LttvProcessState *process = g_new(LttvProcessState, 1);
tcs = (LttvTraceState *)tc = tfs->parent.t_context;
- g_hash_table_insert(tcs->processes, GUINT_TO_POINTER(pid), process);
process->pid = pid;
+ process->last_cpu = tfs->cpu_name;
+ g_hash_table_insert(tcs->processes, process, process);
if(parent) {
process->ppid = parent->pid;
process->name = parent->name;
+ process->creation_time = tfs->parent.timestamp;
}
+
+ /* No parent. This process exists but we are missing all information about
+ its creation. The birth time is set to zero but we remember the time of
+ insertion */
+
else {
process->ppid = 0;
process->name = LTTV_STATE_UNNAMED;
+ process->creation_time = ltt_time_zero;
}
- process->creation_time = tfs->parent.timestamp;
+ process->insertion_time = tfs->parent.timestamp;
sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec,
process->creation_time.tv_nsec);
process->pid_time = g_quark_from_string(buffer);
+ process->last_cpu = tfs->cpu_name;
process->execution_stack = g_array_new(FALSE, FALSE,
sizeof(LttvExecutionState));
g_array_set_size(process->execution_stack, 1);
return process;
}
-LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs,
- guint pid)
+
+LttvProcessState *
+lttv_state_find_process_from_trace(LttvTraceState *ts, GQuark cpu, guint pid)
{
- LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
- LttvProcessState *process = g_hash_table_lookup(ts->processes,
- GUINT_TO_POINTER(pid));
- if(process == NULL) process = create_process(tfs, NULL, pid);
+ LttvProcessState key;
+ LttvProcessState *process;
+
+ key.pid = pid;
+ key.last_cpu = cpu;
+ process = g_hash_table_lookup(ts->processes, &key);
return process;
}
-LttvProcessState *lttv_state_find_process_from_trace(LttvTraceState *ts,
+
+LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs,
guint pid)
{
- LttvProcessState *process = g_hash_table_lookup(ts->processes,
- GUINT_TO_POINTER(pid));
- //We do not create a process at this level, because we can be called
- //from outside of state.c, and therefore cannot assume a tracefile
- //exists.
- //if(process == NULL) process = create_process_from_trace(ts, NULL, pid);
- return process;
+ LttvTraceState *ts =(LttvTraceState *)tfs->parent.t_context;
+ return lttv_state_find_process_from_trace(ts, tfs->cpu_name, pid);
}
+LttvProcessState *
+lttv_state_find_process_or_create(LttvTracefileState *tfs, guint pid)
+{
+ LttvProcessState *process = lttv_state_find_process(tfs, pid);
+
+ if(process == NULL) process = lttv_state_create_process(tfs, NULL, pid);
+ return process;
+}
+
static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
{
LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context);
+ LttvProcessState key;
- g_hash_table_remove(ts->processes, GUINT_TO_POINTER(process->pid));
+ key.pid = process->pid;
+ key.last_cpu = process->last_cpu;
+ g_hash_table_remove(ts->processes, &key);
g_array_free(process->execution_stack, TRUE);
g_free(process);
}
s->process->state->change = s->parent.timestamp;
}
- s->process = lttv_state_find_process(s, pid_in);
+ s->process = lttv_state_find_process_or_create(s, pid_in);
s->process->state->s = LTTV_STATE_RUN;
+ s->process->last_cpu = s->cpu_name;
s->process->state->change = s->parent.timestamp;
return FALSE;
}
guint child_pid;
child_pid = ltt_event_get_unsigned(s->parent.e, f);
- create_process(s, s->process, child_pid);
+ lttv_state_create_process(s, s->process, child_pid);
return FALSE;
}
for(i = 0 ; i < nb_trace ; i++) {
tcs = (LttvTraceState *)self->parent.traces[i];
- if(tcs->recompute_state_in_seek) {
- if(tcs->saved_state_available) {
- saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
- LTTV_STATE_SAVED_STATES);
- min_pos = -1;
+ if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
+ saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
+ LTTV_STATE_SAVED_STATES);
+ min_pos = -1;
+
+ if(saved_states_tree) {
max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
mid_pos = max_pos / 2;
while(min_pos < max_pos) {
mid_pos = (min_pos + max_pos + 1) / 2;
}
+ }
- /* restore the closest earlier saved state */
- if(min_pos != -1) lttv_state_restore(tcs, closest_tree);
+ /* restore the closest earlier saved state */
+ if(min_pos != -1) lttv_state_restore(tcs, closest_tree);
- }
- /* There is no saved state yet we want to have it. Restart at T0 */
+ /* There is no saved state, yet we want to have it. Restart at T0 */
else {
restore_init_state(tcs);
lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
#include <stdio.h>
#include <lttv/stats.h>
+#include <lttv/lttv.h>
#include <ltt/facility.h>
#include <ltt/trace.h>
#include <ltt/event.h>
/* get the information for the process scheduled in */
- process = lttv_state_find_process(&(tfcs->parent), pid_in);
+ process = lttv_state_find_process_or_create(&(tfcs->parent), pid_in);
find_event_tree(tfcs, process->pid_time, tfcs->parent.cpu_name,
process->state->t, process->state->n, &(tfcs->current_events_tree),
hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k));
}
}
- g_critical("lttv_stats_remove_event_hooks()");
+ g_debug("lttv_stats_remove_event_hooks()");
g_array_free(before_hooks, TRUE);
g_array_free(after_hooks, TRUE);
}
#include "processlist.h"
#include "eventhooks.h"
#include "cfv-private.h"
-
-
-#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
-#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
+#include <lttv/lttv.h>
extern GSList *g_control_flow_data_list;
#include <gtk/gtk.h>
#include <gdk/gdk.h>
+#include <lttv/lttv.h>
#include <lttv/processTrace.h>
#include <lttv/gtktraceset.h>
#include <lttv/hook.h>
LttTime window_end = ltt_time_add(control_flow_data->time_window.time_width,
control_flow_data->time_window.start_time);
- g_critical("req : window_end : %u, %u", window_end.tv_sec,
+ g_debug("req : window_end : %u, %u", window_end.tv_sec,
window_end.tv_nsec);
- g_critical("req : time width : %u, %u", control_flow_data->time_window.time_width.tv_sec,
+ g_debug("req : time width : %u, %u", control_flow_data->time_window.time_width.tv_sec,
control_flow_data->time_window.time_width.tv_nsec);
- g_critical("x is : %i, x+width is : %i", x, x+width);
+ g_debug("x is : %i, x+width is : %i", x, x+width);
convert_pixels_to_time(drawing->drawing_area->allocation.width, x,
&control_flow_data->time_window.start_time,
event_request.x_begin = x;
event_request.x_end = x+width;
- g_critical("req : start : %u, %u", event_request.time_begin.tv_sec,
+ g_debug("req : start : %u, %u", event_request.time_begin.tv_sec,
event_request.time_begin.tv_nsec);
- g_critical("req : end : %u, %u", event_request.time_end.tv_sec,
+ g_debug("req : end : %u, %u", event_request.time_end.tv_sec,
event_request.time_end.tv_nsec);
LttvHooks *event = lttv_hooks_new();
// widget->allocation.height + SAFETY,
// -1);
- g_critical("drawing configure event");
- g_critical("New draw size : %i by %i",widget->allocation.width, widget->allocation.height);
+ g_debug("drawing configure event");
+ g_debug("New draw size : %i by %i",widget->allocation.width, widget->allocation.height);
if (drawing->pixmap)
G_OBJECT(widget),
"control_flow_data");
- g_critical("drawing expose event");
+ g_debug("drawing expose event");
guint x=0;
LttTime* current_time =
Drawing_t *drawing = control_flow_data->drawing;
- g_critical("click");
+ g_debug("click");
if(event->button == 1)
{
LttTime time;
/* left mouse button click */
- g_critical("x click is : %f", event->x);
+ g_debug("x click is : %f", event->x);
convert_pixels_to_time(widget->allocation.width, (guint)event->x,
&control_flow_data->time_window.start_time,
LttTime window_middle =
ltt_time_add(half_width,
drawing->control_flow_data->time_window.start_time);
- g_critical("ruler expose event");
+ g_debug("ruler expose event");
gdk_draw_rectangle (drawing->ruler->window,
drawing->ruler->style->white_gc,
static gboolean
motion_notify_ruler(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
{
- //g_critical("motion");
+ //g_debug("motion");
//eventually follow mouse and show time here
}
*****************************************************************************/
-#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
-#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
-
//#define PANGO_ENABLE_BACKEND
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <ltt/time.h>
#include <ltt/type.h>
+#include <lttv/lttv.h>
#include <lttv/hook.h>
#include <lttv/common.h>
#include <lttv/state.h>
current_time->tv_sec = 0;
current_time->tv_nsec = 0;
- //g_critical("time width1 : %u",time_window->time_width);
+ //g_debug("time width1 : %u",time_window->time_width);
get_time_window(mw,
time_window);
get_current_time(mw,
current_time);
- //g_critical("time width2 : %u",time_window->time_width);
+ //g_debug("time width2 : %u",time_window->time_width);
// Unreg done in the GuiControlFlow_Destructor
reg_update_time_window(update_time_window_hook, control_flow_data,
mw);
ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
guint *event_number = (guint*) call_data;
- g_critical("DEBUG : event selected by main window : %u", *event_number);
+ g_debug("DEBUG : event selected by main window : %u", *event_number);
// control_flow_data->currently_Selected_Event = *event_number;
// control_flow_data->Selected_Event = TRUE ;
if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
{
- g_critical("schedchange!");
+ g_debug("schedchange!");
/* Add process to process list (if not present) and get drawing "y" from
* process position */
pid_out = ltt_event_get_long_unsigned(e,element);
element = ltt_field_member(f,1);
pid_in = ltt_event_get_long_unsigned(e,element);
- g_critical("out : %u in : %u", pid_out, pid_in);
+ g_debug("out : %u in : %u", pid_out, pid_in);
/* Find process pid_out in the list... */
- //process_out = lttv_state_find_process_from_trace(ts, pid_out);
process_out = lttv_state_find_process(tfs, pid_out);
if(process_out == NULL) return 0;
- g_critical("out : %s",g_quark_to_string(process_out->state->s));
+ g_debug("out : %s",g_quark_to_string(process_out->state->s));
birth = process_out->creation_time;
gchar *name = strdup(g_quark_to_string(process_out->name));
g_free(name);
/* Find process pid_in in the list... */
- //process_in = lttv_state_find_process_from_trace(ts, pid_in);
process_in = lttv_state_find_process(tfs, pid_in);
if(process_in == NULL) return 0;
- g_critical("in : %s",g_quark_to_string(process_in->state->s));
+ g_debug("in : %s",g_quark_to_string(process_in->state->s));
birth = process_in->creation_time;
name = strdup(g_quark_to_string(process_in->name));
draw_context_out->previous->middle->x = event_request->x_begin;
draw_context_out->previous->under->x = event_request->x_begin;
- g_critical("out middle x_beg : %u",event_request->x_begin);
+ g_debug("out middle x_beg : %u",event_request->x_begin);
}
draw_context_out->current->middle->x = x;
prop_bg.color->blue = 0xe7e7;
}
- g_critical("calling from draw_event");
+ g_debug("calling from draw_event");
draw_bg((void*)&prop_bg, (void*)draw_context_out);
g_free(prop_bg.color);
gdk_gc_unref(draw_context_out->gc);
prop_line_out.style = GDK_LINE_SOLID;
prop_line_out.position = MIDDLE;
- g_critical("out state : %s", g_quark_to_string(process_out->state->s));
+ g_debug("out state : %s", g_quark_to_string(process_out->state->s));
/* color of line : status of the process */
if(process_out->state->s == LTTV_STATE_UNNAMED)
draw_context_in->previous->middle->x = event_request->x_begin;
draw_context_in->previous->over->x = event_request->x_begin;
draw_context_in->previous->under->x = event_request->x_begin;
- g_critical("in middle x_beg : %u",event_request->x_begin);
+ g_debug("in middle x_beg : %u",event_request->x_begin);
}
draw_context_in->current->middle->x = x;
prop_text_in.size = 6;
prop_text_in.position = OVER;
- g_critical("in state : %s", g_quark_to_string(process_in->state->s));
+ g_debug("in state : %s", g_quark_to_string(process_in->state->s));
/* foreground of text : status of the process */
if(process_in->state->s == LTTV_STATE_UNNAMED)
{
if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e)),"schedchange") == 0)
{
- g_critical("schedchange!");
+ g_debug("schedchange!");
/* Add process to process list (if not present) and get drawing "y" from
* process position */
pid_out = ltt_event_get_long_unsigned(e,element);
element = ltt_field_member(f,1);
pid_in = ltt_event_get_long_unsigned(e,element);
- //g_critical("out : %u in : %u", pid_out, pid_in);
+ //g_debug("out : %u in : %u", pid_out, pid_in);
/* Find process pid_out in the list... */
- process_out = lttv_state_find_process_from_trace(ts, pid_out);
+ process_out = lttv_state_find_process(tfs, pid_out);
if(process_out == NULL) return 0;
- //g_critical("out : %s",g_quark_to_string(process_out->state->s));
+ //g_debug("out : %s",g_quark_to_string(process_out->state->s));
birth = process_out->creation_time;
gchar *name = strdup(g_quark_to_string(process_out->name));
g_free(name);
/* Find process pid_in in the list... */
- process_in = lttv_state_find_process_from_trace(ts, pid_in);
+ process_in = lttv_state_find_process(tfs, pid_in);
if(process_in == NULL) return 0;
- //g_critical("in : %s",g_quark_to_string(process_in->state->s));
+ //g_debug("in : %s",g_quark_to_string(process_in->state->s));
birth = process_in->creation_time;
name = strdup(g_quark_to_string(process_in->name));
LttvTraceState *ts = (LttvTraceState*)tc;
LttvProcessState *process;
- process = lttv_state_find_process_from_trace(ts, process_info->pid);
+ /* We do not provide a cpu_name argument assuming that this is not the
+ idle job (pid 0) and thus its pid is unique across all cpus */
+ process = lttv_state_find_process_from_trace(ts, 0, process_info->pid);
/* Draw the closing line */
DrawContext *draw_context = hashed_process_data->draw_context;
draw_context->previous->middle->x = closure_data->event_request->x_begin;
draw_context->previous->over->x = closure_data->event_request->x_begin;
draw_context->previous->under->x = closure_data->event_request->x_begin;
- g_critical("out middle x_beg : %u",closure_data->event_request->x_begin);
+ g_debug("out middle x_beg : %u",closure_data->event_request->x_begin);
}
draw_context->current->middle->x = closure_data->event_request->x_end;
}
*/
- g_critical("calling from closure");
+ g_debug("calling from closure");
//FIXME : I need the cpu number in process's state to draw this.
//draw_bg((void*)&prop_bg, (void*)draw_context);
g_free(prop_bg.color);
* Author : Mathieu Desnoyers, June 2003
*/
-#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
-#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
-
#include <glib.h>
#include <gmodule.h>
+#include <lttv/lttv.h>
#include <lttv/module.h>
#include <lttv/gtktraceset.h>
#include "callbacks.h"
#include "interface.h"
#include "support.h"
+#include <lttv/lttv.h>
#include <lttv/mainwindow.h>
#include <lttv/menu.h>
#include <lttv/toolbar.h>
void construct_main_window(MainWindow * parent, WindowCreationData * win_creation_data)
{
- g_critical("construct_main_window()");
+ g_debug("construct_main_window()");
GtkWidget * new_window; /* New generated main window */
MainWindow * new_m_window;/* New main window structure */
GtkNotebook * notebook;
{
WindowCreationData* window_creation_data = (WindowCreationData*)hook_data;
- g_critical("GUI window_creation_hook()");
+ g_debug("GUI window_creation_hook()");
#ifdef ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
// Global attributes only used for interaction with main() here.
LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
- g_critical("GUI init()");
+ g_debug("GUI init()");
lttv_option_add("trace", 't',
"add a trace to the trace set to analyse",
lttv_hooks_remove_data(main_hooks, window_creation_hook, &win_creation_data);
- g_critical("GUI destroy()");
+ g_debug("GUI destroy()");
if(g_main_window_list){
g_slist_foreach(g_main_window_list, main_window_destroy_walk, NULL );
* MA 02111-1307, USA.
*/
+#include <lttv/lttv.h>
#include <lttv/menu.h>
* (functions).
*/
inline void lttv_menus_destroy(LttvMenus *h) {
- g_critical("lttv_menus_destroy()");
+ g_debug("lttv_menus_destroy()");
g_array_free(h, TRUE);
}
* MA 02111-1307, USA.
*/
+#include <lttv/lttv.h>
#include <lttv/toolbar.h>
* (functions).
*/
inline void lttv_toolbars_destroy(LttvToolbars *h) {
- g_critical("lttv_toolbars_destroy");
+ g_debug("lttv_toolbars_destroy");
g_array_free(h, TRUE);
}
#include <gtk/gtk.h>
#include <gdk/gdk.h>
+#include <lttv/lttv.h>
#include <lttv/module.h>
#include <lttv/gtktraceset.h>
#include <lttv/processTrace.h>