From: compudj Date: Tue, 27 Jan 2004 23:06:25 +0000 (+0000) Subject: revert mainLib, part 1 X-Git-Tag: v0.12.20~3063 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=88a3e3d0ba9a2e56e5d3524bd9da05fe3a81f8e6;p=lttv.git revert mainLib, part 1 git-svn-id: http://ltt.polymtl.ca/svn@426 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/ltt/branches/poly/lttv/main/attribute.c b/ltt/branches/poly/lttv/main/attribute.c new file mode 100644 index 00000000..4b6938d7 --- /dev/null +++ b/ltt/branches/poly/lttv/main/attribute.c @@ -0,0 +1,383 @@ + +#include +#include + +typedef union _AttributeValue { + int dv_int; + unsigned dv_uint; + long dv_long; + unsigned long dv_ulong; + float dv_float; + double dv_double; + LttTime dv_time; + gpointer dv_pointer; + char *dv_string; + GObject *dv_gobject; +} AttributeValue; + + +typedef struct _Attribute { + LttvAttributeName name; + LttvAttributeType type; + AttributeValue value; +} Attribute; + + +LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v) +{ + LttvAttributeValue va; + + switch(t) { + case LTTV_INT: va.v_int = &v->dv_int; break; + case LTTV_UINT: va.v_uint = &v->dv_uint; break; + case LTTV_LONG: va.v_long = &v->dv_long; break; + case LTTV_ULONG: va.v_ulong = &v->dv_ulong; break; + case LTTV_FLOAT: va.v_float = &v->dv_float; break; + case LTTV_DOUBLE: va.v_double = &v->dv_double; break; + case LTTV_TIME: va.v_time = &v->dv_time; break; + case LTTV_POINTER: va.v_pointer = &v->dv_pointer; break; + case LTTV_STRING: va.v_string = &v->dv_string; break; + case LTTV_GOBJECT: va.v_gobject = &v->dv_gobject; break; + } + return va; +} + + +AttributeValue init_value(LttvAttributeType t) +{ + AttributeValue v; + + switch(t) { + case LTTV_INT: v.dv_int = 0; break; + case LTTV_UINT: v.dv_uint = 0; break; + case LTTV_LONG: v.dv_long = 0; break; + case LTTV_ULONG: v.dv_ulong = 0; break; + case LTTV_FLOAT: v.dv_float = 0; break; + case LTTV_DOUBLE: v.dv_double = 0; break; + case LTTV_TIME: v.dv_time.tv_sec = 0; v.dv_time.tv_nsec = 0; break; + case LTTV_POINTER: v.dv_pointer = NULL; break; + case LTTV_STRING: v.dv_string = NULL; break; + case LTTV_GOBJECT: v.dv_gobject = NULL; break; + } + return v; +} + + +unsigned int +lttv_attribute_get_number(LttvAttribute *self) +{ + return self->attributes->len; +} + + +gboolean +lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous) +{ + *homogeneous = FALSE; + return TRUE; +} + + +LttvAttributeType +lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name, + LttvAttributeValue *v) +{ + Attribute *a; + + a = &g_array_index(self->attributes, Attribute, i); + *name = a->name; + *v = address_of_value(a->type, &(a->value)); + return a->type; +} + + +LttvAttributeType +lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name, + LttvAttributeValue *v) +{ + Attribute *a; + + unsigned i; + + gpointer p; + + p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(p == NULL) return LTTV_NONE; + + i = GPOINTER_TO_UINT(p); + i--; + a = &g_array_index(self->attributes, Attribute, i); + *v = address_of_value(a->type, &(a->value)); + return a->type; +} + + +LttvAttributeValue +lttv_attribute_add(LttvAttribute *self, LttvAttributeName name, + LttvAttributeType t) +{ + unsigned i; + + Attribute a, *pa; + + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i != 0) g_error("duplicate entry in attribute table"); + + a.name = name; + a.type = t; + a.value = init_value(t); + g_array_append_val(self->attributes, a); + i = self->attributes->len - 1; + pa = &g_array_index(self->attributes, Attribute, i); + g_hash_table_insert(self->names, GUINT_TO_POINTER(name), + GUINT_TO_POINTER(i + 1)); + return address_of_value(t, &(pa->value)); +} + + +/* Remove an attribute */ + +void +lttv_attribute_remove(LttvAttribute *self, unsigned i) +{ + Attribute *a; + + a = &g_array_index(self->attributes, Attribute, i); + + /* Remove the array element and its entry in the name index */ + + g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name)); + g_array_remove_index_fast(self->attributes, i); + + /* The element used to replace the removed element has its index entry + all wrong now. Reinsert it with its new position. */ + + if(self->attributes->len != i){ + g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name)); + g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1)); + } +} + +void +lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name) +{ + unsigned i; + + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i == 0) g_error("remove by name non existent attribute"); + + lttv_attribute_remove(self, i - 1); +} + +/* Create an empty iattribute object and add it as an attribute under the + specified name, or return an existing iattribute attribute. If an + attribute of that name already exists but is not a GObject supporting the + iattribute interface, return NULL. */ + +/*CHECK*/LttvAttribute* +lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name) +{ + unsigned i; + + Attribute a; + + LttvAttribute *new; + + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i != 0) { + a = g_array_index(self->attributes, Attribute, i - 1); + if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) { + return LTTV_ATTRIBUTE(a.value.dv_gobject); + } + else return NULL; + } + new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new); + return (LttvAttribute *)new; +} + +gboolean +lttv_attribute_find(LttvAttribute *self, LttvAttributeName name, + LttvAttributeType t, LttvAttributeValue *v) +{ + unsigned i; + + Attribute *a; + + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i != 0) { + a = &g_array_index(self->attributes, Attribute, i - 1); + if(a->type != t) return FALSE; + *v = address_of_value(t, &(a->value)); + return TRUE; + } + + *v = lttv_attribute_add(self, name, t); + return TRUE; +} + + +void lttv_attribute_recursive_free(LttvAttribute *self) +{ + int i, nb; + + Attribute *a; + + nb = self->attributes->len; + + for(i = 0 ; i < nb ; i++) { + a = &g_array_index(self->attributes, Attribute, i); + if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) { + lttv_attribute_recursive_free((LttvAttribute *)(a->value.dv_gobject)); + } + } + g_object_unref(self); +} + + +void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src) +{ + int i, nb; + + Attribute *a; + + LttvAttributeValue value; + + nb = src->attributes->len; + + for(i = 0 ; i < nb ; i++) { + a = &g_array_index(src->attributes, Attribute, i); + if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) { + lttv_attribute_recursive_add( + /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir(dest, a->name), + (LttvAttribute *)(a->value.dv_gobject)); + } + else { + g_assert(lttv_attribute_find(dest, a->name, a->type, &value)); + switch(a->type) { + case LTTV_INT: + *value.v_int += a->value.dv_int; + break; + case LTTV_UINT: + *value.v_uint += a->value.dv_uint; + break; + case LTTV_LONG: + *value.v_long += a->value.dv_long; + break; + case LTTV_ULONG: + *value.v_ulong += a->value.dv_ulong; + break; + case LTTV_FLOAT: + *value.v_float += a->value.dv_float; + break; + case LTTV_DOUBLE: + *value.v_double += a->value.dv_double; + break; + case LTTV_TIME: + *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time); + break; + case LTTV_POINTER: + break; + case LTTV_STRING: + break; + case LTTV_GOBJECT: + break; + case LTTV_NONE: + break; + } + } + } +} + + +static void +attribute_interface_init (gpointer g_iface, gpointer iface_data) +{ + LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface; + + klass->get_number = (unsigned int (*) (LttvIAttribute *self)) + lttv_attribute_get_number; + + klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous)) + lttv_attribute_named; + + klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i, + LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get; + + klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self, + LttvAttributeName name, LttvAttributeValue *v)) + lttv_attribute_get_by_name; + + klass->add = (LttvAttributeValue (*) (LttvIAttribute *self, + LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add; + + klass->remove = (void (*) (LttvIAttribute *self, unsigned i)) + lttv_attribute_remove; + + klass->remove_by_name = (void (*) (LttvIAttribute *self, + LttvAttributeName name)) lttv_attribute_remove_by_name; + + klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self, + LttvAttributeName name)) lttv_attribute_find_subdir; +} + + +static void +attribute_instance_init (GTypeInstance *instance, gpointer g_class) +{ + LttvAttribute *self = (LttvAttribute *)instance; + self->names = g_hash_table_new(g_direct_hash, g_direct_equal); + self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute)); +} + + +static void +attribute_finalize (LttvAttribute *self) +{ + g_hash_table_destroy(self->names); + g_critical("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)); +} + + +static void +attribute_class_init (LttvAttributeClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self))attribute_finalize; +} + +GType +lttv_attribute_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvAttributeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) attribute_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvAttribute), + 0, /* n_preallocs */ + (GInstanceInitFunc) attribute_instance_init /* instance_init */ + }; + + static const GInterfaceInfo iattribute_info = { + (GInterfaceInitFunc) attribute_interface_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info, + 0); + g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info); + } + return type; +} + + diff --git a/ltt/branches/poly/lttv/main/filter.c b/ltt/branches/poly/lttv/main/filter.c new file mode 100644 index 00000000..c63940ba --- /dev/null +++ b/ltt/branches/poly/lttv/main/filter.c @@ -0,0 +1,58 @@ + + consist in AND, OR and NOT nested expressions, forming a tree with + simple relations as leaves. The simple relations test is a field + in an event is equal, not equal, smaller, smaller or equal, larger, or + larger or equal to a specified value. */ + +typedef enum _lttv_expression_op +{ LTTV_FIELD_EQ, + LTTV_FIELD_NE, + LTTV_FIELD_LT, + LTTV_FIELD_LE, + LTTV_FIELD_GT, + LTTV_FIELD_GE +} lttv_expression_op; + +typedef _lttv_simple_expression +{ lttv_expression_op op; + char *field_name; + char *value; +} lttv_simple_expression; + +typedef _lttv_expression_type +{ LTTV_EXPRESSION, + LTTV_SIMPLE_EXPRESSION + +} +typedef struct _lttv_expression +{ bool or; + bool not; + bool simple_expression; + union + { lttv_expression *e; + lttv_field_relation *se; + } e; +} lttv_expression; + +read_token + +read_expression + ( read expr ) + simple expr [ op expr ] + +read_simple_expression + read_field_path [ rel value ] + +read_field_path + read_field_component [. field path] + +read_field_component + name [ \[ value \] ] + +data struct: +and/or(left/right) +not(child) +op(left/right) +path(component...) -> field + + diff --git a/ltt/branches/poly/lttv/main/hook.c b/ltt/branches/poly/lttv/main/hook.c new file mode 100644 index 00000000..8edbb2af --- /dev/null +++ b/ltt/branches/poly/lttv/main/hook.c @@ -0,0 +1,212 @@ + +#include + + +typedef struct _LttvHookClosure { + LttvHook hook; + void *hook_data; +} LttvHookClosure; + + +LttvHooks *lttv_hooks_new() +{ + return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure)); +} + + +void lttv_hooks_destroy(LttvHooks *h) +{ + g_critical("lttv_hooks_destroy()"); + g_array_free(h, TRUE); +} + + +void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data) +{ + LttvHookClosure c; + + if(h == NULL)g_error("Null hook added"); + + c.hook = f; + c.hook_data = hook_data; + g_array_append_val(h,c); +} + + +void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list) +{ + guint i; + + if(list == NULL) return; + for(i = 0 ; i < list->len; i++) { + g_array_append_val(h,g_array_index(list, LttvHookClosure, i)); + } +} + + +void *lttv_hooks_remove(LttvHooks *h, LttvHook f) +{ + unsigned i; + + void *hook_data; + + LttvHookClosure *c; + + for(i = 0 ; i < h->len ; i++) { + c = &g_array_index(h, LttvHookClosure, i); + if(c->hook == f) { + hook_data = c->hook_data; + lttv_hooks_remove_by_position(h, i); + return hook_data; + } + } + return NULL; +} + + +void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data) +{ + unsigned i; + + LttvHookClosure *c; + + for(i = 0 ; i < h->len ; i++) { + c = &g_array_index(h, LttvHookClosure, i); + if(c->hook == f && c->hook_data == hook_data) { + lttv_hooks_remove_by_position(h, i); + return; + } + } +} + + +void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list) +{ + guint i, j; + + LttvHookClosure *c, *c_list; + + if(list == NULL) return; + for(i = 0, j = 0 ; i < h->len && j < list->len ;) { + c = &g_array_index(h, LttvHookClosure, i); + c_list = &g_array_index(list, LttvHookClosure, j); + if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) { + lttv_hooks_remove_by_position(h, i); + j++; + } + else i++; + } + + /* Normally the hooks in h are ordered as in list. If this is not the case, + try harder here. */ + + if(j < list->len) { + for(; j < list->len ; j++) { + c_list = &g_array_index(list, LttvHookClosure, j); + lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data); + } + } +} + + +unsigned lttv_hooks_number(LttvHooks *h) +{ + return h->len; +} + + +void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data) +{ + LttvHookClosure *c; + + c = &g_array_index(h, LttvHookClosure, i); + *f = c->hook; + *hook_data = c->hook_data; +} + + +void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i) +{ + g_array_remove_index(h, i); +} + + +gboolean lttv_hooks_call(LttvHooks *h, void *call_data) +{ + gboolean ret, sum_ret = FALSE; + + LttvHookClosure *c; + + guint i; + + if(h != NULL) { + for(i = 0 ; i < h->len ; i++) { + c = &g_array_index(h, LttvHookClosure, i); + ret = c->hook(c->hook_data,call_data); + sum_ret = sum_ret || ret; + } + } + return sum_ret; +} + + +gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data) +{ + LttvHookClosure *c; + + guint i; + + for(i = 0 ; i < h->len ; i++) { + c = &g_array_index(h, LttvHookClosure, i); + if(c->hook(c->hook_data,call_data)) return TRUE; + } + return FALSE; +} + + +LttvHooksById *lttv_hooks_by_id_new() +{ + return g_ptr_array_new(); +} + + +void lttv_hooks_by_id_destroy(LttvHooksById *h) +{ + guint i; + + for(i = 0 ; i < h->len ; i++) { + if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i])); + } + g_ptr_array_free(h, TRUE); +} + + +LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id) +{ + if(h->len <= id) g_ptr_array_set_size(h, id + 1); + if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new(); + return h->pdata[id]; +} + + +unsigned lttv_hooks_by_id_max_id(LttvHooksById *h) +{ + return h->len; +} + + +LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id) +{ + if(id < h->len) return h->pdata[id]; + return NULL; +} + + +void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id) +{ + if(id < h->len && h->pdata[id] != NULL) { + lttv_hooks_destroy((LttvHooks *)h->pdata[id]); + h->pdata[id] = NULL; + } +} + diff --git a/ltt/branches/poly/lttv/main/iattribute.c b/ltt/branches/poly/lttv/main/iattribute.c new file mode 100644 index 00000000..e39d7e08 --- /dev/null +++ b/ltt/branches/poly/lttv/main/iattribute.c @@ -0,0 +1,260 @@ + +#include + +static void +lttv_iattribute_base_init (gpointer klass) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + initialized = TRUE; + } +} + + +GType +lttv_iattribute_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvIAttributeClass), + lttv_iattribute_base_init, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + type = g_type_register_static (G_TYPE_INTERFACE, "LttvIAttribute", + &info, 0); + } + return type; +} + + +unsigned int lttv_iattribute_get_number(LttvIAttribute *self) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->get_number (self); +} + + +gboolean lttv_iattribute_named(LttvIAttribute *self, gboolean *homogeneous) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->named (self, homogeneous); +} + + +LttvAttributeType lttv_iattribute_get(LttvIAttribute *self, unsigned i, + LttvAttributeName *name, LttvAttributeValue *v) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->get (self, i, name, v); +} + + +LttvAttributeType lttv_iattribute_get_by_name(LttvIAttribute *self, + LttvAttributeName name, LttvAttributeValue *v) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->get_by_name (self, name, v); +} + + +LttvAttributeValue lttv_iattribute_add(LttvIAttribute *self, + LttvAttributeName name, LttvAttributeType t) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->add (self, name, t); +} + + +void lttv_iattribute_remove(LttvIAttribute *self, unsigned i) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->remove (self, i); +} + + +void lttv_iattribute_remove_by_name(LttvIAttribute *self, + LttvAttributeName name) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->remove_by_name (self, name); +} + +LttvIAttribute* lttv_iattribute_find_subdir(LttvIAttribute *self, + LttvAttributeName name) +{ + return LTTV_IATTRIBUTE_GET_CLASS (self)->find_subdir (self, name); +} + + +/* Find the named attribute in the table, which must be of the specified type. + If it does not exist, it is created with a default value of 0 (NULL for + pointer types). Since the address of the value is obtained, it may be + changed easily afterwards. The function returns false when the attribute + exists but is of incorrect type. */ + +gboolean lttv_iattribute_find(LttvIAttribute *self, LttvAttributeName name, + LttvAttributeType t, LttvAttributeValue *v) +{ + LttvAttributeType found_type; + + found_type = lttv_iattribute_get_by_name(self, name, v); + if(found_type == t) return TRUE; + + if(found_type == LTTV_NONE) { + *v = lttv_iattribute_add(self, name, t); + return TRUE; + } + + return FALSE; +} + + +/* Trees of attribute tables may be accessed using a hierarchical path with + components separated by /, like in filesystems */ + +gboolean lttv_iattribute_find_by_path(LttvIAttribute *self, char *path, + LttvAttributeType t, LttvAttributeValue *v) +{ + LttvIAttribute *node = self; + + LttvAttributeType found_type; + + LttvAttributeName name; + + gchar **components, **cursor; + + components = g_strsplit(path, "\"", G_MAXINT); + + if(components == NULL || *components == NULL) { + g_strfreev(components); + return FALSE; + } + + for(cursor = components;;) { + name = g_quark_from_string(*cursor); + cursor++; + + if(*cursor == NULL) { + g_strfreev(components); + return lttv_iattribute_find(node, name, t, v); + } + else { + found_type = lttv_iattribute_get_by_name(node, name, v); + if(found_type == LTTV_NONE) { + node = lttv_iattribute_find_subdir(node, name); + } + else if(found_type == LTTV_GOBJECT && + LTTV_IS_IATTRIBUTE(*(v->v_gobject))) { + node = LTTV_IATTRIBUTE(*(v->v_gobject)); + } + else { + g_strfreev(components); + return FALSE; + } + } + } +} + +/* Shallow and deep copies */ + +LttvIAttribute *lttv_iattribute_shallow_copy(LttvIAttribute *self) +{ + LttvIAttribute *copy; + + LttvAttributeType t; + + LttvAttributeValue v, v_copy; + + LttvAttributeName name; + + int i; + + int nb_attributes = lttv_iattribute_get_number(self); + + copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self),NULL)); + + for(i = 0 ; i < nb_attributes ; i++) { + t = lttv_iattribute_get(self, i, &name, &v); + v_copy = lttv_iattribute_add(copy, name, t); + lttv_iattribute_copy_value(t, v_copy, v); + } +} + +LttvIAttribute *lttv_iattribute_deep_copy(LttvIAttribute *self) +{ + LttvIAttribute *copy, *child; + + LttvAttributeType t; + + LttvAttributeValue v, v_copy; + + LttvAttributeName name; + + int i; + + int nb_attributes = lttv_iattribute_get_number(self); + + copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self), NULL)); + + for(i = 0 ; i < nb_attributes ; i++) { + t = lttv_iattribute_get(self, i, &name, &v); + v_copy = lttv_iattribute_add(copy, name, t); + if(t == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(*(v.v_gobject))) { + child = LTTV_IATTRIBUTE(*(v.v_gobject)); + *(v_copy.v_gobject) = G_OBJECT(lttv_iattribute_deep_copy(child)); + } + else lttv_iattribute_copy_value(t, v_copy, v); + } +} + +void lttv_iattribute_copy_value(LttvAttributeType t, LttvAttributeValue dest, + LttvAttributeValue src) +{ + switch(t) { + case LTTV_INT: + *(dest.v_int) = *(src.v_int); + break; + + case LTTV_UINT: + *(dest.v_uint) = *(src.v_uint); + break; + + case LTTV_LONG: + *(dest.v_long) = *(src.v_long); + break; + + case LTTV_ULONG: + *(dest.v_ulong) = *(src.v_ulong); + break; + + case LTTV_FLOAT: + *(dest.v_float) = *(src.v_float); + break; + + case LTTV_DOUBLE: + *(dest.v_double) = *(src.v_double); + break; + + case LTTV_TIME: + *(dest.v_time) = *(src.v_time); + break; + + case LTTV_POINTER: + *(dest.v_pointer) = *(src.v_pointer); + break; + + case LTTV_STRING: + *(dest.v_string) = *(src.v_string); + break; + + case LTTV_GOBJECT: + *(dest.v_gobject) = *(src.v_gobject); + break; + + case LTTV_NONE: + break; + } +} + + diff --git a/ltt/branches/poly/lttv/main/module.c b/ltt/branches/poly/lttv/main/module.c new file mode 100644 index 00000000..e225992a --- /dev/null +++ b/ltt/branches/poly/lttv/main/module.c @@ -0,0 +1,302 @@ + +/* module.c : Implementation of the module loading/unloading mechanism. + * + */ + +#include + +#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; + guint ref_count; + guint load_count; + GPtrArray *dependents; +}; + + +/* Table of loaded modules and paths where to search for modules */ + +static GHashTable *modules = NULL; + +static GPtrArray *modulesPaths = NULL; + +static void lttv_module_unload_all(); + + +void lttv_module_init(int argc, char **argv) +{ + g_info("Init module.c"); + modules = g_hash_table_new(g_str_hash, g_str_equal); + modulesPaths = g_ptr_array_new(); +} + + +void lttv_module_destroy() +{ + int i; + + g_info("Destroy module.c"); + + /* Unload all modules */ + lttv_module_unload_all(); + + /* Free the modules paths pointer array as well as the elements */ + for(i = 0; i < modulesPaths->len ; i++) { + g_free(modulesPaths->pdata[i]); + } + g_ptr_array_free(modulesPaths,TRUE) ; + modulesPaths = NULL; + + /* destroy the hash table */ + g_hash_table_destroy(modules) ; + modules = NULL; +} + + +/* Add a new pathname to the modules loading search path */ + +void lttv_module_path_add(const char *name) +{ + g_info("Add module path %s", name); + g_ptr_array_add(modulesPaths,(char*)g_strdup(name)); +} + + +static LttvModule * +module_load(const char *name, int argc, char **argv) +{ + GModule *gm; + + LttvModule *m; + + int i; + + char *pathname; + + const char *module_name; + + LttvModuleInit init_function; + + g_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); + gm = g_module_open(pathname,0); + g_free(pathname); + + if(gm != NULL) break; + g_info("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"); + 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); + return NULL; + } + + /* Check if the module was already opened using the hopefully canonical name + returned by g_module_name. */ + + module_name = g_module_name(gm); + + m = g_hash_table_lookup(modules, module_name); + + if(m == NULL) { + g_info("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. */ + + m = g_new(LttvModule, 1); + m->module = gm; + m->ref_count = 0; + m->load_count = 0; + m->dependents = g_ptr_array_new(); + g_hash_table_insert(modules, (gpointer)module_name, m); + + if(!g_module_symbol(gm, "init", (gpointer)&init_function)) { + g_warning("module %s (%s) has no init function", name, pathname); + } + else init_function(m, argc, argv); + } + else { + + /* 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); + if(m->module != gm) g_error("Two gmodules with the same pathname"); + g_module_close(gm); + } + + m->ref_count++; + return m; +} + + +LttvModule * +lttv_module_load(const char *name, int argc, char **argv) +{ + g_info("Load module %s explicitly", name); + LttvModule *m = module_load(name, argc, argv); + if(m != NULL) m->load_count++; + return m; +} + + +LttvModule * +lttv_module_require(LttvModule *m, const char *name, int argc, char **argv) +{ + LttvModule *module; + + g_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); + return module; +} + + +static void module_unload(LttvModule *m) +{ + LttvModuleDestroy destroy_function; + + char *pathname; + + guint i, len; + + /* Decrement the reference count */ + + g_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); + return; + } + /* We really have to unload the module, first unload its dependents */ + + len = m->dependents->len; + g_info("Unload dependent modules"); + + for(i = 0 ; i < len ; i++) { + module_unload(m->dependents->pdata[i]); + } + + if(len != m->dependents->len) g_error("dependents list modified"); + + /* Unload the module itself */ + + g_info("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); + } + else destroy_function(); + + g_hash_table_remove(modules, g_module_name(m->module)); + g_ptr_array_free(m->dependents, TRUE); + g_module_close(m->module); + g_free(m); +} + + +void lttv_module_unload(LttvModule *m) +{ + g_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; + } + m->load_count--; + module_unload(m); +} + + +static void +list_modules(gpointer key, gpointer value, gpointer user_data) +{ + g_ptr_array_add((GPtrArray *)user_data, value); +} + + +LttvModule ** +lttv_module_list(guint *nb) +{ + GPtrArray *list = g_ptr_array_new(); + + LttvModule **array; + + g_hash_table_foreach(modules, list_modules, list); + *nb = list->len; + array = (LttvModule **)list->pdata; + g_ptr_array_free(list, FALSE); + return array; +} + + +LttvModule ** +lttv_module_info(LttvModule *m, const char **name, + guint *ref_count, guint *load_count, guint *nb_dependents) +{ + guint i, len = m->dependents->len; + + LttvModule **array = g_new(LttvModule *, len); + + *name = g_module_name(m->module); + *ref_count = m->ref_count; + *load_count = m->load_count; + *nb_dependents = len; + for(i = 0 ; i < len ; i++) array[i] = m->dependents->pdata[i]; + return array; +} + +char * +lttv_module_name(LttvModule *m) +{ + return g_module_name(m->module); +} + +static void +list_independent(gpointer key, gpointer value, gpointer user_data) +{ + LttvModule *m = (LttvModule *)value; + + if(m->load_count > 0) g_ptr_array_add((GPtrArray *)user_data, m); +} + + +void +lttv_module_unload_all() +{ + guint i; + + LttvModule *m; + + GPtrArray *independent_modules = g_ptr_array_new(); + + g_hash_table_foreach(modules, list_independent, independent_modules); + + for(i = 0 ; i < independent_modules->len ; i++) { + m = (LttvModule *)independent_modules->pdata[i]; + while(m->load_count > 0) lttv_module_unload(m); + } + + g_ptr_array_free(independent_modules, TRUE); + if(g_hash_table_size(modules) != 0) g_warning("cannot unload all modules"); +} diff --git a/ltt/branches/poly/lttv/main/processTrace.c b/ltt/branches/poly/lttv/main/processTrace.c new file mode 100644 index 00000000..4a290dd0 --- /dev/null +++ b/ltt/branches/poly/lttv/main/processTrace.c @@ -0,0 +1,812 @@ + +#include +#include +#include +#include +#include + +void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts) +{ + LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts); +} + + +void lttv_context_fini(LttvTracesetContext *self) +{ + LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self); +} + + +LttvTracesetContext * +lttv_context_new_traceset_context(LttvTracesetContext *self) +{ + return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self); +} + + + + +LttvTraceContext * +lttv_context_new_trace_context(LttvTracesetContext *self) +{ + return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); +} + + +LttvTracefileContext * +lttv_context_new_tracefile_context(LttvTracesetContext *self) +{ + return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self); +} + +/**************************************************************************** + * lttv_traceset_context_compute_time_span + * + * Keep the Time_Span is sync with on the fly addition and removal of traces + * in a trace set. It must be called each time a trace is added/removed from + * the traceset. It could be more efficient to call it only once a bunch + * of traces are loaded, but the calculation is not long, so it's not + * critical. + * + * Author : Xang Xiu Yang + * Imported from gtkTraceSet.c by Mathieu Desnoyers + ***************************************************************************/ +static void lttv_traceset_context_compute_time_span( + LttvTracesetContext *self, + TimeInterval *Time_Span) +{ + LttvTraceset * traceset = self->ts; + int numTraces = lttv_traceset_number(traceset); + int i; + LttTime s, e; + LttvTraceContext *tc; + LttTrace * trace; + + for(i=0; itraces[i]; + trace = tc->t; + + ltt_trace_time_span_get(trace, &s, &e); + + if(i==0){ + Time_Span->startTime = s; + Time_Span->endTime = e; + }else{ + if(s.tv_sec < Time_Span->startTime.tv_sec || + (s.tv_sec == Time_Span->startTime.tv_sec + && s.tv_nsec < Time_Span->startTime.tv_nsec)) + Time_Span->startTime = s; + if(e.tv_sec > Time_Span->endTime.tv_sec || + (e.tv_sec == Time_Span->endTime.tv_sec && + e.tv_nsec > Time_Span->endTime.tv_nsec)) + Time_Span->endTime = e; + } + } +} + + +static void +init(LttvTracesetContext *self, LttvTraceset *ts) +{ + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTracefileContext *tfc; + + LttTime null_time = {0, 0}; + + nb_trace = lttv_traceset_number(ts); + self->ts = ts; + self->traces = g_new(LttvTraceContext *, nb_trace); + self->before = lttv_hooks_new(); + self->after = lttv_hooks_new(); + self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + self->ts_a = lttv_traceset_attribute(ts); + for(i = 0 ; i < nb_trace ; i++) { + tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); + self->traces[i] = tc; + + tc->ts_context = self; + tc->index = i; + tc->vt = lttv_traceset_get(ts, i); + tc->t = lttv_trace(tc->vt); + tc->check = lttv_hooks_new(); + tc->before = lttv_hooks_new(); + tc->after = lttv_hooks_new(); + tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + tc->t_a = lttv_trace_attribute(tc->vt); + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + tc->control_tracefiles = g_new(LttvTracefileContext *, nb_control); + tc->per_cpu_tracefiles = g_new(LttvTracefileContext *, nb_per_cpu); + + for(j = 0 ; j < nb_tracefile ; j++) { + tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self); + if(j < nb_control) { + tc->control_tracefiles[j] = tfc; + tfc->control = TRUE; + tfc->index = j; + tfc->tf = ltt_trace_control_tracefile_get(tc->t, j); + } + else { + tc->per_cpu_tracefiles[j - nb_control] = tfc; + tfc->control = FALSE; + tfc->index = j - nb_control; + tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control); + } + tfc->t_context = tc; + tfc->check = lttv_hooks_new(); + tfc->before = lttv_hooks_new(); + tfc->after = lttv_hooks_new(); + tfc->check_event = lttv_hooks_new(); + tfc->before_event = lttv_hooks_new(); + tfc->before_event_by_id = lttv_hooks_by_id_new(); + tfc->after_event = lttv_hooks_new(); + tfc->after_event_by_id = lttv_hooks_by_id_new(); + tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + } + } + lttv_process_traceset_seek_time(self, null_time); + /*CHECK why dynamically allocate the time span... and the casing is wroNg*/ + self->Time_Span = g_new(TimeInterval,1); + lttv_traceset_context_compute_time_span(self, self->Time_Span); +} + + +void fini(LttvTracesetContext *self) +{ + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTracefileContext *tfc; + + LttvTraceset *ts = self->ts; + + g_free(self->Time_Span); + + lttv_hooks_destroy(self->before); + lttv_hooks_destroy(self->after); + //FIXME : segfault + g_object_unref(self->a); + + nb_trace = lttv_traceset_number(ts); + + for(i = 0 ; i < nb_trace ; i++) { + tc = self->traces[i]; + + lttv_hooks_destroy(tc->check); + lttv_hooks_destroy(tc->before); + lttv_hooks_destroy(tc->after); + g_object_unref(tc->a); + + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) tfc = tc->control_tracefiles[j]; + else tfc = tc->per_cpu_tracefiles[j - nb_control]; + + lttv_hooks_destroy(tfc->check); + lttv_hooks_destroy(tfc->before); + lttv_hooks_destroy(tfc->after); + lttv_hooks_destroy(tfc->check_event); + lttv_hooks_destroy(tfc->before_event); + lttv_hooks_by_id_destroy(tfc->before_event_by_id); + lttv_hooks_destroy(tfc->after_event); + lttv_hooks_by_id_destroy(tfc->after_event_by_id); + g_object_unref(tfc->a); + g_object_unref(tfc); + } + g_free(tc->control_tracefiles); + g_free(tc->per_cpu_tracefiles); + g_object_unref(tc); + } + g_free(self->traces); +} + + +void lttv_traceset_context_add_hooks(LttvTracesetContext *self, + LttvHooks *before_traceset, + LttvHooks *after_traceset, + LttvHooks *check_trace, + LttvHooks *before_trace, + LttvHooks *after_trace, + LttvHooks *check_tracefile, + LttvHooks *before_tracefile, + LttvHooks *after_tracefile, + LttvHooks *check_event, + LttvHooks *before_event, + LttvHooks *after_event) +{ + LttvTraceset *ts = self->ts; + + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTracefileContext *tfc; + + void *hook_data; + + lttv_hooks_add_list(self->before, before_traceset); + lttv_hooks_add_list(self->after, after_traceset); + nb_trace = lttv_traceset_number(ts); + + for(i = 0 ; i < nb_trace ; i++) { + tc = self->traces[i]; + lttv_hooks_add_list(tc->check, check_trace); + lttv_hooks_add_list(tc->before, before_trace); + lttv_hooks_add_list(tc->after, after_trace); + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfc = tc->control_tracefiles[j]; + } + else { + tfc = tc->per_cpu_tracefiles[j-nb_control]; + } + lttv_hooks_add_list(tfc->check, check_tracefile); + lttv_hooks_add_list(tfc->before, before_tracefile); + lttv_hooks_add_list(tfc->after, after_tracefile); + lttv_hooks_add_list(tfc->check_event, check_event); + lttv_hooks_add_list(tfc->before_event, before_event); + lttv_hooks_add_list(tfc->after_event, after_event); + } + } +} + + +void lttv_traceset_context_remove_hooks(LttvTracesetContext *self, + LttvHooks *before_traceset, + LttvHooks *after_traceset, + LttvHooks *check_trace, + LttvHooks *before_trace, + LttvHooks *after_trace, + LttvHooks *check_tracefile, + LttvHooks *before_tracefile, + LttvHooks *after_tracefile, + LttvHooks *check_event, + LttvHooks *before_event, + LttvHooks *after_event) +{ + LttvTraceset *ts = self->ts; + + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTracefileContext *tfc; + + void *hook_data; + + lttv_hooks_remove_list(self->before, before_traceset); + lttv_hooks_remove_list(self->after, after_traceset); + nb_trace = lttv_traceset_number(ts); + + for(i = 0 ; i < nb_trace ; i++) { + tc = self->traces[i]; + lttv_hooks_remove_list(tc->check, check_trace); + lttv_hooks_remove_list(tc->before, before_trace); + lttv_hooks_remove_list(tc->after, after_trace); + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfc = tc->control_tracefiles[j]; + } + else { + tfc = tc->per_cpu_tracefiles[j-nb_control]; + } + lttv_hooks_remove_list(tfc->check, check_tracefile); + lttv_hooks_remove_list(tfc->before, before_tracefile); + lttv_hooks_remove_list(tfc->after, after_tracefile); + lttv_hooks_remove_list(tfc->check_event, check_event); + lttv_hooks_remove_list(tfc->before_event, before_event); + lttv_hooks_remove_list(tfc->after_event, after_event); + } + } +} + +void lttv_trace_context_add_hooks(LttvTraceContext *tc, + LttvHooks *check_trace, + LttvHooks *before_trace, + LttvHooks *after_trace) +{ + lttv_hooks_add_list(tc->check, check_trace); + lttv_hooks_add_list(tc->before, before_trace); + lttv_hooks_add_list(tc->after, after_trace); +} + +void lttv_trace_context_remove_hooks(LttvTraceContext *tc, + LttvHooks *check_trace, + LttvHooks *before_trace, + LttvHooks *after_trace) +{ + lttv_hooks_remove_list(tc->check, check_trace); + lttv_hooks_remove_list(tc->before, before_trace); + lttv_hooks_remove_list(tc->after, after_trace); +} + +void lttv_tracefile_context_add_hooks(LttvTracefileContext *tfc, + LttvHooks *check_tracefile, + LttvHooks *before_tracefile, + LttvHooks *after_tracefile, + LttvHooks *check_event, + LttvHooks *before_event, + LttvHooks *after_event) +{ + lttv_hooks_add_list(tfc->check, check_tracefile); + lttv_hooks_add_list(tfc->before, before_tracefile); + lttv_hooks_add_list(tfc->after, after_tracefile); + lttv_hooks_add_list(tfc->check_event, check_event); + lttv_hooks_add_list(tfc->before_event, before_event); + lttv_hooks_add_list(tfc->after_event, after_event); +} + +void lttv_tracefile_context_remove_hooks(LttvTracefileContext *tfc, + LttvHooks *check_tracefile, + LttvHooks *before_tracefile, + LttvHooks *after_tracefile, + LttvHooks *check_event, + LttvHooks *before_event, + LttvHooks *after_event) +{ + lttv_hooks_remove_list(tfc->check, check_tracefile); + lttv_hooks_remove_list(tfc->before, before_tracefile); + lttv_hooks_remove_list(tfc->after, after_tracefile); + lttv_hooks_remove_list(tfc->check_event, check_event); + lttv_hooks_remove_list(tfc->before_event, before_event); + lttv_hooks_remove_list(tfc->after_event, after_event); +} + +void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc, + unsigned i, + LttvHooks *before_event_by_id, + LttvHooks *after_event_by_id) +{ + LttvHooks * h; + h = lttv_hooks_by_id_find(tfc->before_event_by_id, i); + lttv_hooks_add_list(h, before_event_by_id); + h = lttv_hooks_by_id_find(tfc->after_event_by_id, i); + lttv_hooks_add_list(h, after_event_by_id); +} + +void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc, + unsigned i) +{ + lttv_hooks_by_id_remove(tfc->before_event_by_id, i); + lttv_hooks_by_id_remove(tfc->after_event_by_id, i); +} + +static LttvTracesetContext * +new_traceset_context(LttvTracesetContext *self) +{ + return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL); +} + + +static LttvTraceContext * +new_trace_context(LttvTracesetContext *self) +{ + return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL); +} + + +static LttvTracefileContext * +new_tracefile_context(LttvTracesetContext *self) +{ + return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL); +} + + +static void +traceset_context_instance_init (GTypeInstance *instance, gpointer g_class) +{ + /* Be careful of anything which would not work well with shallow copies */ +} + + +static void +traceset_context_finalize (LttvTracesetContext *self) +{ + G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE))) + ->finalize(G_OBJECT(self)); +} + + +static void +traceset_context_class_init (LttvTracesetContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize; + klass->init = init; + klass->fini = fini; + klass->new_traceset_context = new_traceset_context; + klass->new_trace_context = new_trace_context; + klass->new_tracefile_context = new_tracefile_context; +} + + +GType +lttv_traceset_context_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracesetContextClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) traceset_context_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracesetContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) traceset_context_instance_init /* instance_init */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType", + &info, 0); + } + return type; +} + + +static void +trace_context_instance_init (GTypeInstance *instance, gpointer g_class) +{ + /* Be careful of anything which would not work well with shallow copies */ +} + + +static void +trace_context_finalize (LttvTraceContext *self) +{ + G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))-> + finalize(G_OBJECT(self)); +} + + +static void +trace_context_class_init (LttvTraceContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize; +} + + +GType +lttv_trace_context_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTraceContextClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) trace_context_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTraceContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) trace_context_instance_init /* instance_init */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType", + &info, 0); + } + return type; +} + + +static void +tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class) +{ + /* Be careful of anything which would not work well with shallow copies */ +} + + +static void +tracefile_context_finalize (LttvTracefileContext *self) +{ + G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE))) + ->finalize(G_OBJECT(self)); +} + + +static void +tracefile_context_class_init (LttvTracefileContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize; +} + + +GType +lttv_tracefile_context_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracefileContextClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) tracefile_context_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracefileContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) tracefile_context_instance_init /* instance_init */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType", + &info, 0); + } + return type; +} + + +gint compare_tracefile(gconstpointer a, gconstpointer b) +{ + return ltt_time_compare(*((LttTime *)a), *((LttTime *)b)); +} + + +gboolean get_first(gpointer key, gpointer value, gpointer user_data) { + *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value; + return TRUE; +} + + +void lttv_process_traceset(LttvTracesetContext *self, LttTime end, + unsigned maxNumEvents) +{ + 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; + + 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); + + 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); + 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]; + } + + 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); + } + } + } + } + } + } + + /* Get the next event from the pqueue, call its hooks, + reinsert in the pqueue the following event from the same tracefile + unless the tracefile is finished or the event is later than the + start time. */ + + while(TRUE) { + tfc = NULL; + g_tree_foreach(pqueue, get_first, &tfc); + if(tfc == NULL) break; + + /* 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; + } + } + previous_timestamp = tfc->timestamp; + + + /* Get the tracefile with an event for the smallest time found. If two + or more tracefiles have events for the same time, hope that lookup + and remove are consistent. */ + + tfc = g_tree_lookup(pqueue, &(tfc->timestamp)); + g_tree_remove(pqueue, &(tfc->timestamp)); + + if(!lttv_hooks_call(tfc->check_event, tfc)) { + id = ltt_event_eventtype_id(tfc->e); + lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc); + lttv_hooks_call(tfc->before_event, tfc); + lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc); + lttv_hooks_call(tfc->after_event, tfc); + } + + event = ltt_tracefile_read(tfc->tf); + if(event != NULL) { + tfc->e = event; + tfc->timestamp = ltt_event_time(event); + 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); + } + } + + /* Call all the after_tracefile, after_trace and after_traceset hooks. */ + + for(i = 0, j = 0 ; i < traces->len ; i++) { + tc = traces->pdata[i]; + while(j < tracefiles->len) { + tfc = tracefiles->pdata[j]; + + if(tfc->t_context == tc) { + lttv_hooks_call(tfc->after, tfc); + j++; + } + else break; + } + lttv_hooks_call(tc->after, tc); + } + + g_assert(j == tracefiles->len); + lttv_hooks_call(self->after, self); + + /* Free the traces, tracefiles and pqueue */ + + g_ptr_array_free(tracefiles, TRUE); + g_ptr_array_free(traces, TRUE); + g_tree_destroy(pqueue); +} + + +void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileContext *tfc; + + LttEvent *event; + + nb_control = ltt_trace_control_tracefile_number(self->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->t); + nb_tracefile = nb_control + nb_per_cpu; + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) tfc = self->control_tracefiles[i]; + else tfc = self->per_cpu_tracefiles[i - nb_control]; + + ltt_tracefile_seek_time(tfc->tf, start); + event = ltt_tracefile_read(tfc->tf); + tfc->e = event; + if(event != NULL) tfc->timestamp = ltt_event_time(event); + } +} + + +void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start) +{ + guint i, nb_trace; + + LttvTraceContext *tc; + + nb_trace = lttv_traceset_number(self->ts); + for(i = 0 ; i < nb_trace ; i++) { + tc = self->traces[i]; + lttv_process_trace_seek_time(tc, start); + } +} + + +static LttField * +find_field(LttEventType *et, const char *field) +{ + LttType *t; + + LttField *f; + + guint i, nb; + + char *name; + + if(field == NULL) return NULL; + + f = ltt_eventtype_field(et); + t = ltt_eventtype_type(et); + g_assert(ltt_type_class(t) == LTT_STRUCT); + nb = ltt_type_member_number(t); + for(i = 0 ; i < nb ; i++) { + ltt_type_member_type(t, i, &name); + if(strcmp(name, field) == 0) break; + } + g_assert(i < nb); + return ltt_field_member(f, i); +} + + +void +lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type, + char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th) +{ + LttFacility *f; + + LttEventType *et; + + guint nb, pos, i; + + char *name; + + nb = ltt_trace_facility_find(t, facility, &pos); + if(nb < 1) g_error("No %s facility", facility); + f = ltt_trace_facility_get(t, pos); + et = ltt_facility_eventtype_get_by_name(f, event_type); + if(et == NULL) g_error("Event %s does not exist", event_type); + + th->h = h; + th->id = ltt_eventtype_id(et); + th->f1 = find_field(et, field1); + th->f2 = find_field(et, field2); + th->f3 = find_field(et, field3); +} + + diff --git a/ltt/branches/poly/lttv/main/state.c b/ltt/branches/poly/lttv/main/state.c new file mode 100644 index 00000000..dbdb11ce --- /dev/null +++ b/ltt/branches/poly/lttv/main/state.c @@ -0,0 +1,1198 @@ + +#include +#include +#include +#include +#include + +LttvExecutionMode + LTTV_STATE_MODE_UNKNOWN, + LTTV_STATE_USER_MODE, + LTTV_STATE_SYSCALL, + LTTV_STATE_TRAP, + LTTV_STATE_IRQ; + +LttvExecutionSubmode + LTTV_STATE_SUBMODE_UNKNOWN, + LTTV_STATE_SUBMODE_NONE; + +LttvProcessStatus + LTTV_STATE_UNNAMED, + LTTV_STATE_WAIT_FORK, + LTTV_STATE_WAIT_CPU, + LTTV_STATE_EXIT, + LTTV_STATE_WAIT, + LTTV_STATE_RUN; + +static GQuark + LTTV_STATE_TRACEFILES, + LTTV_STATE_PROCESSES, + LTTV_STATE_PROCESS, + LTTV_STATE_EVENT, + LTTV_STATE_SAVED_STATES, + LTTV_STATE_TIME, + LTTV_STATE_HOOKS; + + +static void fill_name_tables(LttvTraceState *tcs); + +static void free_name_tables(LttvTraceState *tcs); + +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) +{ + LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container); +} + + +void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) +{ + LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); +} + + +void lttv_state_saved_state_free(LttvTraceState *self, + LttvAttribute *container) +{ + LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); +} + + +static void +restore_init_state(LttvTraceState *self) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileState *tfcs; + + 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->nb_event = 0; + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) { + tfcs = LTTV_TRACEFILE_STATE(self->parent.control_tracefiles[i]); + } + else { + tfcs = LTTV_TRACEFILE_STATE(self->parent.per_cpu_tracefiles[i - nb_control]); + } + + tfcs->parent.timestamp = null_time; + tfcs->saved_position = 0; + tfcs->process = create_process(tfcs, NULL,0); + } +} + + +static void +init(LttvTracesetState *self, LttvTraceset *ts) +{ + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTraceState *tcs; + + LttvTracefileState *tfcs; + + LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> + init((LttvTracesetContext *)self, ts); + + nb_trace = lttv_traceset_number(ts); + for(i = 0 ; i < nb_trace ; i++) { + tc = self->parent.traces[i]; + tcs = (LttvTraceState *)tc; + tcs->save_interval = 100000; + fill_name_tables(tcs); + + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfcs = LTTV_TRACEFILE_STATE(tc->control_tracefiles[j]); + } + else { + tfcs = LTTV_TRACEFILE_STATE(tc->per_cpu_tracefiles[j - nb_control]); + } + tfcs->cpu_name= g_quark_from_string(ltt_tracefile_name(tfcs->parent.tf)); + } + tcs->processes = NULL; + restore_init_state(tcs); + } +} + + +static void +fini(LttvTracesetState *self) +{ + guint i, j, nb_trace, nb_tracefile; + + LttvTraceState *tcs; + + LttvTracefileState *tfcs; + + nb_trace = lttv_traceset_number(LTTV_TRACESET_CONTEXT(self)->ts); + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceState *)(LTTV_TRACESET_CONTEXT(self)->traces[i]); + lttv_state_free_process_table(tcs->processes); + tcs->processes = NULL; + free_name_tables(tcs); + } + LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> + fini((LttvTracesetContext *)self); +} + + +static LttvTracesetContext * +new_traceset_context(LttvTracesetContext *self) +{ + return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE, NULL)); +} + + +static LttvTraceContext * +new_trace_context(LttvTracesetContext *self) +{ + return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE, NULL)); +} + + +static LttvTracefileContext * +new_tracefile_context(LttvTracesetContext *self) +{ + return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE, NULL)); +} + + +static void copy_process_state(gpointer key, gpointer value,gpointer user_data) +{ + LttvProcessState *process, *new_process; + + GHashTable *new_processes = (GHashTable *)user_data; + + guint i; + + process = (LttvProcessState *)value; + new_process = g_new(LttvProcessState, 1); + *new_process = *process; + new_process->execution_stack = g_array_new(FALSE, FALSE, + sizeof(LttvExecutionState)); + g_array_set_size(new_process->execution_stack,process->execution_stack->len); + for(i = 0 ; i < process->execution_stack->len; i++) { + g_array_index(new_process->execution_stack, LttvExecutionState, i) = + g_array_index(process->execution_stack, LttvExecutionState, i); + } + 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); +} + + +static GHashTable *lttv_state_copy_process_table(GHashTable *processes) +{ + GHashTable *new_processes = g_hash_table_new(g_direct_hash, g_direct_equal); + + g_hash_table_foreach(processes, copy_process_state, new_processes); + return new_processes; +} + + +/* The saved state for each trace contains a member "processes", which + stores a copy of the process table, and a member "tracefiles" with + one entry per tracefile. Each tracefile has a "process" member pointing + to the current process and a "position" member storing the tracefile + position (needed to seek to the current "next" event. */ + +static void state_save(LttvTraceState *self, LttvAttribute *container) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileState *tfcs; + + LttvAttribute *tracefiles_tree, *tracefile_tree; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + LttEventPosition *ep; + + tracefiles_tree = lttv_attribute_find_subdir(container, + LTTV_STATE_TRACEFILES); + + value = lttv_attribute_add(container, LTTV_STATE_PROCESSES, + LTTV_POINTER); + *(value.v_pointer) = lttv_state_copy_process_table(self->processes); + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) + tfcs = (LttvTracefileState *)self->parent.control_tracefiles[i]; + else tfcs = (LttvTracefileState *) + self->parent.per_cpu_tracefiles[i - nb_control]; + + tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + value = lttv_attribute_add(tracefiles_tree, i, + LTTV_GOBJECT); + *(value.v_gobject) = (GObject *)tracefile_tree; + value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS, + LTTV_UINT); + *(value.v_uint) = tfcs->process->pid; + value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT, + LTTV_POINTER); + if(tfcs->parent.e == NULL) *(value.v_pointer) = NULL; + else { + ep = ltt_event_position_new(); + ltt_event_position(tfcs->parent.e, ep); + *(value.v_pointer) = ep; + } + } +} + + +static void state_restore(LttvTraceState *self, LttvAttribute *container) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileState *tfcs; + + LttvAttribute *tracefiles_tree, *tracefile_tree; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + LttEventPosition *ep; + + tracefiles_tree = lttv_attribute_find_subdir(container, + LTTV_STATE_TRACEFILES); + + type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, + &value); + g_assert(type == LTTV_POINTER); + lttv_state_free_process_table(self->processes); + self->processes = lttv_state_copy_process_table(*(value.v_pointer)); + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) tfcs = (LttvTracefileState *) + self->parent.control_tracefiles[i]; + else tfcs = (LttvTracefileState *) + self->parent.per_cpu_tracefiles[i - nb_control]; + + type = lttv_attribute_get(tracefiles_tree, i, &name, &value); + g_assert(type == LTTV_GOBJECT); + tracefile_tree = *((LttvAttribute **)(value.v_gobject)); + + 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)); + type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, + &value); + g_assert(type == LTTV_POINTER); + if(*(value.v_pointer) == NULL) tfcs->parent.e = NULL; + else { + ep = *(value.v_pointer); + ltt_tracefile_seek_position(tfcs->parent.tf, ep); + tfcs->parent.e = ltt_tracefile_read(tfcs->parent.tf); + tfcs->parent.timestamp = ltt_event_time(tfcs->parent.e); + } + } +} + + +static void state_saved_free(LttvTraceState *self, LttvAttribute *container) +{ + guint i, nb_control, nb_per_cpu, nb_tracefile; + + LttvTracefileState *tfcs; + + LttvAttribute *tracefiles_tree, *tracefile_tree; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + LttEventPosition *ep; + + tracefiles_tree = lttv_attribute_find_subdir(container, + LTTV_STATE_TRACEFILES); + lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES); + + type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, + &value); + g_assert(type == LTTV_POINTER); + lttv_state_free_process_table(*(value.v_pointer)); + *(value.v_pointer) = NULL; + lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES); + + nb_control = ltt_trace_control_tracefile_number(self->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + + for(i = 0 ; i < nb_tracefile ; i++) { + if(i < nb_control) tfcs = (LttvTracefileState *) + self->parent.control_tracefiles[i]; + else tfcs = (LttvTracefileState *) + self->parent.per_cpu_tracefiles[i - nb_control]; + + type = lttv_attribute_get(tracefiles_tree, i, &name, &value); + g_assert(type == LTTV_GOBJECT); + tracefile_tree = *((LttvAttribute **)(value.v_gobject)); + + type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, + &value); + g_assert(type == LTTV_POINTER); + if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer)); + } + lttv_attribute_recursive_free(tracefiles_tree); +} + + +static void +fill_name_tables(LttvTraceState *tcs) +{ + int i, nb; + + char *f_name, *e_name; + + LttvTraceHook h; + + LttEventType *et; + + LttType *t; + + GString *fe_name = g_string_new(""); + + nb = ltt_trace_eventtype_number(tcs->parent.t); + tcs->eventtype_names = g_new(GQuark, nb); + for(i = 0 ; i < nb ; i++) { + et = ltt_trace_eventtype_get(tcs->parent.t, i); + e_name = ltt_eventtype_name(et); + f_name = ltt_facility_name(ltt_eventtype_facility(et)); + g_string_printf(fe_name, "%s.%s", f_name, e_name); + tcs->eventtype_names[i] = g_quark_from_string(fe_name->str); + } + + lttv_trace_find_hook(tcs->parent.t, "core", "syscall_entry", + "syscall_id", NULL, NULL, NULL, &h); + t = ltt_field_type(h.f1); + nb = ltt_type_element_number(t); + + /* CHECK syscalls should be an emun but currently are not! + tcs->syscall_names = g_new(GQuark, nb); + + for(i = 0 ; i < nb ; i++) { + tcs->syscall_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + } + */ + + tcs->syscall_names = g_new(GQuark, 256); + for(i = 0 ; i < 256 ; i++) { + g_string_printf(fe_name, "syscall %d", i); + tcs->syscall_names[i] = g_quark_from_string(fe_name->str); + } + + lttv_trace_find_hook(tcs->parent.t, "core", "trap_entry", + "trap_id", NULL, NULL, NULL, &h); + t = ltt_field_type(h.f1); + nb = ltt_type_element_number(t); + + /* + tcs->trap_names = g_new(GQuark, nb); + for(i = 0 ; i < nb ; i++) { + tcs->trap_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + } + */ + + tcs->trap_names = g_new(GQuark, 256); + for(i = 0 ; i < 256 ; i++) { + g_string_printf(fe_name, "trap %d", i); + tcs->trap_names[i] = g_quark_from_string(fe_name->str); + } + + lttv_trace_find_hook(tcs->parent.t, "core", "irq_entry", + "irq_id", NULL, NULL, NULL, &h); + t = ltt_field_type(h.f1); + nb = ltt_type_element_number(t); + + /* + tcs->irq_names = g_new(GQuark, nb); + for(i = 0 ; i < nb ; i++) { + tcs->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + } + */ + + tcs->irq_names = g_new(GQuark, 256); + for(i = 0 ; i < 256 ; i++) { + g_string_printf(fe_name, "irq %d", i); + tcs->irq_names[i] = g_quark_from_string(fe_name->str); + } + + g_string_free(fe_name, TRUE); +} + + +static void +free_name_tables(LttvTraceState *tcs) +{ + g_free(tcs->eventtype_names); + g_free(tcs->syscall_names); + g_free(tcs->trap_names); + g_free(tcs->irq_names); +} + + +static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, + guint state_id) +{ + LttvExecutionState *es; + + LttvProcessState *process = tfs->process; + + guint depth = process->execution_stack->len; + + g_array_set_size(process->execution_stack, depth + 1); + es = &g_array_index(process->execution_stack, LttvExecutionState, depth); + es->t = t; + es->n = state_id; + es->entry = es->change = tfs->parent.timestamp; + es->s = process->state->s; + process->state = es; +} + + +static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) +{ + LttvProcessState *process = tfs->process; + + guint depth = process->execution_stack->len - 1; + + if(process->state->t != t){ + g_warning("Different execution mode type (%d.%09d): ignore it\n", + tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + g_warning("process state has %s when pop_int is %s\n", + g_quark_to_string(process->state->t), + g_quark_to_string(t)); + g_warning("{ %u, %u, %s, %s }\n", + process->pid, + process->ppid, + g_quark_to_string(process->name), + g_quark_to_string(process->state->s)); + return; + } + + if(depth == 0){ + g_warning("Trying to pop last state on stack (%d.%09d): ignore it\n", + tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + return; + } + + g_array_remove_index(process->execution_stack, depth); + depth--; + process->state = &g_array_index(process->execution_stack, LttvExecutionState, + depth); + process->state->change = tfs->parent.timestamp; +} + + +static LttvProcessState *create_process(LttvTracefileState *tfs, + LttvProcessState *parent, guint pid) +{ + LttvProcessState *process = g_new(LttvProcessState, 1); + + LttvExecutionState *es; + + LttvTraceContext *tc; + + LttvTraceState *tcs; + + char buffer[128]; + + tcs = (LttvTraceState *)tc = tfs->parent.t_context; + + g_hash_table_insert(tcs->processes, GUINT_TO_POINTER(pid), process); + process->pid = pid; + + if(parent) { + process->ppid = parent->pid; + process->name = parent->name; + } + else { + process->ppid = 0; + process->name = LTTV_STATE_UNNAMED; + } + + process->creation_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->execution_stack = g_array_new(FALSE, FALSE, + sizeof(LttvExecutionState)); + g_array_set_size(process->execution_stack, 1); + es = process->state = &g_array_index(process->execution_stack, + LttvExecutionState, 0); + es->t = LTTV_STATE_USER_MODE; + es->n = LTTV_STATE_SUBMODE_NONE; + es->entry = tfs->parent.timestamp; + es->change = tfs->parent.timestamp; + es->s = LTTV_STATE_WAIT_FORK; + + return process; +} + + +LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs, + 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); + return process; +} + + +static void exit_process(LttvTracefileState *tfs, LttvProcessState *process) +{ + LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context); + + g_hash_table_remove(ts->processes, GUINT_TO_POINTER(process->pid)); + g_array_free(process->execution_stack, TRUE); + g_free(process); +} + + +static void free_process_state(gpointer key, gpointer value,gpointer user_data) +{ + g_array_free(((LttvProcessState *)value)->execution_stack, TRUE); + g_free(value); +} + + +static void lttv_state_free_process_table(GHashTable *processes) +{ + g_hash_table_foreach(processes, free_process_state, NULL); + g_hash_table_destroy(processes); +} + + +static gboolean syscall_entry(void *hook_data, void *call_data) +{ + LttField *f = ((LttvTraceHook *)hook_data)->f1; + + LttvTracefileState *s = (LttvTracefileState *)call_data; + + LttvExecutionSubmode submode; + + submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[ + ltt_event_get_unsigned(s->parent.e, f)]; + push_state(s, LTTV_STATE_SYSCALL, submode); + return FALSE; +} + + +static gboolean syscall_exit(void *hook_data, void *call_data) +{ + LttvTracefileState *s = (LttvTracefileState *)call_data; + + pop_state(s, LTTV_STATE_SYSCALL); + return FALSE; +} + + +static gboolean trap_entry(void *hook_data, void *call_data) +{ + LttField *f = ((LttvTraceHook *)hook_data)->f1; + + LttvTracefileState *s = (LttvTracefileState *)call_data; + + LttvExecutionSubmode submode; + + submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[ + ltt_event_get_unsigned(s->parent.e, f)]; + push_state(s, LTTV_STATE_TRAP, submode); + return FALSE; +} + + +static gboolean trap_exit(void *hook_data, void *call_data) +{ + LttvTracefileState *s = (LttvTracefileState *)call_data; + + pop_state(s, LTTV_STATE_TRAP); + return FALSE; +} + + +static gboolean irq_entry(void *hook_data, void *call_data) +{ + LttField *f = ((LttvTraceHook *)hook_data)->f1; + + LttvTracefileState *s = (LttvTracefileState *)call_data; + + LttvExecutionSubmode submode; + + submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[ + ltt_event_get_unsigned(s->parent.e, f)]; + + /* Do something with the info about being in user or system mode when int? */ + push_state(s, LTTV_STATE_IRQ, submode); + return FALSE; +} + + +static gboolean irq_exit(void *hook_data, void *call_data) +{ + LttvTracefileState *s = (LttvTracefileState *)call_data; + + pop_state(s, LTTV_STATE_IRQ); + return FALSE; +} + + +static gboolean schedchange(void *hook_data, void *call_data) +{ + LttvTraceHook *h = (LttvTraceHook *)hook_data; + + LttvTracefileState *s = (LttvTracefileState *)call_data; + + guint pid_in, pid_out, state_out; + + pid_in = ltt_event_get_unsigned(s->parent.e, h->f1); + pid_out = ltt_event_get_unsigned(s->parent.e, h->f2); + state_out = ltt_event_get_unsigned(s->parent.e, h->f3); + + if(s->process != NULL) { + + if(state_out == 0) s->process->state->s = LTTV_STATE_WAIT_CPU; + else if(s->process->state->s == LTTV_STATE_EXIT) + exit_process(s, s->process); + else s->process->state->s = LTTV_STATE_WAIT; + + if(s->process->pid == 0) + s->process->pid = pid_out; + + s->process->state->change = s->parent.timestamp; + } + s->process = lttv_state_find_process(s, pid_in); + s->process->state->s = LTTV_STATE_RUN; + s->process->state->change = s->parent.timestamp; + return FALSE; +} + + +static gboolean process_fork(void *hook_data, void *call_data) +{ + LttField *f = ((LttvTraceHook *)hook_data)->f1; + + LttvTracefileState *s = (LttvTracefileState *)call_data; + + guint child_pid; + + child_pid = ltt_event_get_unsigned(s->parent.e, f); + create_process(s, s->process, child_pid); + return FALSE; +} + + +static gboolean process_exit(void *hook_data, void *call_data) +{ + LttvTracefileState *s = (LttvTracefileState *)call_data; + + if(s->process != NULL) { + s->process->state->s = LTTV_STATE_EXIT; + } + return FALSE; +} + + +void lttv_state_add_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + GArray *hooks; + + LttvTraceHook hook; + + LttvAttributeValue val; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = (LttvTraceState *)self->parent.traces[i]; + + /* Find the eventtype id for the following events and register the + associated by id hooks. */ + + hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); + g_array_set_size(hooks, 9); + + lttv_trace_find_hook(ts->parent.t, "core","syscall_entry","syscall_id", + NULL, NULL, syscall_entry, &g_array_index(hooks, LttvTraceHook, 0)); + + lttv_trace_find_hook(ts->parent.t, "core", "syscall_exit", NULL, NULL, + NULL, syscall_exit, &g_array_index(hooks, LttvTraceHook, 1)); + + lttv_trace_find_hook(ts->parent.t, "core", "trap_entry", "trap_id", + NULL, NULL, trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); + + lttv_trace_find_hook(ts->parent.t, "core", "trap_exit", NULL, NULL, NULL, + trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); + + lttv_trace_find_hook(ts->parent.t, "core", "irq_entry", "irq_id", NULL, + NULL, irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); + + lttv_trace_find_hook(ts->parent.t, "core", "irq_exit", NULL, NULL, NULL, + irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); + + lttv_trace_find_hook(ts->parent.t, "core", "schedchange", "in", "out", + "out_state", schedchange, &g_array_index(hooks, LttvTraceHook, 6)); + + lttv_trace_find_hook(ts->parent.t, "core", "process_fork", "child_pid", + NULL, NULL, process_fork, &g_array_index(hooks, LttvTraceHook, 7)); + + lttv_trace_find_hook(ts->parent.t, "core", "process_exit", NULL, NULL, + NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 8)); + + /* Add these hooks to each before_event_by_id hooks list */ + + nb_control = ltt_trace_control_tracefile_number(ts->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); + } + else { + tfs = LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); + } + + for(k = 0 ; k < hooks->len ; k++) { + hook = g_array_index(hooks, LttvTraceHook, k); + lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, + hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k)); + } + } + lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); + *(val.v_pointer) = hooks; + } +} + + +void lttv_state_remove_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + GArray *hooks; + + LttvTraceHook hook; + + LttvAttributeValue val; + + 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); + hooks = *(val.v_pointer); + + /* Add these hooks to each before_event_by_id hooks list */ + + nb_control = ltt_trace_control_tracefile_number(ts->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); + } + else { + tfs = LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); + } + + for(k = 0 ; k < hooks->len ; k++) { + hook = g_array_index(hooks, LttvTraceHook, k); + lttv_hooks_remove_data( + lttv_hooks_by_id_find(tfs->parent.after_event_by_id, + hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k)); + } + } + g_array_free(hooks, TRUE); + } +} + + +static gboolean block_end(void *hook_data, void *call_data) +{ + LttvTracefileState *tfcs = (LttvTracefileState *)call_data; + + LttvTraceState *tcs = (LttvTraceState *)(tfcs->parent.t_context); + + LttEventPosition *ep = ltt_event_position_new(); + + guint nb_block, nb_event; + + LttTracefile *tf; + + LttvAttribute *saved_states_tree, *saved_state_tree; + + LttvAttributeValue value; + + ltt_event_position(tfcs->parent.e, ep); + + ltt_event_position_get(ep, &nb_block, &nb_event, &tf); + tcs->nb_event += nb_event - tfcs->saved_position; + tfcs->saved_position = 0; + if(tcs->nb_event >= tcs->save_interval) { + saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, + LTTV_STATE_SAVED_STATES); + saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + value = lttv_attribute_add(saved_states_tree, + lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT); + *(value.v_gobject) = (GObject *)saved_state_tree; + value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME); + *(value.v_time) = tfcs->parent.timestamp; + lttv_state_save(tcs, saved_state_tree); + tcs->nb_event = 0; + } + return FALSE; +} + + +void lttv_state_save_add_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + LttvTraceHook hook; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = (LttvTraceState *)self->parent.traces[i]; + lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, + NULL, NULL, block_end, &hook); + + nb_control = ltt_trace_control_tracefile_number(ts->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); + } + else { + tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); + } + + lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, + hook.id), hook.h, NULL); + } + } +} + + +void lttv_state_save_remove_event_hooks(LttvTracesetState *self) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceState *ts; + + LttvTracefileState *tfs; + + LttvTraceHook hook; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = LTTV_TRACE_STATE(self->parent.traces[i]); + lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, + NULL, NULL, block_end, &hook); + + nb_control = ltt_trace_control_tracefile_number(ts->parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); + } + else { + tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); + } + + lttv_hooks_remove_data(lttv_hooks_by_id_find( + tfs->parent.after_event_by_id, hook.id), hook.h, NULL); + } + } +} + + +void lttv_state_restore_closest_state(LttvTracesetState *self, LttTime t) +{ + LttvTraceset *traceset = self->parent.ts; + + guint i, j, nb_trace, nb_saved_state; + + int min_pos, mid_pos, max_pos; + + LttvTraceState *tcs; + + LttvAttributeValue value; + + LttvAttributeType type; + + LttvAttributeName name; + + LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceState *)self->parent.traces[i]; + + saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, + LTTV_STATE_SAVED_STATES); + min_pos = -1; + max_pos = lttv_attribute_get_number(saved_states_tree) - 1; + mid_pos = max_pos / 2; + while(min_pos < max_pos) { + type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value); + g_assert(type == LTTV_GOBJECT); + saved_state_tree = *((LttvAttribute **)(value.v_gobject)); + type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME, + &value); + g_assert(type == LTTV_TIME); + if(ltt_time_compare(*(value.v_time), t) < 0) { + min_pos = mid_pos; + closest_tree = saved_state_tree; + } + else max_pos = mid_pos - 1; + + mid_pos = (min_pos + max_pos + 1) / 2; + } + if(min_pos == -1) { + restore_init_state(tcs); + lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero); + } + else lttv_state_restore(tcs, closest_tree); + } +} + + +static void +traceset_state_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +traceset_state_finalize (LttvTracesetState *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +traceset_state_class_init (LttvTracesetContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize; + klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init; + klass->fini = (void (*)(LttvTracesetContext *self))fini; + klass->new_traceset_context = new_traceset_context; + klass->new_trace_context = new_trace_context; + klass->new_tracefile_context = new_tracefile_context; +} + + +GType +lttv_traceset_state_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracesetStateClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) traceset_state_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracesetContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) traceset_state_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType", + &info, 0); + } + return type; +} + + +static void +trace_state_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +trace_state_finalize (LttvTraceState *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +trace_state_class_init (LttvTraceStateClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize; + klass->state_save = state_save; + klass->state_restore = state_restore; + klass->state_saved_free = state_saved_free; +} + + +GType +lttv_trace_state_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTraceStateClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) trace_state_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTraceState), + 0, /* n_preallocs */ + (GInstanceInitFunc) trace_state_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE, + "LttvTraceStateType", &info, 0); + } + return type; +} + + +static void +tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +tracefile_state_finalize (LttvTracefileState *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +tracefile_state_class_init (LttvTracefileStateClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize; +} + + +GType +lttv_tracefile_state_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracefileStateClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) tracefile_state_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracefileState), + 0, /* n_preallocs */ + (GInstanceInitFunc) tracefile_state_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE, + "LttvTracefileStateType", &info, 0); + } + return type; +} + + +void lttv_state_init(int argc, char **argv) +{ + LTTV_STATE_UNNAMED = g_quark_from_string("unnamed"); + LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode"); + LTTV_STATE_USER_MODE = g_quark_from_string("user mode"); + LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork"); + LTTV_STATE_SYSCALL = g_quark_from_string("system call"); + LTTV_STATE_TRAP = g_quark_from_string("trap"); + LTTV_STATE_IRQ = g_quark_from_string("irq"); + LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode"); + LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)"); + LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu"); + LTTV_STATE_EXIT = g_quark_from_string("exiting"); + LTTV_STATE_WAIT = g_quark_from_string("wait for I/O"); + LTTV_STATE_RUN = g_quark_from_string("running"); + LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles"); + LTTV_STATE_PROCESSES = g_quark_from_string("processes"); + LTTV_STATE_PROCESS = g_quark_from_string("process"); + LTTV_STATE_EVENT = g_quark_from_string("event"); + LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states"); + LTTV_STATE_TIME = g_quark_from_string("time"); + LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks"); +} + +void lttv_state_destroy() +{ +} + + + + diff --git a/ltt/branches/poly/lttv/main/stats.c b/ltt/branches/poly/lttv/main/stats.c new file mode 100644 index 00000000..4265853d --- /dev/null +++ b/ltt/branches/poly/lttv/main/stats.c @@ -0,0 +1,1180 @@ + +#include +#include +#include +#include +#include + +#define BUF_SIZE 256 + +GQuark + LTTV_STATS_PROCESS_UNKNOWN, + LTTV_STATS_PROCESSES, + LTTV_STATS_CPU, + LTTV_STATS_MODE_TYPES, + LTTV_STATS_MODES, + LTTV_STATS_SUBMODES, + LTTV_STATS_EVENT_TYPES, + LTTV_STATS_CPU_TIME, + LTTV_STATS_ELAPSED_TIME, + LTTV_STATS_EVENTS, + LTTV_STATS_EVENTS_COUNT; + +static GQuark + LTTV_STATS_BEFORE_HOOKS, + LTTV_STATS_AFTER_HOOKS; + +static void remove_all_processes(GHashTable *processes); + +static void +find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu, + GQuark mode, GQuark sub_mode, LttvAttribute **events_tree, + LttvAttribute **event_types_tree); + +static void +init(LttvTracesetStats *self, LttvTraceset *ts) +{ + guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceContext *tc; + + LttvTraceStats *tcs; + + LttvTracefileContext *tfc; + + LttvTracefileStats *tfcs; + + LttTime timestamp = {0,0}; + + LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> + init((LttvTracesetContext *)self, ts); + + self->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + nb_trace = lttv_traceset_number(ts); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); + tcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + + nb_control = ltt_trace_control_tracefile_number(tc->t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfcs = LTTV_TRACEFILE_STATS(tc->control_tracefiles[j]); + } + else { + tfcs = LTTV_TRACEFILE_STATS(tc->per_cpu_tracefiles[j - nb_control]); + } + + tfcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN, + tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN, + LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree, + &tfcs->current_event_types_tree); + } + } +} + + +static void +fini(LttvTracesetStats *self) +{ + guint i, j, nb_trace, nb_tracefile; + + LttvTraceset *ts; + + LttvTraceContext *tc; + + LttvTraceStats *tcs; + + LttvTracefileContext *tfc; + + LttvTracefileStats *tfcs; + + LttTime timestamp = {0,0}; + + lttv_attribute_recursive_free(self->stats); + ts = self->parent.parent.ts; + nb_trace = lttv_traceset_number(ts); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); + lttv_attribute_recursive_free(tcs->stats); + + nb_tracefile = ltt_trace_control_tracefile_number(tc->t); + for(j = 0 ; j < nb_tracefile ; j++) { + tfcs = (LttvTracefileStats *)tfc = tc->control_tracefiles[j]; + lttv_attribute_recursive_free(tfcs->stats); + tfcs->current_events_tree = NULL; + tfcs->current_event_types_tree = NULL; + } + + nb_tracefile = ltt_trace_per_cpu_tracefile_number(tc->t); + for(j = 0 ; j < nb_tracefile ; j++) { + tfcs = (LttvTracefileStats *)tfc = tc->per_cpu_tracefiles[j]; + lttv_attribute_recursive_free(tfcs->stats); + tfcs->current_events_tree = NULL; + tfcs->current_event_types_tree = NULL; + } + } + LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> + fini((LttvTracesetContext *)self); +} + + +static LttvTracesetContext * +new_traceset_context(LttvTracesetContext *self) +{ + return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL)); +} + + +static LttvTraceContext * +new_trace_context(LttvTracesetContext *self) +{ + return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL)); +} + + +static LttvTracefileContext * +new_tracefile_context(LttvTracesetContext *self) +{ + return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL)); +} + + +static void +traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +traceset_stats_finalize (LttvTracesetStats *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +traceset_stats_class_init (LttvTracesetContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize; + klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init; + klass->fini = (void (*)(LttvTracesetContext *self))fini; + klass->new_traceset_context = new_traceset_context; + klass->new_trace_context = new_trace_context; + klass->new_tracefile_context = new_tracefile_context; +} + + +GType +lttv_traceset_stats_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracesetStatsClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) traceset_stats_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracesetContext), + 0, /* n_preallocs */ + (GInstanceInitFunc) traceset_stats_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACESET_STATE_TYPE, "LttvTracesetStatsType", + &info, 0); + } + return type; +} + + +static void +trace_stats_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +trace_stats_finalize (LttvTraceStats *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +trace_stats_class_init (LttvTraceContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize; +} + + +GType +lttv_trace_stats_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTraceStatsClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) trace_stats_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTraceStats), + 0, /* n_preallocs */ + (GInstanceInitFunc) trace_stats_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACE_STATE_TYPE, + "LttvTraceStatsType", &info, 0); + } + return type; +} + + +static void +tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class) +{ +} + + +static void +tracefile_stats_finalize (LttvTracefileStats *self) +{ + G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))-> + finalize(G_OBJECT(self)); +} + + +static void +tracefile_stats_class_init (LttvTracefileStatsClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize; +} + + +GType +lttv_tracefile_stats_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvTracefileStatsClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) tracefile_stats_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvTracefileStats), + 0, /* n_preallocs */ + (GInstanceInitFunc) tracefile_stats_instance_init /* instance_init */ + }; + + type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE, + "LttvTracefileStatsType", &info, 0); + } + return type; +} + + +static void +find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu, + GQuark mode, GQuark sub_mode, LttvAttribute **events_tree, + LttvAttribute **event_types_tree) +{ + LttvAttribute *a; + + LttvTraceStats *tcs = LTTV_TRACE_STATS(tfcs->parent.parent.t_context); + a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES); + a = lttv_attribute_find_subdir(a, tfcs->parent.process->pid_time); + a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU); + a = lttv_attribute_find_subdir(a, tfcs->parent.cpu_name); + a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES); + a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->t); + a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES); + a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->n); + *events_tree = a; + a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES); + *event_types_tree = a; +} + + +static void update_event_tree(LttvTracefileStats *tfcs) +{ + LttvExecutionState *es = tfcs->parent.process->state; + + find_event_tree(tfcs, tfcs->parent.process->pid_time, tfcs->parent.cpu_name, + es->t, es->n, &(tfcs->current_events_tree), + &(tfcs->current_event_types_tree)); +} + + +static void mode_change(LttvTracefileStats *tfcs) +{ + LttvAttributeValue cpu_time; + + LttTime delta; + + lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, + LTTV_TIME, &cpu_time); + delta = ltt_time_sub(tfcs->parent.parent.timestamp, + tfcs->parent.process->state->change); + *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta); +} + + +static void mode_end(LttvTracefileStats *tfcs) +{ + LttvAttributeValue elapsed_time, cpu_time; + + LttTime delta; + + lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME, + LTTV_TIME, &elapsed_time); + delta = ltt_time_sub(tfcs->parent.parent.timestamp, + tfcs->parent.process->state->entry); + *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta); + + lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, + LTTV_TIME, &cpu_time); + delta = ltt_time_sub(tfcs->parent.parent.timestamp, + tfcs->parent.process->state->change); + *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta); +} + + +static gboolean before_syscall_entry(void *hook_data, void *call_data) +{ + mode_change((LttvTracefileStats *)call_data); + return FALSE; +} + + +static gboolean after_syscall_entry(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_syscall_exit(void *hook_data, void *call_data) +{ + mode_end((LttvTracefileStats *)call_data); + return FALSE; +} + + +static gboolean after_syscall_exit(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_trap_entry(void *hook_data, void *call_data) +{ + mode_change((LttvTracefileStats *)call_data); + return FALSE; +} + + +static gboolean after_trap_entry(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_trap_exit(void *hook_data, void *call_data) +{ + mode_end((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean after_trap_exit(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_irq_entry(void *hook_data, void *call_data) +{ + mode_change((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean after_irq_entry(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_irq_exit(void *hook_data, void *call_data) +{ + mode_end((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean after_irq_exit(void *hook_data, void *call_data) +{ + update_event_tree((LttvTracefileStats *)call_data); + return FALSE; +} + + +gboolean before_schedchange(void *hook_data, void *call_data) +{ + LttvTraceHook *h = (LttvTraceHook *)hook_data; + + LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data; + + guint pid_in, pid_out, state_out; + + LttvProcessState *process; + + pid_in = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f1); + pid_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f2); + state_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f3); + + /* compute the time for the process to schedule out */ + + mode_change(tfcs); + + /* get the information for the process scheduled in */ + + process = lttv_state_find_process(&(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), + &(tfcs->current_event_types_tree)); + + /* compute the time waiting for the process to schedule in */ + + mode_change(tfcs); + return FALSE; +} + + +gboolean process_fork(void *hook_data, void *call_data) +{ + /* nothing to do for now */ + return FALSE; +} + + +gboolean process_exit(void *hook_data, void *call_data) +{ + /* We should probably exit all modes here or we could do that at + schedule out. */ + return FALSE; +} + + +gboolean every_event(void *hook_data, void *call_data) +{ + LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data; + + LttvAttributeValue v; + + /* The current branch corresponds to the tracefile/process/interrupt state. + Statistics are added within it, to count the number of events of this + type occuring in this context. A quark has been pre-allocated for each + event type and is used as name. */ + + lttv_attribute_find(tfcs->current_event_types_tree, + ((LttvTraceState *)(tfcs->parent.parent.t_context))-> + eventtype_names[ltt_event_eventtype_id(tfcs->parent.parent.e)], + LTTV_UINT, &v); + (*(v.v_uint))++; + return FALSE; +} + + +static gboolean +sum_stats(void *hook_data, void *call_data) +{ + LttvTracesetStats *tscs = (LttvTracesetStats *)call_data; + + LttvTraceStats *tcs; + + LttvTraceset *traceset = tscs->parent.parent.ts; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + unsigned sum; + + int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode, + nb_event_type; + + LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, + *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, + *submode_tree, *event_types_tree, *mode_events_tree, + *cpu_events_tree, *process_modes_tree, *trace_cpu_tree, + *trace_modes_tree, *traceset_modes_tree; + + traceset_modes_tree = lttv_attribute_find_subdir(tscs->stats, + LTTV_STATS_MODES); + nb_trace = lttv_traceset_number(traceset); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); + main_tree = tcs->stats; + processes_tree = lttv_attribute_find_subdir(main_tree, + LTTV_STATS_PROCESSES); + trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES); + nb_process = lttv_attribute_get_number(processes_tree); + + for(j = 0 ; j < nb_process ; j++) { + type = lttv_attribute_get(processes_tree, j, &name, &value); + process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); + process_modes_tree = lttv_attribute_find_subdir(process_tree, + LTTV_STATS_MODES); + nb_cpu = lttv_attribute_get_number(cpus_tree); + + for(k = 0 ; k < nb_cpu ; k++) { + type = lttv_attribute_get(cpus_tree, k, &name, &value); + cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + mode_types_tree = lttv_attribute_find_subdir(cpu_tree, + LTTV_STATS_MODE_TYPES); + cpu_events_tree = lttv_attribute_find_subdir(cpu_tree, + LTTV_STATS_EVENTS); + trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU); + trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name); + nb_mode_type = lttv_attribute_get_number(mode_types_tree); + + for(l = 0 ; l < nb_mode_type ; l++) { + type = lttv_attribute_get(mode_types_tree, l, &name, &value); + mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + submodes_tree = lttv_attribute_find_subdir(mode_tree, + LTTV_STATS_SUBMODES); + mode_events_tree = lttv_attribute_find_subdir(mode_tree, + LTTV_STATS_EVENTS); + nb_submode = lttv_attribute_get_number(submodes_tree); + + for(m = 0 ; m < nb_submode ; m++) { + type = lttv_attribute_get(submodes_tree, m, &name, &value); + submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + event_types_tree = lttv_attribute_find_subdir(submode_tree, + LTTV_STATS_EVENT_TYPES); + nb_event_type = lttv_attribute_get_number(event_types_tree); + + sum = 0; + for(n = 0 ; n < nb_event_type ; n++) { + type = lttv_attribute_get(event_types_tree, n, &name, &value); + sum += *(value.v_uint); + } + lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT, + LTTV_UINT, &value); + *(value.v_uint) = sum; + lttv_attribute_recursive_add(mode_events_tree, submode_tree); + } + lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree); + } + lttv_attribute_recursive_add(process_modes_tree, cpu_tree); + lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree); + } + lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree); + } + lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree); + } + return FALSE; +} + + +lttv_stats_add_event_hooks(LttvTracesetStats *self) +{ + LttvTraceset *traceset = self->parent.parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttFacility *f; + + LttEventType *et; + + LttvTraceStats *ts; + + LttvTracefileStats *tfs; + + void *hook_data; + + GArray *hooks, *before_hooks, *after_hooks; + + LttvTraceHook hook; + + LttvAttributeValue val; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = (LttvTraceStats *)self->parent.parent.traces[i]; + + /* Find the eventtype id for the following events and register the + associated by id hooks. */ + + hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); + g_array_set_size(hooks, 7); + + lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry", + "syscall_id", NULL, NULL, before_syscall_entry, + &g_array_index(hooks, LttvTraceHook, 0)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL, + NULL, NULL, before_syscall_exit, + &g_array_index(hooks, LttvTraceHook, 1)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id", + NULL, NULL, before_trap_entry, + &g_array_index(hooks, LttvTraceHook, 2)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL, + NULL, before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id", + NULL, NULL, before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL, + NULL, before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "schedchange", "in", + "out", "out_state", before_schedchange, + &g_array_index(hooks, LttvTraceHook, 6)); + + before_hooks = hooks; + + hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); + g_array_set_size(hooks, 8); + + lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry", + "syscall_id", NULL, NULL, after_syscall_entry, + &g_array_index(hooks, LttvTraceHook, 0)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL, + NULL, NULL, after_syscall_exit, + &g_array_index(hooks, LttvTraceHook, 1)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id", + NULL, NULL, after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL, + NULL, after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id", + NULL, NULL, after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL, + NULL, after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "process_fork", + "child_pid", NULL, NULL, process_fork, + &g_array_index(hooks, LttvTraceHook, 6)); + + lttv_trace_find_hook(ts->parent.parent.t, "core", "process_exit", NULL, + NULL, NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 7)); + + after_hooks = hooks; + + /* Add these hooks to each before_event_by_id hooks list */ + + nb_control = ltt_trace_control_tracefile_number(ts->parent.parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.control_tracefiles[j]); + } + else { + tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.per_cpu_tracefiles[ + j-nb_control]); + } + + lttv_hooks_add(tfs->parent.parent.after_event, every_event, NULL); + + for(k = 0 ; k < before_hooks->len ; k++) { + hook = g_array_index(before_hooks, LttvTraceHook, k); + lttv_hooks_add(lttv_hooks_by_id_find( + tfs->parent.parent.before_event_by_id, + hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k)); + } + for(k = 0 ; k < after_hooks->len ; k++) { + hook = g_array_index(after_hooks, LttvTraceHook, k); + lttv_hooks_add(lttv_hooks_by_id_find( + tfs->parent.parent.after_event_by_id, + hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k)); + } + } + lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS, + LTTV_POINTER, &val); + *(val.v_pointer) = before_hooks; + lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS, + LTTV_POINTER, &val); + *(val.v_pointer) = after_hooks; + } + lttv_hooks_add(self->parent.parent.after, sum_stats, NULL); +} + + +lttv_stats_remove_event_hooks(LttvTracesetStats *self) +{ + LttvTraceset *traceset = self->parent.parent.ts; + + guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; + + LttvTraceStats *ts; + + LttvTracefileStats *tfs; + + void *hook_data; + + GArray *before_hooks, *after_hooks; + + LttvTraceHook hook; + + LttvAttributeValue val; + + nb_trace = lttv_traceset_number(traceset); + for(i = 0 ; i < nb_trace ; i++) { + ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]); + lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS, + LTTV_POINTER, &val); + before_hooks = *(val.v_pointer); + lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS, + LTTV_POINTER, &val); + after_hooks = *(val.v_pointer); + + /* Add these hooks to each before_event_by_id hooks list */ + + nb_control = ltt_trace_control_tracefile_number(ts->parent.parent.t); + nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t); + nb_tracefile = nb_control + nb_per_cpu; + for(j = 0 ; j < nb_tracefile ; j++) { + if(j < nb_control) { + tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.control_tracefiles[j]); + } + else { + tfs =LTTV_TRACEFILE_STATS(ts->parent.parent.per_cpu_tracefiles[ + j-nb_control]); + } + + lttv_hooks_remove_data(tfs->parent.parent.after_event, every_event, + NULL); + + for(k = 0 ; k < before_hooks->len ; k++) { + hook = g_array_index(before_hooks, LttvTraceHook, k); + lttv_hooks_remove_data( + lttv_hooks_by_id_find(tfs->parent.parent.before_event_by_id, + hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k)); + } + for(k = 0 ; k < after_hooks->len ; k++) { + hook = g_array_index(after_hooks, LttvTraceHook, k); + lttv_hooks_remove_data( + lttv_hooks_by_id_find(tfs->parent.parent.after_event_by_id, + hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k)); + } + } + g_critical("lttv_stats_remove_event_hooks()"); + g_array_free(before_hooks, TRUE); + g_array_free(after_hooks, TRUE); + } + lttv_hooks_remove_data(self->parent.parent.after, sum_stats, NULL); +} + + +void lttv_stats_init(int argc, char **argv) +{ + LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process"); + LTTV_STATS_PROCESSES = g_quark_from_string("processes"); + LTTV_STATS_CPU = g_quark_from_string("cpu"); + LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types"); + LTTV_STATS_MODES = g_quark_from_string("modes"); + LTTV_STATS_SUBMODES = g_quark_from_string("submodes"); + LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types"); + LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time"); + LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time"); + LTTV_STATS_EVENTS = g_quark_from_string("events"); + LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count"); + LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks"); + LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks"); +} + +void lttv_stats_destroy() +{ +} + +void lttv_stats_save_attribute(LttvAttribute *attr, char *indent, FILE * fp) +{ + LttvAttributeType type; + LttvAttributeValue value; + LttvAttributeName name; + char type_value[BUF_SIZE]; + int i, nb_attr, flag; + + nb_attr = lttv_attribute_get_number(attr); + for(i=0;itv_sec, + value.v_time->tv_nsec); + break; + case LTTV_POINTER: + sprintf(type_value, "POINTER\0"); + break; + case LTTV_STRING: + sprintf(type_value, "%s\0", *value.v_string); + break; + default: + flag = 0; + break; + } + if(flag == 0) continue; + fprintf(fp,"%s",indent,type,g_quark_to_string(name)); + fprintf(fp,"%s",type_value); + fprintf(fp," \n"); + } + +} + +void lttv_stats_save_statistics(LttvTracesetStats *self) +{ + LttvTracesetStats *tscs = self; + LttvTraceStats *tcs; + LttvTraceset *traceset = tscs->parent.parent.ts; + LttvAttributeType type; + LttvAttributeValue value; + LttvAttributeName name; + + char filename[BUF_SIZE]; + FILE * fp; + char indent[10][24]= {" ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + }; + + + int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode; + + LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, + *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, + *submode_tree, *event_types_tree; + + nb_trace = lttv_traceset_number(traceset); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); + + filename[0] = '\0'; + strcat(filename,ltt_trace_name(tcs->parent.parent.t)); + strcat(filename,"/statistics.xml"); + fp = fopen(filename,"w"); + if(!fp){ + g_warning("can not open the file %s for saving statistics\n", filename); + exit(1); + } + + main_tree = tcs->stats; + processes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_PROCESSES); + nb_process = lttv_attribute_get_number(processes_tree); + + fprintf(fp, " \n",g_quark_to_string(LTTV_STATS_PROCESSES)); //root NODE + + for(j = 0 ; j < nb_process ; j++) { + type = lttv_attribute_get(processes_tree, j, &name, &value); + process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + fprintf(fp,"%s \n",indent[0],g_quark_to_string(name)); //process NODE + lttv_stats_save_attribute(process_tree,indent[1], fp); + fprintf(fp,"%s \n", indent[1],g_quark_to_string(LTTV_STATS_CPU)); //cpus NODE + + cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); + nb_cpu = lttv_attribute_get_number(cpus_tree); + + for(k = 0 ; k < nb_cpu ; k++) { + type = lttv_attribute_get(cpus_tree, k, &name, &value); + cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + fprintf(fp,"%s \n",indent[2],g_quark_to_string(name)); //cpu NODE + lttv_stats_save_attribute(cpu_tree,indent[3], fp); + fprintf(fp,"%s \n",indent[3],g_quark_to_string(LTTV_STATS_MODE_TYPES)); //mode_types NODE + + mode_types_tree = lttv_attribute_find_subdir(cpu_tree,LTTV_STATS_MODE_TYPES); + nb_mode_type = lttv_attribute_get_number(mode_types_tree); + + for(l = 0 ; l < nb_mode_type ; l++) { + type = lttv_attribute_get(mode_types_tree, l, &name, &value); + mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + fprintf(fp,"%s \n",indent[4],g_quark_to_string(name)); //mode NODE + lttv_stats_save_attribute(mode_tree,indent[5], fp); + fprintf(fp,"%s \n",indent[5],g_quark_to_string(LTTV_STATS_SUBMODES)); //sub_modes NODE + + submodes_tree = lttv_attribute_find_subdir(mode_tree,LTTV_STATS_SUBMODES); + nb_submode = lttv_attribute_get_number(submodes_tree); + + for(m = 0 ; m < nb_submode ; m++) { + type = lttv_attribute_get(submodes_tree, m, &name, &value); + submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + fprintf(fp,"%s \n",indent[6],g_quark_to_string(name)); //sub_mode NODE + lttv_stats_save_attribute(submode_tree,indent[7], fp); + fprintf(fp,"%s \n",indent[7],g_quark_to_string(LTTV_STATS_EVENT_TYPES)); //event_types NODE + + event_types_tree = lttv_attribute_find_subdir(submode_tree, LTTV_STATS_EVENT_TYPES); + lttv_stats_save_attribute(event_types_tree,indent[8], fp); + + fprintf(fp,"%s \n",indent[7]); //event_types NODE + fprintf(fp,"%s \n",indent[6]); //sub_mode NODE + } + fprintf(fp,"%s \n",indent[5]); //sub_modes NODE + fprintf(fp,"%s \n",indent[4]); //mode NODE + } + fprintf(fp,"%s \n",indent[3]); //mode_type NODE + fprintf(fp,"%s \n",indent[2]); //cpu NODE + } + fprintf(fp,"%s \n",indent[1]); //cpus NODE + fprintf(fp,"%s \n", indent[0]); //process NODE + } + fprintf(fp, "\n"); //root NODE + fclose(fp); + } +} + + +/* Functions to parse statistic.xml file (using glib xml parser) */ + +typedef struct _ParserStruct{ + GPtrArray * attribute; + LttvAttributeType type; + LttvAttributeName name; +} ParserStruct; + +static void stats_parser_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + ParserStruct * parser = (ParserStruct *)user_data; + int len; + LttvAttributeType type; + LttvAttributeName name; + LttvAttribute * parent_att, *new_att; + + len = parser->attribute->len; + parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); + + if(strcmp("NODE", element_name) == 0){ + type = LTTV_GOBJECT; + name = g_quark_from_string(attribute_values[0]); + new_att = lttv_attribute_find_subdir(parent_att,name); + g_ptr_array_add(parser->attribute, (gpointer)new_att); + }else if(strcmp("VALUE", element_name) == 0){ + parser->type = (LttvAttributeType) atoi(attribute_values[0]); + parser->name = g_quark_from_string(attribute_values[1]); + }else{ + g_warning("This is not statistics.xml file\n"); + exit(1); + } +} + +static void stats_parser_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + ParserStruct * parser = (ParserStruct *)user_data; + int len; + LttvAttribute * parent_att; + + len = parser->attribute->len; + parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); + + if(strcmp("NODE", element_name) == 0){ + g_ptr_array_remove_index(parser->attribute, len-1); + }else if(strcmp("VALUE", element_name) == 0){ + }else{ + g_warning("This is not statistics.xml file\n"); + exit(1); + } + +} + +static void stats_parser_characters (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + ParserStruct * parser = (ParserStruct *)user_data; + LttvAttributeValue value; + int len; + LttvAttribute * parent_att; + char *pos; + + pos = (char*)text; + for(len=0;lenattribute->len; + parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); + if(!lttv_attribute_find(parent_att,parser->name, parser->type, &value)){ + g_warning("can not find value\n"); + exit(1); + } + + switch(parser->type) { + case LTTV_INT: + *value.v_int = atoi(text); + break; + case LTTV_UINT: + *value.v_uint = (unsigned)atoi(text); + break; + case LTTV_LONG: + *value.v_long = atol(text); + break; + case LTTV_ULONG: + *value.v_ulong = (unsigned long)atol(text); + break; + case LTTV_FLOAT: + *value.v_float = atof(text); + break; + case LTTV_DOUBLE: + *value.v_float = atof(text); + break; + case LTTV_TIME: + pos = strrchr(text,'.'); + if(pos){ + *pos = '\0'; + pos++; + value.v_time->tv_sec = atol(text); + value.v_time->tv_nsec = atol(pos); + }else{ + g_warning("The time value format is wrong\n"); + exit(1); + } + break; + case LTTV_POINTER: + break; + case LTTV_STRING: + *value.v_string = g_strdup(text); + break; + default: + break; + } + +} + +gboolean lttv_stats_load_statistics(LttvTracesetStats *self) +{ + FILE * fp; + char buf[BUF_SIZE]; + LttvTracesetStats *tscs = self; + LttvTraceStats *tcs; + LttvTraceset *traceset = tscs->parent.parent.ts; + char filename[BUF_SIZE]; + + GMarkupParseContext * context; + GError * error; + GMarkupParser markup_parser = + { + stats_parser_start_element, + stats_parser_end_element, + stats_parser_characters, + NULL, /* passthrough */ + NULL /* error */ + }; + + int i, nb_trace; + LttvAttribute *main_tree; + ParserStruct a_parser_struct; + a_parser_struct.attribute = g_ptr_array_new(); + + nb_trace = lttv_traceset_number(traceset); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); + + filename[0] = '\0'; + strcat(filename,ltt_trace_name(tcs->parent.parent.t)); + strcat(filename,"/statistics.xml"); + fp = fopen(filename,"r"); + if(!fp){ + g_warning("can not open the file %s for reading statistics\n", filename); + return FALSE; + } + + main_tree = tcs->stats; + g_ptr_array_add(a_parser_struct.attribute,(gpointer)main_tree); + + context = g_markup_parse_context_new(&markup_parser, 0, (gpointer)&a_parser_struct, NULL); + + while(fgets(buf,BUF_SIZE, fp) != NULL){ + if(!g_markup_parse_context_parse(context, buf, BUF_SIZE, &error)){ + g_warning("Can not parse xml file: \n%s\n", error->message); + exit(1); + } + } + fclose(fp); + } + + sum_stats(NULL, (void *)self); + + return TRUE; +} diff --git a/ltt/branches/poly/lttv/main/traceset.c b/ltt/branches/poly/lttv/main/traceset.c new file mode 100644 index 00000000..ce96b99a --- /dev/null +++ b/ltt/branches/poly/lttv/main/traceset.c @@ -0,0 +1,171 @@ + +#include +#include + +/* A trace is a sequence of events gathered in the same tracing session. The + events may be stored in several tracefiles in the same directory. + A trace set is defined when several traces are to be analyzed together, + possibly to study the interactions between events in the different traces. +*/ + +struct _LttvTraceset { + char * filename; + GPtrArray *traces; + LttvAttribute *a; +}; + + +struct _LttvTrace { + LttTrace *t; + LttvAttribute *a; + guint ref_count; +}; + + +LttvTraceset *lttv_traceset_new() +{ + LttvTraceset *s; + + s = g_new(LttvTraceset, 1); + s->filename = NULL; + s->traces = g_ptr_array_new(); + s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + return s; +} + +char * lttv_traceset_name(LttvTraceset * s) +{ + return s->filename; +} + +LttvTrace *lttv_trace_new(LttTrace *t) +{ + LttvTrace *new_trace; + + new_trace = g_new(LttvTrace, 1); + new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + new_trace->t = t; + new_trace->ref_count = 0; + return new_trace; +} + + +LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) +{ + int i; + LttvTraceset *s; + LttvTrace * trace; + + s = g_new(LttvTraceset, 1); + s->filename = NULL; + s->traces = g_ptr_array_new(); + for(i=0;itraces->len;i++) + { + trace = g_ptr_array_index(s_orig->traces, i); + trace->ref_count++; + + /*CHECK this used ltt_trace_copy while it may not be needed. Need to + define how traces and tracesets are shared */ + g_ptr_array_add( + s->traces, + g_ptr_array_index(s_orig->traces, i)); + } + s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a))); + return s; +} + + +LttvTraceset *lttv_traceset_load(const gchar *filename) +{ + LttvTraceset *s = g_new(LttvTraceset,1); + FILE *tf; + + s->filename = g_strdup(filename); + tf = fopen(filename,"r"); + + g_critical("NOT IMPLEMENTED : load traceset data from a XML file"); + + fclose(tf); + return s; +} + +gint lttv_traceset_save(LttvTraceset *s) +{ + FILE *tf; + + tf = fopen(s->filename, "w"); + + g_critical("NOT IMPLEMENTED : save traceset data in a XML file"); + + fclose(tf); + return 0; +} + +void lttv_traceset_destroy(LttvTraceset *s) +{ + g_ptr_array_free(s->traces, TRUE); + g_object_unref(s->a); + g_free(s); +} + +void lttv_trace_destroy(LttvTrace *t) +{ + g_object_unref(t->a); + g_free(t); +} + + +void lttv_traceset_add(LttvTraceset *s, LttvTrace *t) +{ + t->ref_count++; + g_ptr_array_add(s->traces, t); +} + + +unsigned lttv_traceset_number(LttvTraceset *s) +{ + return s->traces->len; +} + + +LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i) +{ + g_assert(s->traces->len > i); + return ((LttvTrace *)s->traces->pdata[i]); +} + + +void lttv_traceset_remove(LttvTraceset *s, unsigned i) +{ + LttvTrace * t; + g_assert(s->traces->len > i); + t = (LttvTrace *)s->traces->pdata[i]; + t->ref_count--; + g_ptr_array_remove_index(s->traces, i); +} + + +/* A set of attributes is attached to each trace set, trace and tracefile + to store user defined data as needed. */ + +LttvAttribute *lttv_traceset_attribute(LttvTraceset *s) +{ + return s->a; +} + + +LttvAttribute *lttv_trace_attribute(LttvTrace *t) +{ + return t->a; +} + + +LttTrace *lttv_trace(LttvTrace *t) +{ + return t->t; +} + +guint lttv_trace_get_ref_number(LttvTrace * t) +{ + return t->ref_count; +} diff --git a/ltt/branches/poly/lttv/mainLib/attribute.c b/ltt/branches/poly/lttv/mainLib/attribute.c deleted file mode 100644 index 4b6938d7..00000000 --- a/ltt/branches/poly/lttv/mainLib/attribute.c +++ /dev/null @@ -1,383 +0,0 @@ - -#include -#include - -typedef union _AttributeValue { - int dv_int; - unsigned dv_uint; - long dv_long; - unsigned long dv_ulong; - float dv_float; - double dv_double; - LttTime dv_time; - gpointer dv_pointer; - char *dv_string; - GObject *dv_gobject; -} AttributeValue; - - -typedef struct _Attribute { - LttvAttributeName name; - LttvAttributeType type; - AttributeValue value; -} Attribute; - - -LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v) -{ - LttvAttributeValue va; - - switch(t) { - case LTTV_INT: va.v_int = &v->dv_int; break; - case LTTV_UINT: va.v_uint = &v->dv_uint; break; - case LTTV_LONG: va.v_long = &v->dv_long; break; - case LTTV_ULONG: va.v_ulong = &v->dv_ulong; break; - case LTTV_FLOAT: va.v_float = &v->dv_float; break; - case LTTV_DOUBLE: va.v_double = &v->dv_double; break; - case LTTV_TIME: va.v_time = &v->dv_time; break; - case LTTV_POINTER: va.v_pointer = &v->dv_pointer; break; - case LTTV_STRING: va.v_string = &v->dv_string; break; - case LTTV_GOBJECT: va.v_gobject = &v->dv_gobject; break; - } - return va; -} - - -AttributeValue init_value(LttvAttributeType t) -{ - AttributeValue v; - - switch(t) { - case LTTV_INT: v.dv_int = 0; break; - case LTTV_UINT: v.dv_uint = 0; break; - case LTTV_LONG: v.dv_long = 0; break; - case LTTV_ULONG: v.dv_ulong = 0; break; - case LTTV_FLOAT: v.dv_float = 0; break; - case LTTV_DOUBLE: v.dv_double = 0; break; - case LTTV_TIME: v.dv_time.tv_sec = 0; v.dv_time.tv_nsec = 0; break; - case LTTV_POINTER: v.dv_pointer = NULL; break; - case LTTV_STRING: v.dv_string = NULL; break; - case LTTV_GOBJECT: v.dv_gobject = NULL; break; - } - return v; -} - - -unsigned int -lttv_attribute_get_number(LttvAttribute *self) -{ - return self->attributes->len; -} - - -gboolean -lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous) -{ - *homogeneous = FALSE; - return TRUE; -} - - -LttvAttributeType -lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name, - LttvAttributeValue *v) -{ - Attribute *a; - - a = &g_array_index(self->attributes, Attribute, i); - *name = a->name; - *v = address_of_value(a->type, &(a->value)); - return a->type; -} - - -LttvAttributeType -lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name, - LttvAttributeValue *v) -{ - Attribute *a; - - unsigned i; - - gpointer p; - - p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); - if(p == NULL) return LTTV_NONE; - - i = GPOINTER_TO_UINT(p); - i--; - a = &g_array_index(self->attributes, Attribute, i); - *v = address_of_value(a->type, &(a->value)); - return a->type; -} - - -LttvAttributeValue -lttv_attribute_add(LttvAttribute *self, LttvAttributeName name, - LttvAttributeType t) -{ - unsigned i; - - Attribute a, *pa; - - i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); - if(i != 0) g_error("duplicate entry in attribute table"); - - a.name = name; - a.type = t; - a.value = init_value(t); - g_array_append_val(self->attributes, a); - i = self->attributes->len - 1; - pa = &g_array_index(self->attributes, Attribute, i); - g_hash_table_insert(self->names, GUINT_TO_POINTER(name), - GUINT_TO_POINTER(i + 1)); - return address_of_value(t, &(pa->value)); -} - - -/* Remove an attribute */ - -void -lttv_attribute_remove(LttvAttribute *self, unsigned i) -{ - Attribute *a; - - a = &g_array_index(self->attributes, Attribute, i); - - /* Remove the array element and its entry in the name index */ - - g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name)); - g_array_remove_index_fast(self->attributes, i); - - /* The element used to replace the removed element has its index entry - all wrong now. Reinsert it with its new position. */ - - if(self->attributes->len != i){ - g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name)); - g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1)); - } -} - -void -lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name) -{ - unsigned i; - - i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); - if(i == 0) g_error("remove by name non existent attribute"); - - lttv_attribute_remove(self, i - 1); -} - -/* Create an empty iattribute object and add it as an attribute under the - specified name, or return an existing iattribute attribute. If an - attribute of that name already exists but is not a GObject supporting the - iattribute interface, return NULL. */ - -/*CHECK*/LttvAttribute* -lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name) -{ - unsigned i; - - Attribute a; - - LttvAttribute *new; - - i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); - if(i != 0) { - a = g_array_index(self->attributes, Attribute, i - 1); - if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) { - return LTTV_ATTRIBUTE(a.value.dv_gobject); - } - else return NULL; - } - new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new); - return (LttvAttribute *)new; -} - -gboolean -lttv_attribute_find(LttvAttribute *self, LttvAttributeName name, - LttvAttributeType t, LttvAttributeValue *v) -{ - unsigned i; - - Attribute *a; - - i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); - if(i != 0) { - a = &g_array_index(self->attributes, Attribute, i - 1); - if(a->type != t) return FALSE; - *v = address_of_value(t, &(a->value)); - return TRUE; - } - - *v = lttv_attribute_add(self, name, t); - return TRUE; -} - - -void lttv_attribute_recursive_free(LttvAttribute *self) -{ - int i, nb; - - Attribute *a; - - nb = self->attributes->len; - - for(i = 0 ; i < nb ; i++) { - a = &g_array_index(self->attributes, Attribute, i); - if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) { - lttv_attribute_recursive_free((LttvAttribute *)(a->value.dv_gobject)); - } - } - g_object_unref(self); -} - - -void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src) -{ - int i, nb; - - Attribute *a; - - LttvAttributeValue value; - - nb = src->attributes->len; - - for(i = 0 ; i < nb ; i++) { - a = &g_array_index(src->attributes, Attribute, i); - if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) { - lttv_attribute_recursive_add( - /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir(dest, a->name), - (LttvAttribute *)(a->value.dv_gobject)); - } - else { - g_assert(lttv_attribute_find(dest, a->name, a->type, &value)); - switch(a->type) { - case LTTV_INT: - *value.v_int += a->value.dv_int; - break; - case LTTV_UINT: - *value.v_uint += a->value.dv_uint; - break; - case LTTV_LONG: - *value.v_long += a->value.dv_long; - break; - case LTTV_ULONG: - *value.v_ulong += a->value.dv_ulong; - break; - case LTTV_FLOAT: - *value.v_float += a->value.dv_float; - break; - case LTTV_DOUBLE: - *value.v_double += a->value.dv_double; - break; - case LTTV_TIME: - *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time); - break; - case LTTV_POINTER: - break; - case LTTV_STRING: - break; - case LTTV_GOBJECT: - break; - case LTTV_NONE: - break; - } - } - } -} - - -static void -attribute_interface_init (gpointer g_iface, gpointer iface_data) -{ - LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface; - - klass->get_number = (unsigned int (*) (LttvIAttribute *self)) - lttv_attribute_get_number; - - klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous)) - lttv_attribute_named; - - klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i, - LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get; - - klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self, - LttvAttributeName name, LttvAttributeValue *v)) - lttv_attribute_get_by_name; - - klass->add = (LttvAttributeValue (*) (LttvIAttribute *self, - LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add; - - klass->remove = (void (*) (LttvIAttribute *self, unsigned i)) - lttv_attribute_remove; - - klass->remove_by_name = (void (*) (LttvIAttribute *self, - LttvAttributeName name)) lttv_attribute_remove_by_name; - - klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self, - LttvAttributeName name)) lttv_attribute_find_subdir; -} - - -static void -attribute_instance_init (GTypeInstance *instance, gpointer g_class) -{ - LttvAttribute *self = (LttvAttribute *)instance; - self->names = g_hash_table_new(g_direct_hash, g_direct_equal); - self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute)); -} - - -static void -attribute_finalize (LttvAttribute *self) -{ - g_hash_table_destroy(self->names); - g_critical("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)); -} - - -static void -attribute_class_init (LttvAttributeClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self))attribute_finalize; -} - -GType -lttv_attribute_get_type (void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvAttributeClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) attribute_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvAttribute), - 0, /* n_preallocs */ - (GInstanceInitFunc) attribute_instance_init /* instance_init */ - }; - - static const GInterfaceInfo iattribute_info = { - (GInterfaceInitFunc) attribute_interface_init, /* interface_init */ - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info, - 0); - g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info); - } - return type; -} - - diff --git a/ltt/branches/poly/lttv/mainLib/filter.c b/ltt/branches/poly/lttv/mainLib/filter.c deleted file mode 100644 index c63940ba..00000000 --- a/ltt/branches/poly/lttv/mainLib/filter.c +++ /dev/null @@ -1,58 +0,0 @@ - - consist in AND, OR and NOT nested expressions, forming a tree with - simple relations as leaves. The simple relations test is a field - in an event is equal, not equal, smaller, smaller or equal, larger, or - larger or equal to a specified value. */ - -typedef enum _lttv_expression_op -{ LTTV_FIELD_EQ, - LTTV_FIELD_NE, - LTTV_FIELD_LT, - LTTV_FIELD_LE, - LTTV_FIELD_GT, - LTTV_FIELD_GE -} lttv_expression_op; - -typedef _lttv_simple_expression -{ lttv_expression_op op; - char *field_name; - char *value; -} lttv_simple_expression; - -typedef _lttv_expression_type -{ LTTV_EXPRESSION, - LTTV_SIMPLE_EXPRESSION - -} -typedef struct _lttv_expression -{ bool or; - bool not; - bool simple_expression; - union - { lttv_expression *e; - lttv_field_relation *se; - } e; -} lttv_expression; - -read_token - -read_expression - ( read expr ) - simple expr [ op expr ] - -read_simple_expression - read_field_path [ rel value ] - -read_field_path - read_field_component [. field path] - -read_field_component - name [ \[ value \] ] - -data struct: -and/or(left/right) -not(child) -op(left/right) -path(component...) -> field - - diff --git a/ltt/branches/poly/lttv/mainLib/hook.c b/ltt/branches/poly/lttv/mainLib/hook.c deleted file mode 100644 index 8edbb2af..00000000 --- a/ltt/branches/poly/lttv/mainLib/hook.c +++ /dev/null @@ -1,212 +0,0 @@ - -#include - - -typedef struct _LttvHookClosure { - LttvHook hook; - void *hook_data; -} LttvHookClosure; - - -LttvHooks *lttv_hooks_new() -{ - return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure)); -} - - -void lttv_hooks_destroy(LttvHooks *h) -{ - g_critical("lttv_hooks_destroy()"); - g_array_free(h, TRUE); -} - - -void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data) -{ - LttvHookClosure c; - - if(h == NULL)g_error("Null hook added"); - - c.hook = f; - c.hook_data = hook_data; - g_array_append_val(h,c); -} - - -void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list) -{ - guint i; - - if(list == NULL) return; - for(i = 0 ; i < list->len; i++) { - g_array_append_val(h,g_array_index(list, LttvHookClosure, i)); - } -} - - -void *lttv_hooks_remove(LttvHooks *h, LttvHook f) -{ - unsigned i; - - void *hook_data; - - LttvHookClosure *c; - - for(i = 0 ; i < h->len ; i++) { - c = &g_array_index(h, LttvHookClosure, i); - if(c->hook == f) { - hook_data = c->hook_data; - lttv_hooks_remove_by_position(h, i); - return hook_data; - } - } - return NULL; -} - - -void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data) -{ - unsigned i; - - LttvHookClosure *c; - - for(i = 0 ; i < h->len ; i++) { - c = &g_array_index(h, LttvHookClosure, i); - if(c->hook == f && c->hook_data == hook_data) { - lttv_hooks_remove_by_position(h, i); - return; - } - } -} - - -void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list) -{ - guint i, j; - - LttvHookClosure *c, *c_list; - - if(list == NULL) return; - for(i = 0, j = 0 ; i < h->len && j < list->len ;) { - c = &g_array_index(h, LttvHookClosure, i); - c_list = &g_array_index(list, LttvHookClosure, j); - if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) { - lttv_hooks_remove_by_position(h, i); - j++; - } - else i++; - } - - /* Normally the hooks in h are ordered as in list. If this is not the case, - try harder here. */ - - if(j < list->len) { - for(; j < list->len ; j++) { - c_list = &g_array_index(list, LttvHookClosure, j); - lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data); - } - } -} - - -unsigned lttv_hooks_number(LttvHooks *h) -{ - return h->len; -} - - -void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data) -{ - LttvHookClosure *c; - - c = &g_array_index(h, LttvHookClosure, i); - *f = c->hook; - *hook_data = c->hook_data; -} - - -void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i) -{ - g_array_remove_index(h, i); -} - - -gboolean lttv_hooks_call(LttvHooks *h, void *call_data) -{ - gboolean ret, sum_ret = FALSE; - - LttvHookClosure *c; - - guint i; - - if(h != NULL) { - for(i = 0 ; i < h->len ; i++) { - c = &g_array_index(h, LttvHookClosure, i); - ret = c->hook(c->hook_data,call_data); - sum_ret = sum_ret || ret; - } - } - return sum_ret; -} - - -gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data) -{ - LttvHookClosure *c; - - guint i; - - for(i = 0 ; i < h->len ; i++) { - c = &g_array_index(h, LttvHookClosure, i); - if(c->hook(c->hook_data,call_data)) return TRUE; - } - return FALSE; -} - - -LttvHooksById *lttv_hooks_by_id_new() -{ - return g_ptr_array_new(); -} - - -void lttv_hooks_by_id_destroy(LttvHooksById *h) -{ - guint i; - - for(i = 0 ; i < h->len ; i++) { - if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i])); - } - g_ptr_array_free(h, TRUE); -} - - -LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id) -{ - if(h->len <= id) g_ptr_array_set_size(h, id + 1); - if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new(); - return h->pdata[id]; -} - - -unsigned lttv_hooks_by_id_max_id(LttvHooksById *h) -{ - return h->len; -} - - -LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id) -{ - if(id < h->len) return h->pdata[id]; - return NULL; -} - - -void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id) -{ - if(id < h->len && h->pdata[id] != NULL) { - lttv_hooks_destroy((LttvHooks *)h->pdata[id]); - h->pdata[id] = NULL; - } -} - diff --git a/ltt/branches/poly/lttv/mainLib/iattribute.c b/ltt/branches/poly/lttv/mainLib/iattribute.c deleted file mode 100644 index e39d7e08..00000000 --- a/ltt/branches/poly/lttv/mainLib/iattribute.c +++ /dev/null @@ -1,260 +0,0 @@ - -#include - -static void -lttv_iattribute_base_init (gpointer klass) -{ - static gboolean initialized = FALSE; - - if (!initialized) { - initialized = TRUE; - } -} - - -GType -lttv_iattribute_get_type (void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvIAttributeClass), - lttv_iattribute_base_init, /* base_init */ - NULL, /* base_finalize */ - NULL, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - 0, - 0, /* n_preallocs */ - NULL /* instance_init */ - }; - type = g_type_register_static (G_TYPE_INTERFACE, "LttvIAttribute", - &info, 0); - } - return type; -} - - -unsigned int lttv_iattribute_get_number(LttvIAttribute *self) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->get_number (self); -} - - -gboolean lttv_iattribute_named(LttvIAttribute *self, gboolean *homogeneous) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->named (self, homogeneous); -} - - -LttvAttributeType lttv_iattribute_get(LttvIAttribute *self, unsigned i, - LttvAttributeName *name, LttvAttributeValue *v) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->get (self, i, name, v); -} - - -LttvAttributeType lttv_iattribute_get_by_name(LttvIAttribute *self, - LttvAttributeName name, LttvAttributeValue *v) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->get_by_name (self, name, v); -} - - -LttvAttributeValue lttv_iattribute_add(LttvIAttribute *self, - LttvAttributeName name, LttvAttributeType t) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->add (self, name, t); -} - - -void lttv_iattribute_remove(LttvIAttribute *self, unsigned i) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->remove (self, i); -} - - -void lttv_iattribute_remove_by_name(LttvIAttribute *self, - LttvAttributeName name) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->remove_by_name (self, name); -} - -LttvIAttribute* lttv_iattribute_find_subdir(LttvIAttribute *self, - LttvAttributeName name) -{ - return LTTV_IATTRIBUTE_GET_CLASS (self)->find_subdir (self, name); -} - - -/* Find the named attribute in the table, which must be of the specified type. - If it does not exist, it is created with a default value of 0 (NULL for - pointer types). Since the address of the value is obtained, it may be - changed easily afterwards. The function returns false when the attribute - exists but is of incorrect type. */ - -gboolean lttv_iattribute_find(LttvIAttribute *self, LttvAttributeName name, - LttvAttributeType t, LttvAttributeValue *v) -{ - LttvAttributeType found_type; - - found_type = lttv_iattribute_get_by_name(self, name, v); - if(found_type == t) return TRUE; - - if(found_type == LTTV_NONE) { - *v = lttv_iattribute_add(self, name, t); - return TRUE; - } - - return FALSE; -} - - -/* Trees of attribute tables may be accessed using a hierarchical path with - components separated by /, like in filesystems */ - -gboolean lttv_iattribute_find_by_path(LttvIAttribute *self, char *path, - LttvAttributeType t, LttvAttributeValue *v) -{ - LttvIAttribute *node = self; - - LttvAttributeType found_type; - - LttvAttributeName name; - - gchar **components, **cursor; - - components = g_strsplit(path, "\"", G_MAXINT); - - if(components == NULL || *components == NULL) { - g_strfreev(components); - return FALSE; - } - - for(cursor = components;;) { - name = g_quark_from_string(*cursor); - cursor++; - - if(*cursor == NULL) { - g_strfreev(components); - return lttv_iattribute_find(node, name, t, v); - } - else { - found_type = lttv_iattribute_get_by_name(node, name, v); - if(found_type == LTTV_NONE) { - node = lttv_iattribute_find_subdir(node, name); - } - else if(found_type == LTTV_GOBJECT && - LTTV_IS_IATTRIBUTE(*(v->v_gobject))) { - node = LTTV_IATTRIBUTE(*(v->v_gobject)); - } - else { - g_strfreev(components); - return FALSE; - } - } - } -} - -/* Shallow and deep copies */ - -LttvIAttribute *lttv_iattribute_shallow_copy(LttvIAttribute *self) -{ - LttvIAttribute *copy; - - LttvAttributeType t; - - LttvAttributeValue v, v_copy; - - LttvAttributeName name; - - int i; - - int nb_attributes = lttv_iattribute_get_number(self); - - copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self),NULL)); - - for(i = 0 ; i < nb_attributes ; i++) { - t = lttv_iattribute_get(self, i, &name, &v); - v_copy = lttv_iattribute_add(copy, name, t); - lttv_iattribute_copy_value(t, v_copy, v); - } -} - -LttvIAttribute *lttv_iattribute_deep_copy(LttvIAttribute *self) -{ - LttvIAttribute *copy, *child; - - LttvAttributeType t; - - LttvAttributeValue v, v_copy; - - LttvAttributeName name; - - int i; - - int nb_attributes = lttv_iattribute_get_number(self); - - copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self), NULL)); - - for(i = 0 ; i < nb_attributes ; i++) { - t = lttv_iattribute_get(self, i, &name, &v); - v_copy = lttv_iattribute_add(copy, name, t); - if(t == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(*(v.v_gobject))) { - child = LTTV_IATTRIBUTE(*(v.v_gobject)); - *(v_copy.v_gobject) = G_OBJECT(lttv_iattribute_deep_copy(child)); - } - else lttv_iattribute_copy_value(t, v_copy, v); - } -} - -void lttv_iattribute_copy_value(LttvAttributeType t, LttvAttributeValue dest, - LttvAttributeValue src) -{ - switch(t) { - case LTTV_INT: - *(dest.v_int) = *(src.v_int); - break; - - case LTTV_UINT: - *(dest.v_uint) = *(src.v_uint); - break; - - case LTTV_LONG: - *(dest.v_long) = *(src.v_long); - break; - - case LTTV_ULONG: - *(dest.v_ulong) = *(src.v_ulong); - break; - - case LTTV_FLOAT: - *(dest.v_float) = *(src.v_float); - break; - - case LTTV_DOUBLE: - *(dest.v_double) = *(src.v_double); - break; - - case LTTV_TIME: - *(dest.v_time) = *(src.v_time); - break; - - case LTTV_POINTER: - *(dest.v_pointer) = *(src.v_pointer); - break; - - case LTTV_STRING: - *(dest.v_string) = *(src.v_string); - break; - - case LTTV_GOBJECT: - *(dest.v_gobject) = *(src.v_gobject); - break; - - case LTTV_NONE: - break; - } -} - - diff --git a/ltt/branches/poly/lttv/mainLib/module.c b/ltt/branches/poly/lttv/mainLib/module.c deleted file mode 100644 index e225992a..00000000 --- a/ltt/branches/poly/lttv/mainLib/module.c +++ /dev/null @@ -1,302 +0,0 @@ - -/* module.c : Implementation of the module loading/unloading mechanism. - * - */ - -#include - -#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; - guint ref_count; - guint load_count; - GPtrArray *dependents; -}; - - -/* Table of loaded modules and paths where to search for modules */ - -static GHashTable *modules = NULL; - -static GPtrArray *modulesPaths = NULL; - -static void lttv_module_unload_all(); - - -void lttv_module_init(int argc, char **argv) -{ - g_info("Init module.c"); - modules = g_hash_table_new(g_str_hash, g_str_equal); - modulesPaths = g_ptr_array_new(); -} - - -void lttv_module_destroy() -{ - int i; - - g_info("Destroy module.c"); - - /* Unload all modules */ - lttv_module_unload_all(); - - /* Free the modules paths pointer array as well as the elements */ - for(i = 0; i < modulesPaths->len ; i++) { - g_free(modulesPaths->pdata[i]); - } - g_ptr_array_free(modulesPaths,TRUE) ; - modulesPaths = NULL; - - /* destroy the hash table */ - g_hash_table_destroy(modules) ; - modules = NULL; -} - - -/* Add a new pathname to the modules loading search path */ - -void lttv_module_path_add(const char *name) -{ - g_info("Add module path %s", name); - g_ptr_array_add(modulesPaths,(char*)g_strdup(name)); -} - - -static LttvModule * -module_load(const char *name, int argc, char **argv) -{ - GModule *gm; - - LttvModule *m; - - int i; - - char *pathname; - - const char *module_name; - - LttvModuleInit init_function; - - g_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); - gm = g_module_open(pathname,0); - g_free(pathname); - - if(gm != NULL) break; - g_info("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"); - 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); - return NULL; - } - - /* Check if the module was already opened using the hopefully canonical name - returned by g_module_name. */ - - module_name = g_module_name(gm); - - m = g_hash_table_lookup(modules, module_name); - - if(m == NULL) { - g_info("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. */ - - m = g_new(LttvModule, 1); - m->module = gm; - m->ref_count = 0; - m->load_count = 0; - m->dependents = g_ptr_array_new(); - g_hash_table_insert(modules, (gpointer)module_name, m); - - if(!g_module_symbol(gm, "init", (gpointer)&init_function)) { - g_warning("module %s (%s) has no init function", name, pathname); - } - else init_function(m, argc, argv); - } - else { - - /* 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); - if(m->module != gm) g_error("Two gmodules with the same pathname"); - g_module_close(gm); - } - - m->ref_count++; - return m; -} - - -LttvModule * -lttv_module_load(const char *name, int argc, char **argv) -{ - g_info("Load module %s explicitly", name); - LttvModule *m = module_load(name, argc, argv); - if(m != NULL) m->load_count++; - return m; -} - - -LttvModule * -lttv_module_require(LttvModule *m, const char *name, int argc, char **argv) -{ - LttvModule *module; - - g_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); - return module; -} - - -static void module_unload(LttvModule *m) -{ - LttvModuleDestroy destroy_function; - - char *pathname; - - guint i, len; - - /* Decrement the reference count */ - - g_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); - return; - } - /* We really have to unload the module, first unload its dependents */ - - len = m->dependents->len; - g_info("Unload dependent modules"); - - for(i = 0 ; i < len ; i++) { - module_unload(m->dependents->pdata[i]); - } - - if(len != m->dependents->len) g_error("dependents list modified"); - - /* Unload the module itself */ - - g_info("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); - } - else destroy_function(); - - g_hash_table_remove(modules, g_module_name(m->module)); - g_ptr_array_free(m->dependents, TRUE); - g_module_close(m->module); - g_free(m); -} - - -void lttv_module_unload(LttvModule *m) -{ - g_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; - } - m->load_count--; - module_unload(m); -} - - -static void -list_modules(gpointer key, gpointer value, gpointer user_data) -{ - g_ptr_array_add((GPtrArray *)user_data, value); -} - - -LttvModule ** -lttv_module_list(guint *nb) -{ - GPtrArray *list = g_ptr_array_new(); - - LttvModule **array; - - g_hash_table_foreach(modules, list_modules, list); - *nb = list->len; - array = (LttvModule **)list->pdata; - g_ptr_array_free(list, FALSE); - return array; -} - - -LttvModule ** -lttv_module_info(LttvModule *m, const char **name, - guint *ref_count, guint *load_count, guint *nb_dependents) -{ - guint i, len = m->dependents->len; - - LttvModule **array = g_new(LttvModule *, len); - - *name = g_module_name(m->module); - *ref_count = m->ref_count; - *load_count = m->load_count; - *nb_dependents = len; - for(i = 0 ; i < len ; i++) array[i] = m->dependents->pdata[i]; - return array; -} - -char * -lttv_module_name(LttvModule *m) -{ - return g_module_name(m->module); -} - -static void -list_independent(gpointer key, gpointer value, gpointer user_data) -{ - LttvModule *m = (LttvModule *)value; - - if(m->load_count > 0) g_ptr_array_add((GPtrArray *)user_data, m); -} - - -void -lttv_module_unload_all() -{ - guint i; - - LttvModule *m; - - GPtrArray *independent_modules = g_ptr_array_new(); - - g_hash_table_foreach(modules, list_independent, independent_modules); - - for(i = 0 ; i < independent_modules->len ; i++) { - m = (LttvModule *)independent_modules->pdata[i]; - while(m->load_count > 0) lttv_module_unload(m); - } - - g_ptr_array_free(independent_modules, TRUE); - if(g_hash_table_size(modules) != 0) g_warning("cannot unload all modules"); -} diff --git a/ltt/branches/poly/lttv/mainLib/processTrace.c b/ltt/branches/poly/lttv/mainLib/processTrace.c deleted file mode 100644 index 4a290dd0..00000000 --- a/ltt/branches/poly/lttv/mainLib/processTrace.c +++ /dev/null @@ -1,812 +0,0 @@ - -#include -#include -#include -#include -#include - -void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts) -{ - LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts); -} - - -void lttv_context_fini(LttvTracesetContext *self) -{ - LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self); -} - - -LttvTracesetContext * -lttv_context_new_traceset_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self); -} - - - - -LttvTraceContext * -lttv_context_new_trace_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); -} - - -LttvTracefileContext * -lttv_context_new_tracefile_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self); -} - -/**************************************************************************** - * lttv_traceset_context_compute_time_span - * - * Keep the Time_Span is sync with on the fly addition and removal of traces - * in a trace set. It must be called each time a trace is added/removed from - * the traceset. It could be more efficient to call it only once a bunch - * of traces are loaded, but the calculation is not long, so it's not - * critical. - * - * Author : Xang Xiu Yang - * Imported from gtkTraceSet.c by Mathieu Desnoyers - ***************************************************************************/ -static void lttv_traceset_context_compute_time_span( - LttvTracesetContext *self, - TimeInterval *Time_Span) -{ - LttvTraceset * traceset = self->ts; - int numTraces = lttv_traceset_number(traceset); - int i; - LttTime s, e; - LttvTraceContext *tc; - LttTrace * trace; - - for(i=0; itraces[i]; - trace = tc->t; - - ltt_trace_time_span_get(trace, &s, &e); - - if(i==0){ - Time_Span->startTime = s; - Time_Span->endTime = e; - }else{ - if(s.tv_sec < Time_Span->startTime.tv_sec || - (s.tv_sec == Time_Span->startTime.tv_sec - && s.tv_nsec < Time_Span->startTime.tv_nsec)) - Time_Span->startTime = s; - if(e.tv_sec > Time_Span->endTime.tv_sec || - (e.tv_sec == Time_Span->endTime.tv_sec && - e.tv_nsec > Time_Span->endTime.tv_nsec)) - Time_Span->endTime = e; - } - } -} - - -static void -init(LttvTracesetContext *self, LttvTraceset *ts) -{ - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTracefileContext *tfc; - - LttTime null_time = {0, 0}; - - nb_trace = lttv_traceset_number(ts); - self->ts = ts; - self->traces = g_new(LttvTraceContext *, nb_trace); - self->before = lttv_hooks_new(); - self->after = lttv_hooks_new(); - self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - self->ts_a = lttv_traceset_attribute(ts); - for(i = 0 ; i < nb_trace ; i++) { - tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self); - self->traces[i] = tc; - - tc->ts_context = self; - tc->index = i; - tc->vt = lttv_traceset_get(ts, i); - tc->t = lttv_trace(tc->vt); - tc->check = lttv_hooks_new(); - tc->before = lttv_hooks_new(); - tc->after = lttv_hooks_new(); - tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - tc->t_a = lttv_trace_attribute(tc->vt); - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - tc->control_tracefiles = g_new(LttvTracefileContext *, nb_control); - tc->per_cpu_tracefiles = g_new(LttvTracefileContext *, nb_per_cpu); - - for(j = 0 ; j < nb_tracefile ; j++) { - tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self); - if(j < nb_control) { - tc->control_tracefiles[j] = tfc; - tfc->control = TRUE; - tfc->index = j; - tfc->tf = ltt_trace_control_tracefile_get(tc->t, j); - } - else { - tc->per_cpu_tracefiles[j - nb_control] = tfc; - tfc->control = FALSE; - tfc->index = j - nb_control; - tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control); - } - tfc->t_context = tc; - tfc->check = lttv_hooks_new(); - tfc->before = lttv_hooks_new(); - tfc->after = lttv_hooks_new(); - tfc->check_event = lttv_hooks_new(); - tfc->before_event = lttv_hooks_new(); - tfc->before_event_by_id = lttv_hooks_by_id_new(); - tfc->after_event = lttv_hooks_new(); - tfc->after_event_by_id = lttv_hooks_by_id_new(); - tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - } - } - lttv_process_traceset_seek_time(self, null_time); - /*CHECK why dynamically allocate the time span... and the casing is wroNg*/ - self->Time_Span = g_new(TimeInterval,1); - lttv_traceset_context_compute_time_span(self, self->Time_Span); -} - - -void fini(LttvTracesetContext *self) -{ - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTracefileContext *tfc; - - LttvTraceset *ts = self->ts; - - g_free(self->Time_Span); - - lttv_hooks_destroy(self->before); - lttv_hooks_destroy(self->after); - //FIXME : segfault - g_object_unref(self->a); - - nb_trace = lttv_traceset_number(ts); - - for(i = 0 ; i < nb_trace ; i++) { - tc = self->traces[i]; - - lttv_hooks_destroy(tc->check); - lttv_hooks_destroy(tc->before); - lttv_hooks_destroy(tc->after); - g_object_unref(tc->a); - - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) tfc = tc->control_tracefiles[j]; - else tfc = tc->per_cpu_tracefiles[j - nb_control]; - - lttv_hooks_destroy(tfc->check); - lttv_hooks_destroy(tfc->before); - lttv_hooks_destroy(tfc->after); - lttv_hooks_destroy(tfc->check_event); - lttv_hooks_destroy(tfc->before_event); - lttv_hooks_by_id_destroy(tfc->before_event_by_id); - lttv_hooks_destroy(tfc->after_event); - lttv_hooks_by_id_destroy(tfc->after_event_by_id); - g_object_unref(tfc->a); - g_object_unref(tfc); - } - g_free(tc->control_tracefiles); - g_free(tc->per_cpu_tracefiles); - g_object_unref(tc); - } - g_free(self->traces); -} - - -void lttv_traceset_context_add_hooks(LttvTracesetContext *self, - LttvHooks *before_traceset, - LttvHooks *after_traceset, - LttvHooks *check_trace, - LttvHooks *before_trace, - LttvHooks *after_trace, - LttvHooks *check_tracefile, - LttvHooks *before_tracefile, - LttvHooks *after_tracefile, - LttvHooks *check_event, - LttvHooks *before_event, - LttvHooks *after_event) -{ - LttvTraceset *ts = self->ts; - - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTracefileContext *tfc; - - void *hook_data; - - lttv_hooks_add_list(self->before, before_traceset); - lttv_hooks_add_list(self->after, after_traceset); - nb_trace = lttv_traceset_number(ts); - - for(i = 0 ; i < nb_trace ; i++) { - tc = self->traces[i]; - lttv_hooks_add_list(tc->check, check_trace); - lttv_hooks_add_list(tc->before, before_trace); - lttv_hooks_add_list(tc->after, after_trace); - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfc = tc->control_tracefiles[j]; - } - else { - tfc = tc->per_cpu_tracefiles[j-nb_control]; - } - lttv_hooks_add_list(tfc->check, check_tracefile); - lttv_hooks_add_list(tfc->before, before_tracefile); - lttv_hooks_add_list(tfc->after, after_tracefile); - lttv_hooks_add_list(tfc->check_event, check_event); - lttv_hooks_add_list(tfc->before_event, before_event); - lttv_hooks_add_list(tfc->after_event, after_event); - } - } -} - - -void lttv_traceset_context_remove_hooks(LttvTracesetContext *self, - LttvHooks *before_traceset, - LttvHooks *after_traceset, - LttvHooks *check_trace, - LttvHooks *before_trace, - LttvHooks *after_trace, - LttvHooks *check_tracefile, - LttvHooks *before_tracefile, - LttvHooks *after_tracefile, - LttvHooks *check_event, - LttvHooks *before_event, - LttvHooks *after_event) -{ - LttvTraceset *ts = self->ts; - - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTracefileContext *tfc; - - void *hook_data; - - lttv_hooks_remove_list(self->before, before_traceset); - lttv_hooks_remove_list(self->after, after_traceset); - nb_trace = lttv_traceset_number(ts); - - for(i = 0 ; i < nb_trace ; i++) { - tc = self->traces[i]; - lttv_hooks_remove_list(tc->check, check_trace); - lttv_hooks_remove_list(tc->before, before_trace); - lttv_hooks_remove_list(tc->after, after_trace); - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfc = tc->control_tracefiles[j]; - } - else { - tfc = tc->per_cpu_tracefiles[j-nb_control]; - } - lttv_hooks_remove_list(tfc->check, check_tracefile); - lttv_hooks_remove_list(tfc->before, before_tracefile); - lttv_hooks_remove_list(tfc->after, after_tracefile); - lttv_hooks_remove_list(tfc->check_event, check_event); - lttv_hooks_remove_list(tfc->before_event, before_event); - lttv_hooks_remove_list(tfc->after_event, after_event); - } - } -} - -void lttv_trace_context_add_hooks(LttvTraceContext *tc, - LttvHooks *check_trace, - LttvHooks *before_trace, - LttvHooks *after_trace) -{ - lttv_hooks_add_list(tc->check, check_trace); - lttv_hooks_add_list(tc->before, before_trace); - lttv_hooks_add_list(tc->after, after_trace); -} - -void lttv_trace_context_remove_hooks(LttvTraceContext *tc, - LttvHooks *check_trace, - LttvHooks *before_trace, - LttvHooks *after_trace) -{ - lttv_hooks_remove_list(tc->check, check_trace); - lttv_hooks_remove_list(tc->before, before_trace); - lttv_hooks_remove_list(tc->after, after_trace); -} - -void lttv_tracefile_context_add_hooks(LttvTracefileContext *tfc, - LttvHooks *check_tracefile, - LttvHooks *before_tracefile, - LttvHooks *after_tracefile, - LttvHooks *check_event, - LttvHooks *before_event, - LttvHooks *after_event) -{ - lttv_hooks_add_list(tfc->check, check_tracefile); - lttv_hooks_add_list(tfc->before, before_tracefile); - lttv_hooks_add_list(tfc->after, after_tracefile); - lttv_hooks_add_list(tfc->check_event, check_event); - lttv_hooks_add_list(tfc->before_event, before_event); - lttv_hooks_add_list(tfc->after_event, after_event); -} - -void lttv_tracefile_context_remove_hooks(LttvTracefileContext *tfc, - LttvHooks *check_tracefile, - LttvHooks *before_tracefile, - LttvHooks *after_tracefile, - LttvHooks *check_event, - LttvHooks *before_event, - LttvHooks *after_event) -{ - lttv_hooks_remove_list(tfc->check, check_tracefile); - lttv_hooks_remove_list(tfc->before, before_tracefile); - lttv_hooks_remove_list(tfc->after, after_tracefile); - lttv_hooks_remove_list(tfc->check_event, check_event); - lttv_hooks_remove_list(tfc->before_event, before_event); - lttv_hooks_remove_list(tfc->after_event, after_event); -} - -void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc, - unsigned i, - LttvHooks *before_event_by_id, - LttvHooks *after_event_by_id) -{ - LttvHooks * h; - h = lttv_hooks_by_id_find(tfc->before_event_by_id, i); - lttv_hooks_add_list(h, before_event_by_id); - h = lttv_hooks_by_id_find(tfc->after_event_by_id, i); - lttv_hooks_add_list(h, after_event_by_id); -} - -void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc, - unsigned i) -{ - lttv_hooks_by_id_remove(tfc->before_event_by_id, i); - lttv_hooks_by_id_remove(tfc->after_event_by_id, i); -} - -static LttvTracesetContext * -new_traceset_context(LttvTracesetContext *self) -{ - return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL); -} - - -static LttvTraceContext * -new_trace_context(LttvTracesetContext *self) -{ - return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL); -} - - -static LttvTracefileContext * -new_tracefile_context(LttvTracesetContext *self) -{ - return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL); -} - - -static void -traceset_context_instance_init (GTypeInstance *instance, gpointer g_class) -{ - /* Be careful of anything which would not work well with shallow copies */ -} - - -static void -traceset_context_finalize (LttvTracesetContext *self) -{ - G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE))) - ->finalize(G_OBJECT(self)); -} - - -static void -traceset_context_class_init (LttvTracesetContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize; - klass->init = init; - klass->fini = fini; - klass->new_traceset_context = new_traceset_context; - klass->new_trace_context = new_trace_context; - klass->new_tracefile_context = new_tracefile_context; -} - - -GType -lttv_traceset_context_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracesetContextClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) traceset_context_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracesetContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) traceset_context_instance_init /* instance_init */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType", - &info, 0); - } - return type; -} - - -static void -trace_context_instance_init (GTypeInstance *instance, gpointer g_class) -{ - /* Be careful of anything which would not work well with shallow copies */ -} - - -static void -trace_context_finalize (LttvTraceContext *self) -{ - G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))-> - finalize(G_OBJECT(self)); -} - - -static void -trace_context_class_init (LttvTraceContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize; -} - - -GType -lttv_trace_context_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTraceContextClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) trace_context_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTraceContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) trace_context_instance_init /* instance_init */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType", - &info, 0); - } - return type; -} - - -static void -tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class) -{ - /* Be careful of anything which would not work well with shallow copies */ -} - - -static void -tracefile_context_finalize (LttvTracefileContext *self) -{ - G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE))) - ->finalize(G_OBJECT(self)); -} - - -static void -tracefile_context_class_init (LttvTracefileContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize; -} - - -GType -lttv_tracefile_context_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracefileContextClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) tracefile_context_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracefileContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) tracefile_context_instance_init /* instance_init */ - }; - - type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType", - &info, 0); - } - return type; -} - - -gint compare_tracefile(gconstpointer a, gconstpointer b) -{ - return ltt_time_compare(*((LttTime *)a), *((LttTime *)b)); -} - - -gboolean get_first(gpointer key, gpointer value, gpointer user_data) { - *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value; - return TRUE; -} - - -void lttv_process_traceset(LttvTracesetContext *self, LttTime end, - unsigned maxNumEvents) -{ - 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; - - 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); - - 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); - 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]; - } - - 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); - } - } - } - } - } - } - - /* Get the next event from the pqueue, call its hooks, - reinsert in the pqueue the following event from the same tracefile - unless the tracefile is finished or the event is later than the - start time. */ - - while(TRUE) { - tfc = NULL; - g_tree_foreach(pqueue, get_first, &tfc); - if(tfc == NULL) break; - - /* 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; - } - } - previous_timestamp = tfc->timestamp; - - - /* Get the tracefile with an event for the smallest time found. If two - or more tracefiles have events for the same time, hope that lookup - and remove are consistent. */ - - tfc = g_tree_lookup(pqueue, &(tfc->timestamp)); - g_tree_remove(pqueue, &(tfc->timestamp)); - - if(!lttv_hooks_call(tfc->check_event, tfc)) { - id = ltt_event_eventtype_id(tfc->e); - lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc); - lttv_hooks_call(tfc->before_event, tfc); - lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc); - lttv_hooks_call(tfc->after_event, tfc); - } - - event = ltt_tracefile_read(tfc->tf); - if(event != NULL) { - tfc->e = event; - tfc->timestamp = ltt_event_time(event); - 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); - } - } - - /* Call all the after_tracefile, after_trace and after_traceset hooks. */ - - for(i = 0, j = 0 ; i < traces->len ; i++) { - tc = traces->pdata[i]; - while(j < tracefiles->len) { - tfc = tracefiles->pdata[j]; - - if(tfc->t_context == tc) { - lttv_hooks_call(tfc->after, tfc); - j++; - } - else break; - } - lttv_hooks_call(tc->after, tc); - } - - g_assert(j == tracefiles->len); - lttv_hooks_call(self->after, self); - - /* Free the traces, tracefiles and pqueue */ - - g_ptr_array_free(tracefiles, TRUE); - g_ptr_array_free(traces, TRUE); - g_tree_destroy(pqueue); -} - - -void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start) -{ - guint i, nb_control, nb_per_cpu, nb_tracefile; - - LttvTracefileContext *tfc; - - LttEvent *event; - - nb_control = ltt_trace_control_tracefile_number(self->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->t); - nb_tracefile = nb_control + nb_per_cpu; - for(i = 0 ; i < nb_tracefile ; i++) { - if(i < nb_control) tfc = self->control_tracefiles[i]; - else tfc = self->per_cpu_tracefiles[i - nb_control]; - - ltt_tracefile_seek_time(tfc->tf, start); - event = ltt_tracefile_read(tfc->tf); - tfc->e = event; - if(event != NULL) tfc->timestamp = ltt_event_time(event); - } -} - - -void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start) -{ - guint i, nb_trace; - - LttvTraceContext *tc; - - nb_trace = lttv_traceset_number(self->ts); - for(i = 0 ; i < nb_trace ; i++) { - tc = self->traces[i]; - lttv_process_trace_seek_time(tc, start); - } -} - - -static LttField * -find_field(LttEventType *et, const char *field) -{ - LttType *t; - - LttField *f; - - guint i, nb; - - char *name; - - if(field == NULL) return NULL; - - f = ltt_eventtype_field(et); - t = ltt_eventtype_type(et); - g_assert(ltt_type_class(t) == LTT_STRUCT); - nb = ltt_type_member_number(t); - for(i = 0 ; i < nb ; i++) { - ltt_type_member_type(t, i, &name); - if(strcmp(name, field) == 0) break; - } - g_assert(i < nb); - return ltt_field_member(f, i); -} - - -void -lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type, - char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th) -{ - LttFacility *f; - - LttEventType *et; - - guint nb, pos, i; - - char *name; - - nb = ltt_trace_facility_find(t, facility, &pos); - if(nb < 1) g_error("No %s facility", facility); - f = ltt_trace_facility_get(t, pos); - et = ltt_facility_eventtype_get_by_name(f, event_type); - if(et == NULL) g_error("Event %s does not exist", event_type); - - th->h = h; - th->id = ltt_eventtype_id(et); - th->f1 = find_field(et, field1); - th->f2 = find_field(et, field2); - th->f3 = find_field(et, field3); -} - - diff --git a/ltt/branches/poly/lttv/mainLib/state.c b/ltt/branches/poly/lttv/mainLib/state.c deleted file mode 100644 index dbdb11ce..00000000 --- a/ltt/branches/poly/lttv/mainLib/state.c +++ /dev/null @@ -1,1198 +0,0 @@ - -#include -#include -#include -#include -#include - -LttvExecutionMode - LTTV_STATE_MODE_UNKNOWN, - LTTV_STATE_USER_MODE, - LTTV_STATE_SYSCALL, - LTTV_STATE_TRAP, - LTTV_STATE_IRQ; - -LttvExecutionSubmode - LTTV_STATE_SUBMODE_UNKNOWN, - LTTV_STATE_SUBMODE_NONE; - -LttvProcessStatus - LTTV_STATE_UNNAMED, - LTTV_STATE_WAIT_FORK, - LTTV_STATE_WAIT_CPU, - LTTV_STATE_EXIT, - LTTV_STATE_WAIT, - LTTV_STATE_RUN; - -static GQuark - LTTV_STATE_TRACEFILES, - LTTV_STATE_PROCESSES, - LTTV_STATE_PROCESS, - LTTV_STATE_EVENT, - LTTV_STATE_SAVED_STATES, - LTTV_STATE_TIME, - LTTV_STATE_HOOKS; - - -static void fill_name_tables(LttvTraceState *tcs); - -static void free_name_tables(LttvTraceState *tcs); - -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) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container); -} - - -void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); -} - - -void lttv_state_saved_state_free(LttvTraceState *self, - LttvAttribute *container) -{ - LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); -} - - -static void -restore_init_state(LttvTraceState *self) -{ - guint i, nb_control, nb_per_cpu, nb_tracefile; - - LttvTracefileState *tfcs; - - 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->nb_event = 0; - - nb_control = ltt_trace_control_tracefile_number(self->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(i = 0 ; i < nb_tracefile ; i++) { - if(i < nb_control) { - tfcs = LTTV_TRACEFILE_STATE(self->parent.control_tracefiles[i]); - } - else { - tfcs = LTTV_TRACEFILE_STATE(self->parent.per_cpu_tracefiles[i - nb_control]); - } - - tfcs->parent.timestamp = null_time; - tfcs->saved_position = 0; - tfcs->process = create_process(tfcs, NULL,0); - } -} - - -static void -init(LttvTracesetState *self, LttvTraceset *ts) -{ - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTraceState *tcs; - - LttvTracefileState *tfcs; - - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - init((LttvTracesetContext *)self, ts); - - nb_trace = lttv_traceset_number(ts); - for(i = 0 ; i < nb_trace ; i++) { - tc = self->parent.traces[i]; - tcs = (LttvTraceState *)tc; - tcs->save_interval = 100000; - fill_name_tables(tcs); - - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfcs = LTTV_TRACEFILE_STATE(tc->control_tracefiles[j]); - } - else { - tfcs = LTTV_TRACEFILE_STATE(tc->per_cpu_tracefiles[j - nb_control]); - } - tfcs->cpu_name= g_quark_from_string(ltt_tracefile_name(tfcs->parent.tf)); - } - tcs->processes = NULL; - restore_init_state(tcs); - } -} - - -static void -fini(LttvTracesetState *self) -{ - guint i, j, nb_trace, nb_tracefile; - - LttvTraceState *tcs; - - LttvTracefileState *tfcs; - - nb_trace = lttv_traceset_number(LTTV_TRACESET_CONTEXT(self)->ts); - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceState *)(LTTV_TRACESET_CONTEXT(self)->traces[i]); - lttv_state_free_process_table(tcs->processes); - tcs->processes = NULL; - free_name_tables(tcs); - } - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - fini((LttvTracesetContext *)self); -} - - -static LttvTracesetContext * -new_traceset_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE, NULL)); -} - - -static LttvTraceContext * -new_trace_context(LttvTracesetContext *self) -{ - return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE, NULL)); -} - - -static LttvTracefileContext * -new_tracefile_context(LttvTracesetContext *self) -{ - return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE, NULL)); -} - - -static void copy_process_state(gpointer key, gpointer value,gpointer user_data) -{ - LttvProcessState *process, *new_process; - - GHashTable *new_processes = (GHashTable *)user_data; - - guint i; - - process = (LttvProcessState *)value; - new_process = g_new(LttvProcessState, 1); - *new_process = *process; - new_process->execution_stack = g_array_new(FALSE, FALSE, - sizeof(LttvExecutionState)); - g_array_set_size(new_process->execution_stack,process->execution_stack->len); - for(i = 0 ; i < process->execution_stack->len; i++) { - g_array_index(new_process->execution_stack, LttvExecutionState, i) = - g_array_index(process->execution_stack, LttvExecutionState, i); - } - 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); -} - - -static GHashTable *lttv_state_copy_process_table(GHashTable *processes) -{ - GHashTable *new_processes = g_hash_table_new(g_direct_hash, g_direct_equal); - - g_hash_table_foreach(processes, copy_process_state, new_processes); - return new_processes; -} - - -/* The saved state for each trace contains a member "processes", which - stores a copy of the process table, and a member "tracefiles" with - one entry per tracefile. Each tracefile has a "process" member pointing - to the current process and a "position" member storing the tracefile - position (needed to seek to the current "next" event. */ - -static void state_save(LttvTraceState *self, LttvAttribute *container) -{ - guint i, nb_control, nb_per_cpu, nb_tracefile; - - LttvTracefileState *tfcs; - - LttvAttribute *tracefiles_tree, *tracefile_tree; - - LttvAttributeType type; - - LttvAttributeValue value; - - LttvAttributeName name; - - LttEventPosition *ep; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - - value = lttv_attribute_add(container, LTTV_STATE_PROCESSES, - LTTV_POINTER); - *(value.v_pointer) = lttv_state_copy_process_table(self->processes); - - nb_control = ltt_trace_control_tracefile_number(self->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - - for(i = 0 ; i < nb_tracefile ; i++) { - if(i < nb_control) - tfcs = (LttvTracefileState *)self->parent.control_tracefiles[i]; - else tfcs = (LttvTracefileState *) - self->parent.per_cpu_tracefiles[i - nb_control]; - - tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - value = lttv_attribute_add(tracefiles_tree, i, - LTTV_GOBJECT); - *(value.v_gobject) = (GObject *)tracefile_tree; - value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS, - LTTV_UINT); - *(value.v_uint) = tfcs->process->pid; - value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT, - LTTV_POINTER); - if(tfcs->parent.e == NULL) *(value.v_pointer) = NULL; - else { - ep = ltt_event_position_new(); - ltt_event_position(tfcs->parent.e, ep); - *(value.v_pointer) = ep; - } - } -} - - -static void state_restore(LttvTraceState *self, LttvAttribute *container) -{ - guint i, nb_control, nb_per_cpu, nb_tracefile; - - LttvTracefileState *tfcs; - - LttvAttribute *tracefiles_tree, *tracefile_tree; - - LttvAttributeType type; - - LttvAttributeValue value; - - LttvAttributeName name; - - LttEventPosition *ep; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - - type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, - &value); - g_assert(type == LTTV_POINTER); - lttv_state_free_process_table(self->processes); - self->processes = lttv_state_copy_process_table(*(value.v_pointer)); - - nb_control = ltt_trace_control_tracefile_number(self->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - - for(i = 0 ; i < nb_tracefile ; i++) { - if(i < nb_control) tfcs = (LttvTracefileState *) - self->parent.control_tracefiles[i]; - else tfcs = (LttvTracefileState *) - self->parent.per_cpu_tracefiles[i - nb_control]; - - type = lttv_attribute_get(tracefiles_tree, i, &name, &value); - g_assert(type == LTTV_GOBJECT); - tracefile_tree = *((LttvAttribute **)(value.v_gobject)); - - 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)); - type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, - &value); - g_assert(type == LTTV_POINTER); - if(*(value.v_pointer) == NULL) tfcs->parent.e = NULL; - else { - ep = *(value.v_pointer); - ltt_tracefile_seek_position(tfcs->parent.tf, ep); - tfcs->parent.e = ltt_tracefile_read(tfcs->parent.tf); - tfcs->parent.timestamp = ltt_event_time(tfcs->parent.e); - } - } -} - - -static void state_saved_free(LttvTraceState *self, LttvAttribute *container) -{ - guint i, nb_control, nb_per_cpu, nb_tracefile; - - LttvTracefileState *tfcs; - - LttvAttribute *tracefiles_tree, *tracefile_tree; - - LttvAttributeType type; - - LttvAttributeValue value; - - LttvAttributeName name; - - LttEventPosition *ep; - - tracefiles_tree = lttv_attribute_find_subdir(container, - LTTV_STATE_TRACEFILES); - lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES); - - type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES, - &value); - g_assert(type == LTTV_POINTER); - lttv_state_free_process_table(*(value.v_pointer)); - *(value.v_pointer) = NULL; - lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES); - - nb_control = ltt_trace_control_tracefile_number(self->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - - for(i = 0 ; i < nb_tracefile ; i++) { - if(i < nb_control) tfcs = (LttvTracefileState *) - self->parent.control_tracefiles[i]; - else tfcs = (LttvTracefileState *) - self->parent.per_cpu_tracefiles[i - nb_control]; - - type = lttv_attribute_get(tracefiles_tree, i, &name, &value); - g_assert(type == LTTV_GOBJECT); - tracefile_tree = *((LttvAttribute **)(value.v_gobject)); - - type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT, - &value); - g_assert(type == LTTV_POINTER); - if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer)); - } - lttv_attribute_recursive_free(tracefiles_tree); -} - - -static void -fill_name_tables(LttvTraceState *tcs) -{ - int i, nb; - - char *f_name, *e_name; - - LttvTraceHook h; - - LttEventType *et; - - LttType *t; - - GString *fe_name = g_string_new(""); - - nb = ltt_trace_eventtype_number(tcs->parent.t); - tcs->eventtype_names = g_new(GQuark, nb); - for(i = 0 ; i < nb ; i++) { - et = ltt_trace_eventtype_get(tcs->parent.t, i); - e_name = ltt_eventtype_name(et); - f_name = ltt_facility_name(ltt_eventtype_facility(et)); - g_string_printf(fe_name, "%s.%s", f_name, e_name); - tcs->eventtype_names[i] = g_quark_from_string(fe_name->str); - } - - lttv_trace_find_hook(tcs->parent.t, "core", "syscall_entry", - "syscall_id", NULL, NULL, NULL, &h); - t = ltt_field_type(h.f1); - nb = ltt_type_element_number(t); - - /* CHECK syscalls should be an emun but currently are not! - tcs->syscall_names = g_new(GQuark, nb); - - for(i = 0 ; i < nb ; i++) { - tcs->syscall_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); - } - */ - - tcs->syscall_names = g_new(GQuark, 256); - for(i = 0 ; i < 256 ; i++) { - g_string_printf(fe_name, "syscall %d", i); - tcs->syscall_names[i] = g_quark_from_string(fe_name->str); - } - - lttv_trace_find_hook(tcs->parent.t, "core", "trap_entry", - "trap_id", NULL, NULL, NULL, &h); - t = ltt_field_type(h.f1); - nb = ltt_type_element_number(t); - - /* - tcs->trap_names = g_new(GQuark, nb); - for(i = 0 ; i < nb ; i++) { - tcs->trap_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); - } - */ - - tcs->trap_names = g_new(GQuark, 256); - for(i = 0 ; i < 256 ; i++) { - g_string_printf(fe_name, "trap %d", i); - tcs->trap_names[i] = g_quark_from_string(fe_name->str); - } - - lttv_trace_find_hook(tcs->parent.t, "core", "irq_entry", - "irq_id", NULL, NULL, NULL, &h); - t = ltt_field_type(h.f1); - nb = ltt_type_element_number(t); - - /* - tcs->irq_names = g_new(GQuark, nb); - for(i = 0 ; i < nb ; i++) { - tcs->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); - } - */ - - tcs->irq_names = g_new(GQuark, 256); - for(i = 0 ; i < 256 ; i++) { - g_string_printf(fe_name, "irq %d", i); - tcs->irq_names[i] = g_quark_from_string(fe_name->str); - } - - g_string_free(fe_name, TRUE); -} - - -static void -free_name_tables(LttvTraceState *tcs) -{ - g_free(tcs->eventtype_names); - g_free(tcs->syscall_names); - g_free(tcs->trap_names); - g_free(tcs->irq_names); -} - - -static void push_state(LttvTracefileState *tfs, LttvExecutionMode t, - guint state_id) -{ - LttvExecutionState *es; - - LttvProcessState *process = tfs->process; - - guint depth = process->execution_stack->len; - - g_array_set_size(process->execution_stack, depth + 1); - es = &g_array_index(process->execution_stack, LttvExecutionState, depth); - es->t = t; - es->n = state_id; - es->entry = es->change = tfs->parent.timestamp; - es->s = process->state->s; - process->state = es; -} - - -static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) -{ - LttvProcessState *process = tfs->process; - - guint depth = process->execution_stack->len - 1; - - if(process->state->t != t){ - g_warning("Different execution mode type (%d.%09d): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); - g_warning("process state has %s when pop_int is %s\n", - g_quark_to_string(process->state->t), - g_quark_to_string(t)); - g_warning("{ %u, %u, %s, %s }\n", - process->pid, - process->ppid, - g_quark_to_string(process->name), - g_quark_to_string(process->state->s)); - return; - } - - if(depth == 0){ - g_warning("Trying to pop last state on stack (%d.%09d): ignore it\n", - tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); - return; - } - - g_array_remove_index(process->execution_stack, depth); - depth--; - process->state = &g_array_index(process->execution_stack, LttvExecutionState, - depth); - process->state->change = tfs->parent.timestamp; -} - - -static LttvProcessState *create_process(LttvTracefileState *tfs, - LttvProcessState *parent, guint pid) -{ - LttvProcessState *process = g_new(LttvProcessState, 1); - - LttvExecutionState *es; - - LttvTraceContext *tc; - - LttvTraceState *tcs; - - char buffer[128]; - - tcs = (LttvTraceState *)tc = tfs->parent.t_context; - - g_hash_table_insert(tcs->processes, GUINT_TO_POINTER(pid), process); - process->pid = pid; - - if(parent) { - process->ppid = parent->pid; - process->name = parent->name; - } - else { - process->ppid = 0; - process->name = LTTV_STATE_UNNAMED; - } - - process->creation_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->execution_stack = g_array_new(FALSE, FALSE, - sizeof(LttvExecutionState)); - g_array_set_size(process->execution_stack, 1); - es = process->state = &g_array_index(process->execution_stack, - LttvExecutionState, 0); - es->t = LTTV_STATE_USER_MODE; - es->n = LTTV_STATE_SUBMODE_NONE; - es->entry = tfs->parent.timestamp; - es->change = tfs->parent.timestamp; - es->s = LTTV_STATE_WAIT_FORK; - - return process; -} - - -LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs, - 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); - return process; -} - - -static void exit_process(LttvTracefileState *tfs, LttvProcessState *process) -{ - LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context); - - g_hash_table_remove(ts->processes, GUINT_TO_POINTER(process->pid)); - g_array_free(process->execution_stack, TRUE); - g_free(process); -} - - -static void free_process_state(gpointer key, gpointer value,gpointer user_data) -{ - g_array_free(((LttvProcessState *)value)->execution_stack, TRUE); - g_free(value); -} - - -static void lttv_state_free_process_table(GHashTable *processes) -{ - g_hash_table_foreach(processes, free_process_state, NULL); - g_hash_table_destroy(processes); -} - - -static gboolean syscall_entry(void *hook_data, void *call_data) -{ - LttField *f = ((LttvTraceHook *)hook_data)->f1; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - LttvExecutionSubmode submode; - - submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[ - ltt_event_get_unsigned(s->parent.e, f)]; - push_state(s, LTTV_STATE_SYSCALL, submode); - return FALSE; -} - - -static gboolean syscall_exit(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - - pop_state(s, LTTV_STATE_SYSCALL); - return FALSE; -} - - -static gboolean trap_entry(void *hook_data, void *call_data) -{ - LttField *f = ((LttvTraceHook *)hook_data)->f1; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - LttvExecutionSubmode submode; - - submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[ - ltt_event_get_unsigned(s->parent.e, f)]; - push_state(s, LTTV_STATE_TRAP, submode); - return FALSE; -} - - -static gboolean trap_exit(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - - pop_state(s, LTTV_STATE_TRAP); - return FALSE; -} - - -static gboolean irq_entry(void *hook_data, void *call_data) -{ - LttField *f = ((LttvTraceHook *)hook_data)->f1; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - LttvExecutionSubmode submode; - - submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[ - ltt_event_get_unsigned(s->parent.e, f)]; - - /* Do something with the info about being in user or system mode when int? */ - push_state(s, LTTV_STATE_IRQ, submode); - return FALSE; -} - - -static gboolean irq_exit(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - - pop_state(s, LTTV_STATE_IRQ); - return FALSE; -} - - -static gboolean schedchange(void *hook_data, void *call_data) -{ - LttvTraceHook *h = (LttvTraceHook *)hook_data; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - guint pid_in, pid_out, state_out; - - pid_in = ltt_event_get_unsigned(s->parent.e, h->f1); - pid_out = ltt_event_get_unsigned(s->parent.e, h->f2); - state_out = ltt_event_get_unsigned(s->parent.e, h->f3); - - if(s->process != NULL) { - - if(state_out == 0) s->process->state->s = LTTV_STATE_WAIT_CPU; - else if(s->process->state->s == LTTV_STATE_EXIT) - exit_process(s, s->process); - else s->process->state->s = LTTV_STATE_WAIT; - - if(s->process->pid == 0) - s->process->pid = pid_out; - - s->process->state->change = s->parent.timestamp; - } - s->process = lttv_state_find_process(s, pid_in); - s->process->state->s = LTTV_STATE_RUN; - s->process->state->change = s->parent.timestamp; - return FALSE; -} - - -static gboolean process_fork(void *hook_data, void *call_data) -{ - LttField *f = ((LttvTraceHook *)hook_data)->f1; - - LttvTracefileState *s = (LttvTracefileState *)call_data; - - guint child_pid; - - child_pid = ltt_event_get_unsigned(s->parent.e, f); - create_process(s, s->process, child_pid); - return FALSE; -} - - -static gboolean process_exit(void *hook_data, void *call_data) -{ - LttvTracefileState *s = (LttvTracefileState *)call_data; - - if(s->process != NULL) { - s->process->state->s = LTTV_STATE_EXIT; - } - return FALSE; -} - - -void lttv_state_add_event_hooks(LttvTracesetState *self) -{ - LttvTraceset *traceset = self->parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceState *ts; - - LttvTracefileState *tfs; - - GArray *hooks; - - LttvTraceHook hook; - - LttvAttributeValue val; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = (LttvTraceState *)self->parent.traces[i]; - - /* Find the eventtype id for the following events and register the - associated by id hooks. */ - - hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); - g_array_set_size(hooks, 9); - - lttv_trace_find_hook(ts->parent.t, "core","syscall_entry","syscall_id", - NULL, NULL, syscall_entry, &g_array_index(hooks, LttvTraceHook, 0)); - - lttv_trace_find_hook(ts->parent.t, "core", "syscall_exit", NULL, NULL, - NULL, syscall_exit, &g_array_index(hooks, LttvTraceHook, 1)); - - lttv_trace_find_hook(ts->parent.t, "core", "trap_entry", "trap_id", - NULL, NULL, trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); - - lttv_trace_find_hook(ts->parent.t, "core", "trap_exit", NULL, NULL, NULL, - trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); - - lttv_trace_find_hook(ts->parent.t, "core", "irq_entry", "irq_id", NULL, - NULL, irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); - - lttv_trace_find_hook(ts->parent.t, "core", "irq_exit", NULL, NULL, NULL, - irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); - - lttv_trace_find_hook(ts->parent.t, "core", "schedchange", "in", "out", - "out_state", schedchange, &g_array_index(hooks, LttvTraceHook, 6)); - - lttv_trace_find_hook(ts->parent.t, "core", "process_fork", "child_pid", - NULL, NULL, process_fork, &g_array_index(hooks, LttvTraceHook, 7)); - - lttv_trace_find_hook(ts->parent.t, "core", "process_exit", NULL, NULL, - NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 8)); - - /* Add these hooks to each before_event_by_id hooks list */ - - nb_control = ltt_trace_control_tracefile_number(ts->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); - } - else { - tfs = LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); - } - - for(k = 0 ; k < hooks->len ; k++) { - hook = g_array_index(hooks, LttvTraceHook, k); - lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, - hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k)); - } - } - lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val); - *(val.v_pointer) = hooks; - } -} - - -void lttv_state_remove_event_hooks(LttvTracesetState *self) -{ - LttvTraceset *traceset = self->parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceState *ts; - - LttvTracefileState *tfs; - - GArray *hooks; - - LttvTraceHook hook; - - LttvAttributeValue val; - - 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); - hooks = *(val.v_pointer); - - /* Add these hooks to each before_event_by_id hooks list */ - - nb_control = ltt_trace_control_tracefile_number(ts->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); - } - else { - tfs = LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); - } - - for(k = 0 ; k < hooks->len ; k++) { - hook = g_array_index(hooks, LttvTraceHook, k); - lttv_hooks_remove_data( - lttv_hooks_by_id_find(tfs->parent.after_event_by_id, - hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k)); - } - } - g_array_free(hooks, TRUE); - } -} - - -static gboolean block_end(void *hook_data, void *call_data) -{ - LttvTracefileState *tfcs = (LttvTracefileState *)call_data; - - LttvTraceState *tcs = (LttvTraceState *)(tfcs->parent.t_context); - - LttEventPosition *ep = ltt_event_position_new(); - - guint nb_block, nb_event; - - LttTracefile *tf; - - LttvAttribute *saved_states_tree, *saved_state_tree; - - LttvAttributeValue value; - - ltt_event_position(tfcs->parent.e, ep); - - ltt_event_position_get(ep, &nb_block, &nb_event, &tf); - tcs->nb_event += nb_event - tfcs->saved_position; - tfcs->saved_position = 0; - if(tcs->nb_event >= tcs->save_interval) { - saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, - LTTV_STATE_SAVED_STATES); - saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - value = lttv_attribute_add(saved_states_tree, - lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT); - *(value.v_gobject) = (GObject *)saved_state_tree; - value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME); - *(value.v_time) = tfcs->parent.timestamp; - lttv_state_save(tcs, saved_state_tree); - tcs->nb_event = 0; - } - return FALSE; -} - - -void lttv_state_save_add_event_hooks(LttvTracesetState *self) -{ - LttvTraceset *traceset = self->parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceState *ts; - - LttvTracefileState *tfs; - - LttvTraceHook hook; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = (LttvTraceState *)self->parent.traces[i]; - lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, - NULL, NULL, block_end, &hook); - - nb_control = ltt_trace_control_tracefile_number(ts->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); - } - else { - tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); - } - - lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, - hook.id), hook.h, NULL); - } - } -} - - -void lttv_state_save_remove_event_hooks(LttvTracesetState *self) -{ - LttvTraceset *traceset = self->parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceState *ts; - - LttvTracefileState *tfs; - - LttvTraceHook hook; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = LTTV_TRACE_STATE(self->parent.traces[i]); - lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL, - NULL, NULL, block_end, &hook); - - nb_control = ltt_trace_control_tracefile_number(ts->parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]); - } - else { - tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]); - } - - lttv_hooks_remove_data(lttv_hooks_by_id_find( - tfs->parent.after_event_by_id, hook.id), hook.h, NULL); - } - } -} - - -void lttv_state_restore_closest_state(LttvTracesetState *self, LttTime t) -{ - LttvTraceset *traceset = self->parent.ts; - - guint i, j, nb_trace, nb_saved_state; - - int min_pos, mid_pos, max_pos; - - LttvTraceState *tcs; - - LttvAttributeValue value; - - LttvAttributeType type; - - LttvAttributeName name; - - LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceState *)self->parent.traces[i]; - - saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a, - LTTV_STATE_SAVED_STATES); - min_pos = -1; - max_pos = lttv_attribute_get_number(saved_states_tree) - 1; - mid_pos = max_pos / 2; - while(min_pos < max_pos) { - type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value); - g_assert(type == LTTV_GOBJECT); - saved_state_tree = *((LttvAttribute **)(value.v_gobject)); - type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME, - &value); - g_assert(type == LTTV_TIME); - if(ltt_time_compare(*(value.v_time), t) < 0) { - min_pos = mid_pos; - closest_tree = saved_state_tree; - } - else max_pos = mid_pos - 1; - - mid_pos = (min_pos + max_pos + 1) / 2; - } - if(min_pos == -1) { - restore_init_state(tcs); - lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero); - } - else lttv_state_restore(tcs, closest_tree); - } -} - - -static void -traceset_state_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -traceset_state_finalize (LttvTracesetState *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -traceset_state_class_init (LttvTracesetContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize; - klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init; - klass->fini = (void (*)(LttvTracesetContext *self))fini; - klass->new_traceset_context = new_traceset_context; - klass->new_trace_context = new_trace_context; - klass->new_tracefile_context = new_tracefile_context; -} - - -GType -lttv_traceset_state_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracesetStateClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) traceset_state_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracesetContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) traceset_state_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType", - &info, 0); - } - return type; -} - - -static void -trace_state_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -trace_state_finalize (LttvTraceState *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -trace_state_class_init (LttvTraceStateClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize; - klass->state_save = state_save; - klass->state_restore = state_restore; - klass->state_saved_free = state_saved_free; -} - - -GType -lttv_trace_state_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTraceStateClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) trace_state_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTraceState), - 0, /* n_preallocs */ - (GInstanceInitFunc) trace_state_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE, - "LttvTraceStateType", &info, 0); - } - return type; -} - - -static void -tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -tracefile_state_finalize (LttvTracefileState *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -tracefile_state_class_init (LttvTracefileStateClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize; -} - - -GType -lttv_tracefile_state_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracefileStateClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) tracefile_state_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracefileState), - 0, /* n_preallocs */ - (GInstanceInitFunc) tracefile_state_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE, - "LttvTracefileStateType", &info, 0); - } - return type; -} - - -void lttv_state_init(int argc, char **argv) -{ - LTTV_STATE_UNNAMED = g_quark_from_string("unnamed"); - LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode"); - LTTV_STATE_USER_MODE = g_quark_from_string("user mode"); - LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork"); - LTTV_STATE_SYSCALL = g_quark_from_string("system call"); - LTTV_STATE_TRAP = g_quark_from_string("trap"); - LTTV_STATE_IRQ = g_quark_from_string("irq"); - LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode"); - LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)"); - LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu"); - LTTV_STATE_EXIT = g_quark_from_string("exiting"); - LTTV_STATE_WAIT = g_quark_from_string("wait for I/O"); - LTTV_STATE_RUN = g_quark_from_string("running"); - LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles"); - LTTV_STATE_PROCESSES = g_quark_from_string("processes"); - LTTV_STATE_PROCESS = g_quark_from_string("process"); - LTTV_STATE_EVENT = g_quark_from_string("event"); - LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states"); - LTTV_STATE_TIME = g_quark_from_string("time"); - LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks"); -} - -void lttv_state_destroy() -{ -} - - - - diff --git a/ltt/branches/poly/lttv/mainLib/stats.c b/ltt/branches/poly/lttv/mainLib/stats.c deleted file mode 100644 index 4265853d..00000000 --- a/ltt/branches/poly/lttv/mainLib/stats.c +++ /dev/null @@ -1,1180 +0,0 @@ - -#include -#include -#include -#include -#include - -#define BUF_SIZE 256 - -GQuark - LTTV_STATS_PROCESS_UNKNOWN, - LTTV_STATS_PROCESSES, - LTTV_STATS_CPU, - LTTV_STATS_MODE_TYPES, - LTTV_STATS_MODES, - LTTV_STATS_SUBMODES, - LTTV_STATS_EVENT_TYPES, - LTTV_STATS_CPU_TIME, - LTTV_STATS_ELAPSED_TIME, - LTTV_STATS_EVENTS, - LTTV_STATS_EVENTS_COUNT; - -static GQuark - LTTV_STATS_BEFORE_HOOKS, - LTTV_STATS_AFTER_HOOKS; - -static void remove_all_processes(GHashTable *processes); - -static void -find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu, - GQuark mode, GQuark sub_mode, LttvAttribute **events_tree, - LttvAttribute **event_types_tree); - -static void -init(LttvTracesetStats *self, LttvTraceset *ts) -{ - guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceContext *tc; - - LttvTraceStats *tcs; - - LttvTracefileContext *tfc; - - LttvTracefileStats *tfcs; - - LttTime timestamp = {0,0}; - - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> - init((LttvTracesetContext *)self, ts); - - self->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - nb_trace = lttv_traceset_number(ts); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); - tcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - - nb_control = ltt_trace_control_tracefile_number(tc->t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfcs = LTTV_TRACEFILE_STATS(tc->control_tracefiles[j]); - } - else { - tfcs = LTTV_TRACEFILE_STATS(tc->per_cpu_tracefiles[j - nb_control]); - } - - tfcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN, - tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN, - LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree, - &tfcs->current_event_types_tree); - } - } -} - - -static void -fini(LttvTracesetStats *self) -{ - guint i, j, nb_trace, nb_tracefile; - - LttvTraceset *ts; - - LttvTraceContext *tc; - - LttvTraceStats *tcs; - - LttvTracefileContext *tfc; - - LttvTracefileStats *tfcs; - - LttTime timestamp = {0,0}; - - lttv_attribute_recursive_free(self->stats); - ts = self->parent.parent.ts; - nb_trace = lttv_traceset_number(ts); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); - lttv_attribute_recursive_free(tcs->stats); - - nb_tracefile = ltt_trace_control_tracefile_number(tc->t); - for(j = 0 ; j < nb_tracefile ; j++) { - tfcs = (LttvTracefileStats *)tfc = tc->control_tracefiles[j]; - lttv_attribute_recursive_free(tfcs->stats); - tfcs->current_events_tree = NULL; - tfcs->current_event_types_tree = NULL; - } - - nb_tracefile = ltt_trace_per_cpu_tracefile_number(tc->t); - for(j = 0 ; j < nb_tracefile ; j++) { - tfcs = (LttvTracefileStats *)tfc = tc->per_cpu_tracefiles[j]; - lttv_attribute_recursive_free(tfcs->stats); - tfcs->current_events_tree = NULL; - tfcs->current_event_types_tree = NULL; - } - } - LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> - fini((LttvTracesetContext *)self); -} - - -static LttvTracesetContext * -new_traceset_context(LttvTracesetContext *self) -{ - return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL)); -} - - -static LttvTraceContext * -new_trace_context(LttvTracesetContext *self) -{ - return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL)); -} - - -static LttvTracefileContext * -new_tracefile_context(LttvTracesetContext *self) -{ - return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL)); -} - - -static void -traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -traceset_stats_finalize (LttvTracesetStats *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -traceset_stats_class_init (LttvTracesetContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize; - klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init; - klass->fini = (void (*)(LttvTracesetContext *self))fini; - klass->new_traceset_context = new_traceset_context; - klass->new_trace_context = new_trace_context; - klass->new_tracefile_context = new_tracefile_context; -} - - -GType -lttv_traceset_stats_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracesetStatsClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) traceset_stats_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracesetContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) traceset_stats_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACESET_STATE_TYPE, "LttvTracesetStatsType", - &info, 0); - } - return type; -} - - -static void -trace_stats_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -trace_stats_finalize (LttvTraceStats *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -trace_stats_class_init (LttvTraceContextClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize; -} - - -GType -lttv_trace_stats_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTraceStatsClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) trace_stats_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTraceStats), - 0, /* n_preallocs */ - (GInstanceInitFunc) trace_stats_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACE_STATE_TYPE, - "LttvTraceStatsType", &info, 0); - } - return type; -} - - -static void -tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class) -{ -} - - -static void -tracefile_stats_finalize (LttvTracefileStats *self) -{ - G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))-> - finalize(G_OBJECT(self)); -} - - -static void -tracefile_stats_class_init (LttvTracefileStatsClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize; -} - - -GType -lttv_tracefile_stats_get_type(void) -{ - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (LttvTracefileStatsClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) tracefile_stats_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (LttvTracefileStats), - 0, /* n_preallocs */ - (GInstanceInitFunc) tracefile_stats_instance_init /* instance_init */ - }; - - type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE, - "LttvTracefileStatsType", &info, 0); - } - return type; -} - - -static void -find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu, - GQuark mode, GQuark sub_mode, LttvAttribute **events_tree, - LttvAttribute **event_types_tree) -{ - LttvAttribute *a; - - LttvTraceStats *tcs = LTTV_TRACE_STATS(tfcs->parent.parent.t_context); - a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES); - a = lttv_attribute_find_subdir(a, tfcs->parent.process->pid_time); - a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU); - a = lttv_attribute_find_subdir(a, tfcs->parent.cpu_name); - a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES); - a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->t); - a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES); - a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->n); - *events_tree = a; - a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES); - *event_types_tree = a; -} - - -static void update_event_tree(LttvTracefileStats *tfcs) -{ - LttvExecutionState *es = tfcs->parent.process->state; - - find_event_tree(tfcs, tfcs->parent.process->pid_time, tfcs->parent.cpu_name, - es->t, es->n, &(tfcs->current_events_tree), - &(tfcs->current_event_types_tree)); -} - - -static void mode_change(LttvTracefileStats *tfcs) -{ - LttvAttributeValue cpu_time; - - LttTime delta; - - lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, - LTTV_TIME, &cpu_time); - delta = ltt_time_sub(tfcs->parent.parent.timestamp, - tfcs->parent.process->state->change); - *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta); -} - - -static void mode_end(LttvTracefileStats *tfcs) -{ - LttvAttributeValue elapsed_time, cpu_time; - - LttTime delta; - - lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME, - LTTV_TIME, &elapsed_time); - delta = ltt_time_sub(tfcs->parent.parent.timestamp, - tfcs->parent.process->state->entry); - *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta); - - lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, - LTTV_TIME, &cpu_time); - delta = ltt_time_sub(tfcs->parent.parent.timestamp, - tfcs->parent.process->state->change); - *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta); -} - - -static gboolean before_syscall_entry(void *hook_data, void *call_data) -{ - mode_change((LttvTracefileStats *)call_data); - return FALSE; -} - - -static gboolean after_syscall_entry(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_syscall_exit(void *hook_data, void *call_data) -{ - mode_end((LttvTracefileStats *)call_data); - return FALSE; -} - - -static gboolean after_syscall_exit(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_trap_entry(void *hook_data, void *call_data) -{ - mode_change((LttvTracefileStats *)call_data); - return FALSE; -} - - -static gboolean after_trap_entry(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_trap_exit(void *hook_data, void *call_data) -{ - mode_end((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean after_trap_exit(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_irq_entry(void *hook_data, void *call_data) -{ - mode_change((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean after_irq_entry(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_irq_exit(void *hook_data, void *call_data) -{ - mode_end((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean after_irq_exit(void *hook_data, void *call_data) -{ - update_event_tree((LttvTracefileStats *)call_data); - return FALSE; -} - - -gboolean before_schedchange(void *hook_data, void *call_data) -{ - LttvTraceHook *h = (LttvTraceHook *)hook_data; - - LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data; - - guint pid_in, pid_out, state_out; - - LttvProcessState *process; - - pid_in = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f1); - pid_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f2); - state_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f3); - - /* compute the time for the process to schedule out */ - - mode_change(tfcs); - - /* get the information for the process scheduled in */ - - process = lttv_state_find_process(&(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), - &(tfcs->current_event_types_tree)); - - /* compute the time waiting for the process to schedule in */ - - mode_change(tfcs); - return FALSE; -} - - -gboolean process_fork(void *hook_data, void *call_data) -{ - /* nothing to do for now */ - return FALSE; -} - - -gboolean process_exit(void *hook_data, void *call_data) -{ - /* We should probably exit all modes here or we could do that at - schedule out. */ - return FALSE; -} - - -gboolean every_event(void *hook_data, void *call_data) -{ - LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data; - - LttvAttributeValue v; - - /* The current branch corresponds to the tracefile/process/interrupt state. - Statistics are added within it, to count the number of events of this - type occuring in this context. A quark has been pre-allocated for each - event type and is used as name. */ - - lttv_attribute_find(tfcs->current_event_types_tree, - ((LttvTraceState *)(tfcs->parent.parent.t_context))-> - eventtype_names[ltt_event_eventtype_id(tfcs->parent.parent.e)], - LTTV_UINT, &v); - (*(v.v_uint))++; - return FALSE; -} - - -static gboolean -sum_stats(void *hook_data, void *call_data) -{ - LttvTracesetStats *tscs = (LttvTracesetStats *)call_data; - - LttvTraceStats *tcs; - - LttvTraceset *traceset = tscs->parent.parent.ts; - - LttvAttributeType type; - - LttvAttributeValue value; - - LttvAttributeName name; - - unsigned sum; - - int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode, - nb_event_type; - - LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, - *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, - *submode_tree, *event_types_tree, *mode_events_tree, - *cpu_events_tree, *process_modes_tree, *trace_cpu_tree, - *trace_modes_tree, *traceset_modes_tree; - - traceset_modes_tree = lttv_attribute_find_subdir(tscs->stats, - LTTV_STATS_MODES); - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - main_tree = tcs->stats; - processes_tree = lttv_attribute_find_subdir(main_tree, - LTTV_STATS_PROCESSES); - trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES); - nb_process = lttv_attribute_get_number(processes_tree); - - for(j = 0 ; j < nb_process ; j++) { - type = lttv_attribute_get(processes_tree, j, &name, &value); - process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); - process_modes_tree = lttv_attribute_find_subdir(process_tree, - LTTV_STATS_MODES); - nb_cpu = lttv_attribute_get_number(cpus_tree); - - for(k = 0 ; k < nb_cpu ; k++) { - type = lttv_attribute_get(cpus_tree, k, &name, &value); - cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - mode_types_tree = lttv_attribute_find_subdir(cpu_tree, - LTTV_STATS_MODE_TYPES); - cpu_events_tree = lttv_attribute_find_subdir(cpu_tree, - LTTV_STATS_EVENTS); - trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU); - trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name); - nb_mode_type = lttv_attribute_get_number(mode_types_tree); - - for(l = 0 ; l < nb_mode_type ; l++) { - type = lttv_attribute_get(mode_types_tree, l, &name, &value); - mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - submodes_tree = lttv_attribute_find_subdir(mode_tree, - LTTV_STATS_SUBMODES); - mode_events_tree = lttv_attribute_find_subdir(mode_tree, - LTTV_STATS_EVENTS); - nb_submode = lttv_attribute_get_number(submodes_tree); - - for(m = 0 ; m < nb_submode ; m++) { - type = lttv_attribute_get(submodes_tree, m, &name, &value); - submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - event_types_tree = lttv_attribute_find_subdir(submode_tree, - LTTV_STATS_EVENT_TYPES); - nb_event_type = lttv_attribute_get_number(event_types_tree); - - sum = 0; - for(n = 0 ; n < nb_event_type ; n++) { - type = lttv_attribute_get(event_types_tree, n, &name, &value); - sum += *(value.v_uint); - } - lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT, - LTTV_UINT, &value); - *(value.v_uint) = sum; - lttv_attribute_recursive_add(mode_events_tree, submode_tree); - } - lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree); - } - lttv_attribute_recursive_add(process_modes_tree, cpu_tree); - lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree); - } - lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree); - } - lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree); - } - return FALSE; -} - - -lttv_stats_add_event_hooks(LttvTracesetStats *self) -{ - LttvTraceset *traceset = self->parent.parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttFacility *f; - - LttEventType *et; - - LttvTraceStats *ts; - - LttvTracefileStats *tfs; - - void *hook_data; - - GArray *hooks, *before_hooks, *after_hooks; - - LttvTraceHook hook; - - LttvAttributeValue val; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = (LttvTraceStats *)self->parent.parent.traces[i]; - - /* Find the eventtype id for the following events and register the - associated by id hooks. */ - - hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); - g_array_set_size(hooks, 7); - - lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry", - "syscall_id", NULL, NULL, before_syscall_entry, - &g_array_index(hooks, LttvTraceHook, 0)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL, - NULL, NULL, before_syscall_exit, - &g_array_index(hooks, LttvTraceHook, 1)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id", - NULL, NULL, before_trap_entry, - &g_array_index(hooks, LttvTraceHook, 2)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL, - NULL, before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id", - NULL, NULL, before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL, - NULL, before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "schedchange", "in", - "out", "out_state", before_schedchange, - &g_array_index(hooks, LttvTraceHook, 6)); - - before_hooks = hooks; - - hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook)); - g_array_set_size(hooks, 8); - - lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry", - "syscall_id", NULL, NULL, after_syscall_entry, - &g_array_index(hooks, LttvTraceHook, 0)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL, - NULL, NULL, after_syscall_exit, - &g_array_index(hooks, LttvTraceHook, 1)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id", - NULL, NULL, after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL, - NULL, after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id", - NULL, NULL, after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL, - NULL, after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "process_fork", - "child_pid", NULL, NULL, process_fork, - &g_array_index(hooks, LttvTraceHook, 6)); - - lttv_trace_find_hook(ts->parent.parent.t, "core", "process_exit", NULL, - NULL, NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 7)); - - after_hooks = hooks; - - /* Add these hooks to each before_event_by_id hooks list */ - - nb_control = ltt_trace_control_tracefile_number(ts->parent.parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.control_tracefiles[j]); - } - else { - tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.per_cpu_tracefiles[ - j-nb_control]); - } - - lttv_hooks_add(tfs->parent.parent.after_event, every_event, NULL); - - for(k = 0 ; k < before_hooks->len ; k++) { - hook = g_array_index(before_hooks, LttvTraceHook, k); - lttv_hooks_add(lttv_hooks_by_id_find( - tfs->parent.parent.before_event_by_id, - hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k)); - } - for(k = 0 ; k < after_hooks->len ; k++) { - hook = g_array_index(after_hooks, LttvTraceHook, k); - lttv_hooks_add(lttv_hooks_by_id_find( - tfs->parent.parent.after_event_by_id, - hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k)); - } - } - lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS, - LTTV_POINTER, &val); - *(val.v_pointer) = before_hooks; - lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS, - LTTV_POINTER, &val); - *(val.v_pointer) = after_hooks; - } - lttv_hooks_add(self->parent.parent.after, sum_stats, NULL); -} - - -lttv_stats_remove_event_hooks(LttvTracesetStats *self) -{ - LttvTraceset *traceset = self->parent.parent.ts; - - guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile; - - LttvTraceStats *ts; - - LttvTracefileStats *tfs; - - void *hook_data; - - GArray *before_hooks, *after_hooks; - - LttvTraceHook hook; - - LttvAttributeValue val; - - nb_trace = lttv_traceset_number(traceset); - for(i = 0 ; i < nb_trace ; i++) { - ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]); - lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS, - LTTV_POINTER, &val); - before_hooks = *(val.v_pointer); - lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS, - LTTV_POINTER, &val); - after_hooks = *(val.v_pointer); - - /* Add these hooks to each before_event_by_id hooks list */ - - nb_control = ltt_trace_control_tracefile_number(ts->parent.parent.t); - nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t); - nb_tracefile = nb_control + nb_per_cpu; - for(j = 0 ; j < nb_tracefile ; j++) { - if(j < nb_control) { - tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.control_tracefiles[j]); - } - else { - tfs =LTTV_TRACEFILE_STATS(ts->parent.parent.per_cpu_tracefiles[ - j-nb_control]); - } - - lttv_hooks_remove_data(tfs->parent.parent.after_event, every_event, - NULL); - - for(k = 0 ; k < before_hooks->len ; k++) { - hook = g_array_index(before_hooks, LttvTraceHook, k); - lttv_hooks_remove_data( - lttv_hooks_by_id_find(tfs->parent.parent.before_event_by_id, - hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k)); - } - for(k = 0 ; k < after_hooks->len ; k++) { - hook = g_array_index(after_hooks, LttvTraceHook, k); - lttv_hooks_remove_data( - lttv_hooks_by_id_find(tfs->parent.parent.after_event_by_id, - hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k)); - } - } - g_critical("lttv_stats_remove_event_hooks()"); - g_array_free(before_hooks, TRUE); - g_array_free(after_hooks, TRUE); - } - lttv_hooks_remove_data(self->parent.parent.after, sum_stats, NULL); -} - - -void lttv_stats_init(int argc, char **argv) -{ - LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process"); - LTTV_STATS_PROCESSES = g_quark_from_string("processes"); - LTTV_STATS_CPU = g_quark_from_string("cpu"); - LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types"); - LTTV_STATS_MODES = g_quark_from_string("modes"); - LTTV_STATS_SUBMODES = g_quark_from_string("submodes"); - LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types"); - LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time"); - LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time"); - LTTV_STATS_EVENTS = g_quark_from_string("events"); - LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count"); - LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks"); - LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks"); -} - -void lttv_stats_destroy() -{ -} - -void lttv_stats_save_attribute(LttvAttribute *attr, char *indent, FILE * fp) -{ - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - char type_value[BUF_SIZE]; - int i, nb_attr, flag; - - nb_attr = lttv_attribute_get_number(attr); - for(i=0;itv_sec, - value.v_time->tv_nsec); - break; - case LTTV_POINTER: - sprintf(type_value, "POINTER\0"); - break; - case LTTV_STRING: - sprintf(type_value, "%s\0", *value.v_string); - break; - default: - flag = 0; - break; - } - if(flag == 0) continue; - fprintf(fp,"%s",indent,type,g_quark_to_string(name)); - fprintf(fp,"%s",type_value); - fprintf(fp," \n"); - } - -} - -void lttv_stats_save_statistics(LttvTracesetStats *self) -{ - LttvTracesetStats *tscs = self; - LttvTraceStats *tcs; - LttvTraceset *traceset = tscs->parent.parent.ts; - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - - char filename[BUF_SIZE]; - FILE * fp; - char indent[10][24]= {" ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " " - }; - - - int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode; - - LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, - *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, - *submode_tree, *event_types_tree; - - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - - filename[0] = '\0'; - strcat(filename,ltt_trace_name(tcs->parent.parent.t)); - strcat(filename,"/statistics.xml"); - fp = fopen(filename,"w"); - if(!fp){ - g_warning("can not open the file %s for saving statistics\n", filename); - exit(1); - } - - main_tree = tcs->stats; - processes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_PROCESSES); - nb_process = lttv_attribute_get_number(processes_tree); - - fprintf(fp, " \n",g_quark_to_string(LTTV_STATS_PROCESSES)); //root NODE - - for(j = 0 ; j < nb_process ; j++) { - type = lttv_attribute_get(processes_tree, j, &name, &value); - process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[0],g_quark_to_string(name)); //process NODE - lttv_stats_save_attribute(process_tree,indent[1], fp); - fprintf(fp,"%s \n", indent[1],g_quark_to_string(LTTV_STATS_CPU)); //cpus NODE - - cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); - nb_cpu = lttv_attribute_get_number(cpus_tree); - - for(k = 0 ; k < nb_cpu ; k++) { - type = lttv_attribute_get(cpus_tree, k, &name, &value); - cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[2],g_quark_to_string(name)); //cpu NODE - lttv_stats_save_attribute(cpu_tree,indent[3], fp); - fprintf(fp,"%s \n",indent[3],g_quark_to_string(LTTV_STATS_MODE_TYPES)); //mode_types NODE - - mode_types_tree = lttv_attribute_find_subdir(cpu_tree,LTTV_STATS_MODE_TYPES); - nb_mode_type = lttv_attribute_get_number(mode_types_tree); - - for(l = 0 ; l < nb_mode_type ; l++) { - type = lttv_attribute_get(mode_types_tree, l, &name, &value); - mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[4],g_quark_to_string(name)); //mode NODE - lttv_stats_save_attribute(mode_tree,indent[5], fp); - fprintf(fp,"%s \n",indent[5],g_quark_to_string(LTTV_STATS_SUBMODES)); //sub_modes NODE - - submodes_tree = lttv_attribute_find_subdir(mode_tree,LTTV_STATS_SUBMODES); - nb_submode = lttv_attribute_get_number(submodes_tree); - - for(m = 0 ; m < nb_submode ; m++) { - type = lttv_attribute_get(submodes_tree, m, &name, &value); - submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - fprintf(fp,"%s \n",indent[6],g_quark_to_string(name)); //sub_mode NODE - lttv_stats_save_attribute(submode_tree,indent[7], fp); - fprintf(fp,"%s \n",indent[7],g_quark_to_string(LTTV_STATS_EVENT_TYPES)); //event_types NODE - - event_types_tree = lttv_attribute_find_subdir(submode_tree, LTTV_STATS_EVENT_TYPES); - lttv_stats_save_attribute(event_types_tree,indent[8], fp); - - fprintf(fp,"%s \n",indent[7]); //event_types NODE - fprintf(fp,"%s \n",indent[6]); //sub_mode NODE - } - fprintf(fp,"%s \n",indent[5]); //sub_modes NODE - fprintf(fp,"%s \n",indent[4]); //mode NODE - } - fprintf(fp,"%s \n",indent[3]); //mode_type NODE - fprintf(fp,"%s \n",indent[2]); //cpu NODE - } - fprintf(fp,"%s \n",indent[1]); //cpus NODE - fprintf(fp,"%s \n", indent[0]); //process NODE - } - fprintf(fp, "\n"); //root NODE - fclose(fp); - } -} - - -/* Functions to parse statistic.xml file (using glib xml parser) */ - -typedef struct _ParserStruct{ - GPtrArray * attribute; - LttvAttributeType type; - LttvAttributeName name; -} ParserStruct; - -static void stats_parser_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - int len; - LttvAttributeType type; - LttvAttributeName name; - LttvAttribute * parent_att, *new_att; - - len = parser->attribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - - if(strcmp("NODE", element_name) == 0){ - type = LTTV_GOBJECT; - name = g_quark_from_string(attribute_values[0]); - new_att = lttv_attribute_find_subdir(parent_att,name); - g_ptr_array_add(parser->attribute, (gpointer)new_att); - }else if(strcmp("VALUE", element_name) == 0){ - parser->type = (LttvAttributeType) atoi(attribute_values[0]); - parser->name = g_quark_from_string(attribute_values[1]); - }else{ - g_warning("This is not statistics.xml file\n"); - exit(1); - } -} - -static void stats_parser_end_element (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - int len; - LttvAttribute * parent_att; - - len = parser->attribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - - if(strcmp("NODE", element_name) == 0){ - g_ptr_array_remove_index(parser->attribute, len-1); - }else if(strcmp("VALUE", element_name) == 0){ - }else{ - g_warning("This is not statistics.xml file\n"); - exit(1); - } - -} - -static void stats_parser_characters (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - LttvAttributeValue value; - int len; - LttvAttribute * parent_att; - char *pos; - - pos = (char*)text; - for(len=0;lenattribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - if(!lttv_attribute_find(parent_att,parser->name, parser->type, &value)){ - g_warning("can not find value\n"); - exit(1); - } - - switch(parser->type) { - case LTTV_INT: - *value.v_int = atoi(text); - break; - case LTTV_UINT: - *value.v_uint = (unsigned)atoi(text); - break; - case LTTV_LONG: - *value.v_long = atol(text); - break; - case LTTV_ULONG: - *value.v_ulong = (unsigned long)atol(text); - break; - case LTTV_FLOAT: - *value.v_float = atof(text); - break; - case LTTV_DOUBLE: - *value.v_float = atof(text); - break; - case LTTV_TIME: - pos = strrchr(text,'.'); - if(pos){ - *pos = '\0'; - pos++; - value.v_time->tv_sec = atol(text); - value.v_time->tv_nsec = atol(pos); - }else{ - g_warning("The time value format is wrong\n"); - exit(1); - } - break; - case LTTV_POINTER: - break; - case LTTV_STRING: - *value.v_string = g_strdup(text); - break; - default: - break; - } - -} - -gboolean lttv_stats_load_statistics(LttvTracesetStats *self) -{ - FILE * fp; - char buf[BUF_SIZE]; - LttvTracesetStats *tscs = self; - LttvTraceStats *tcs; - LttvTraceset *traceset = tscs->parent.parent.ts; - char filename[BUF_SIZE]; - - GMarkupParseContext * context; - GError * error; - GMarkupParser markup_parser = - { - stats_parser_start_element, - stats_parser_end_element, - stats_parser_characters, - NULL, /* passthrough */ - NULL /* error */ - }; - - int i, nb_trace; - LttvAttribute *main_tree; - ParserStruct a_parser_struct; - a_parser_struct.attribute = g_ptr_array_new(); - - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - - filename[0] = '\0'; - strcat(filename,ltt_trace_name(tcs->parent.parent.t)); - strcat(filename,"/statistics.xml"); - fp = fopen(filename,"r"); - if(!fp){ - g_warning("can not open the file %s for reading statistics\n", filename); - return FALSE; - } - - main_tree = tcs->stats; - g_ptr_array_add(a_parser_struct.attribute,(gpointer)main_tree); - - context = g_markup_parse_context_new(&markup_parser, 0, (gpointer)&a_parser_struct, NULL); - - while(fgets(buf,BUF_SIZE, fp) != NULL){ - if(!g_markup_parse_context_parse(context, buf, BUF_SIZE, &error)){ - g_warning("Can not parse xml file: \n%s\n", error->message); - exit(1); - } - } - fclose(fp); - } - - sum_stats(NULL, (void *)self); - - return TRUE; -} diff --git a/ltt/branches/poly/lttv/mainLib/traceset.c b/ltt/branches/poly/lttv/mainLib/traceset.c deleted file mode 100644 index ce96b99a..00000000 --- a/ltt/branches/poly/lttv/mainLib/traceset.c +++ /dev/null @@ -1,171 +0,0 @@ - -#include -#include - -/* A trace is a sequence of events gathered in the same tracing session. The - events may be stored in several tracefiles in the same directory. - A trace set is defined when several traces are to be analyzed together, - possibly to study the interactions between events in the different traces. -*/ - -struct _LttvTraceset { - char * filename; - GPtrArray *traces; - LttvAttribute *a; -}; - - -struct _LttvTrace { - LttTrace *t; - LttvAttribute *a; - guint ref_count; -}; - - -LttvTraceset *lttv_traceset_new() -{ - LttvTraceset *s; - - s = g_new(LttvTraceset, 1); - s->filename = NULL; - s->traces = g_ptr_array_new(); - s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - return s; -} - -char * lttv_traceset_name(LttvTraceset * s) -{ - return s->filename; -} - -LttvTrace *lttv_trace_new(LttTrace *t) -{ - LttvTrace *new_trace; - - new_trace = g_new(LttvTrace, 1); - new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - new_trace->t = t; - new_trace->ref_count = 0; - return new_trace; -} - - -LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) -{ - int i; - LttvTraceset *s; - LttvTrace * trace; - - s = g_new(LttvTraceset, 1); - s->filename = NULL; - s->traces = g_ptr_array_new(); - for(i=0;itraces->len;i++) - { - trace = g_ptr_array_index(s_orig->traces, i); - trace->ref_count++; - - /*CHECK this used ltt_trace_copy while it may not be needed. Need to - define how traces and tracesets are shared */ - g_ptr_array_add( - s->traces, - g_ptr_array_index(s_orig->traces, i)); - } - s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a))); - return s; -} - - -LttvTraceset *lttv_traceset_load(const gchar *filename) -{ - LttvTraceset *s = g_new(LttvTraceset,1); - FILE *tf; - - s->filename = g_strdup(filename); - tf = fopen(filename,"r"); - - g_critical("NOT IMPLEMENTED : load traceset data from a XML file"); - - fclose(tf); - return s; -} - -gint lttv_traceset_save(LttvTraceset *s) -{ - FILE *tf; - - tf = fopen(s->filename, "w"); - - g_critical("NOT IMPLEMENTED : save traceset data in a XML file"); - - fclose(tf); - return 0; -} - -void lttv_traceset_destroy(LttvTraceset *s) -{ - g_ptr_array_free(s->traces, TRUE); - g_object_unref(s->a); - g_free(s); -} - -void lttv_trace_destroy(LttvTrace *t) -{ - g_object_unref(t->a); - g_free(t); -} - - -void lttv_traceset_add(LttvTraceset *s, LttvTrace *t) -{ - t->ref_count++; - g_ptr_array_add(s->traces, t); -} - - -unsigned lttv_traceset_number(LttvTraceset *s) -{ - return s->traces->len; -} - - -LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i) -{ - g_assert(s->traces->len > i); - return ((LttvTrace *)s->traces->pdata[i]); -} - - -void lttv_traceset_remove(LttvTraceset *s, unsigned i) -{ - LttvTrace * t; - g_assert(s->traces->len > i); - t = (LttvTrace *)s->traces->pdata[i]; - t->ref_count--; - g_ptr_array_remove_index(s->traces, i); -} - - -/* A set of attributes is attached to each trace set, trace and tracefile - to store user defined data as needed. */ - -LttvAttribute *lttv_traceset_attribute(LttvTraceset *s) -{ - return s->a; -} - - -LttvAttribute *lttv_trace_attribute(LttvTrace *t) -{ - return t->a; -} - - -LttTrace *lttv_trace(LttvTrace *t) -{ - return t->t; -} - -guint lttv_trace_get_ref_number(LttvTrace * t) -{ - return t->ref_count; -}