From de4b3c076d51124ef1ce6c35f2233cb935fa4ec0 Mon Sep 17 00:00:00 2001 From: Soeren Sandmann Date: Thu, 3 Mar 2005 04:44:28 +0000 Subject: [PATCH] Experiment with a file-format-description format. Wed Mar 2 23:39:50 2005 Soeren Sandmann * profile.[ch], sfile.[ch]: Experiment with a file-format-description format. * sysprof.c: Add commented out code using /proc/ based timeout. --- ChangeLog | 8 ++ Makefile | 3 +- process.c | 4 +- profile.c | 397 +++++++++++++++--------------------------------------- profile.h | 6 +- sfile.c | 385 ++++++++++++++++++++++++++-------------------------- sfile.h | 7 +- sysprof.c | 68 +++++++++- 8 files changed, 390 insertions(+), 488 deletions(-) diff --git a/ChangeLog b/ChangeLog index 44923392..e6ad06fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Wed Mar 2 23:39:50 2005 Soeren Sandmann + + * profile.[ch], sfile.[ch]: Experiment with a + file-format-description format. + + * sysprof.c: Add commented out code using /proc/ based + timeout. + Fri Jan 21 11:23:54 2005 Søren Sandmann * README: Some updates - add note about SMP kernels. diff --git a/Makefile b/Makefile index bf974689..9e1dc677 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,8 @@ else CFLAGS := $(shell pkg-config --cflags gtk+-2.0 libglade-2.0) -Wall -g LIBS := $(shell pkg-config --libs gtk+-2.0 libglade-2.0) -lbfd -liberty -C_FILES := sysprof.c binfile.c stackstash.c watch.c process.c profile.c treeviewutils.c sfile.c +C_FILES := sysprof.c binfile.c stackstash.c watch.c process.c \ +profile.c treeviewutils.c sfile.c OBJS := $(addsuffix .o, $(basename $(C_FILES))) BINARY := sysprof MODULE := sysprof-module diff --git a/process.c b/process.c index a3f84dcf..f94556ef 100644 --- a/process.c +++ b/process.c @@ -200,7 +200,7 @@ process_ensure_map (Process *process, int pid, gulong addr) { /* Round down to closest page */ addr = (addr - addr % PAGE_SIZE); - + if (process_has_page (process, addr)) return; @@ -214,7 +214,7 @@ process_ensure_map (Process *process, int pid, gulong addr) process->maps = read_maps (pid); if (!process_has_page (process, addr)) - g_list_prepend (process->bad_pages, (gpointer)addr); + process->bad_pages = g_list_prepend (process->bad_pages, (gpointer)addr); } static gboolean diff --git a/profile.c b/profile.c index fadefeed..546f3987 100644 --- a/profile.c +++ b/profile.c @@ -6,7 +6,7 @@ #include "process.h" #include "stackstash.h" #include "profile.h" - +#include "sfile.h" typedef struct Node Node; @@ -52,14 +52,118 @@ struct Profile GHashTable * nodes_by_object; }; -typedef struct SaveContext SaveContext; -struct SaveContext +static SFormat * +create_format (void) { - GString *str; - GHashTable *id_by_pointer; - GHashTable *pointer_by_id; - int last_id; -}; +#if 0 + SType object_type = 0; + SType node_type = 0; + + return sformat_new ( + sformat_new_record ( + "profile", + sformat_new_integer ("size", NULL), + sformat_new_list ( + "objects", NULL, + sformat_new_record ( + "object", &object_type, + sformat_new_string ("name", NULL), + sformat_new_integer ("total", NULL), + sformat_new_integer ("self", NULL), + NULL)), + sformat_new_list ( + "nodes", NULL, + sformat_new_record ( + "node", &node_type, + sformat_new_pointer ("object", &object_type), + sformat_new_pointer ("siblings", &node_type), + sformat_new_pointer ("children", &node_type), + sformat_new_pointer ("parent", &node_type), + sformat_new_pointer ("next", &node_type), + NULL)), + NULL)); +#endif +} + +static void +add_object (gpointer key, gpointer value, gpointer data) +{ + SFileOutput *output = data; + ProfileObject *object = key; + + sfile_begin_add_record (output, "object"); + + sfile_add_string (output, "name", object->name); + sfile_add_integer (output, "total", object->total); + sfile_add_integer (output, "self", object->self); + + sfile_end_add (output, "object", object); +} + +static void +serialize_call_tree (Node *node, SFileOutput *output) +{ + sfile_begin_add_record (output, "node"); + sfile_add_pointer (output, "object", node->object); + sfile_add_pointer (output, "siblings", node->siblings); + sfile_add_pointer (output, "children", node->children); + sfile_add_pointer (output, "parent", node->parent); + sfile_add_pointer (output, "next", node->next); + sfile_end_add (output, "node", node); + + serialize_call_tree (node->siblings, output); + serialize_call_tree (node->children, output); +} + +gboolean +profile_save (Profile *profile, + const char *file_name, + GError **err) +{ + gboolean result; + + SFormat *format = create_format (); +#if 0 + SFileOutput *output = sfile_output_new (format); + sfile_begin_add_record (output, "profile"); + + sfile_add_integer (output, "size", profile->size); + + sfile_begin_add_list (output, "objects"); + g_hash_table_foreach (profile->nodes_by_object, add_object, output); + sfile_end_add (output, "objects", NULL); + + sfile_begin_add_list (output, "nodes"); + serialize_call_tree (profile->call_tree, output); + sfile_end_add (output, "nodes", NULL); + + sfile_end_add (output, "profile", NULL); + + result = sfile_output_save (output, file_name, err); + + sformat_free (format); + sfile_output_free (output); + +#endif + return result; +} + +Profile * +profile_load (const char *filename, GError **err) +{ + SFormat *format = create_format (); + SFileInput *input; + + input = sfile_load (filename, format, err); + + + +#if 0 + sformat_free (format); +#endif + + +} static ProfileObject * profile_object_new (void) @@ -71,283 +175,6 @@ profile_object_new (void) return obj; } -static void -insert (SaveContext *context, int id, gpointer pointer) -{ - g_hash_table_insert (context->id_by_pointer, pointer, GINT_TO_POINTER (id)); - g_hash_table_insert (context->pointer_by_id, GINT_TO_POINTER (id), pointer); -} - -static int -get_id (SaveContext *context, gpointer pointer) -{ - int id; - - if (!pointer) - return 0; - - id = GPOINTER_TO_INT (g_hash_table_lookup (context->id_by_pointer, pointer)); - - if (!id) - { - id = ++context->last_id; - insert (context, id, pointer); - } - - return id; -} - -static void -serialize_object (gpointer key, gpointer value, gpointer data) -{ - SaveContext *context = data; - ProfileObject *object = key; - - g_string_append_printf (context->str, " \n", - get_id (context, object), - object->name, - object->total, - object->self); -} - -static void -serialize_call_tree (Node *node, SaveContext *context) -{ - if (!node) - return; - - g_string_append_printf (context->str, - " \n", - get_id (context, node), - get_id (context, node->object), - get_id (context, node->siblings), - get_id (context, node->children), - get_id (context, node->parent), - get_id (context, node->next), - node->total, - node->self, - node->toplevel); - - serialize_call_tree (node->siblings, context); - serialize_call_tree (node->children, context); -} - -gboolean -profile_save (Profile *profile, - const char *file_name) -{ - SaveContext context; - - context.str = g_string_new (""); - context.id_by_pointer = g_hash_table_new (g_direct_hash, g_direct_equal); - context.pointer_by_id = g_hash_table_new (g_direct_hash, g_direct_equal); - context.last_id = 0; - - g_string_append_printf (context.str, "\n \n"); - - g_hash_table_foreach (profile->nodes_by_object, serialize_object, &context); - - g_string_append_printf (context.str, " \n \n"); - - serialize_call_tree (profile->call_tree, &context); - - g_string_append_printf (context.str, " \n\n"); - - g_hash_table_destroy (context.id_by_pointer); - g_hash_table_destroy (context.pointer_by_id); - - /* FIXME - write it to disk, not screen */ - - g_print (context.str->str); - - g_string_free (context.str, TRUE); - - return TRUE; -} - -typedef struct LoadContext LoadContext; -struct LoadContext -{ - GHashTable *objects_by_id; - GHashTable *nodes_by_id; - -}; - -static int -get_number (const char *input_name, - const char *target_name, - const char *value) -{ - if (strcmp (input_name, target_name) == 0) - { - char *end; - int r = strtol (value, &end, 10); - if (*end == '\0') - return r; - } - - return -1; -} - -#if 0 -static Node * -create_node (const char **names, - const char **values, - int *id) -{ - int i; - - int object = -1; - int siblings = -1; - int children = -1; - int parent = -1; - int next = -1; - int total = -1; - int self = -1; - - Node *node = node_new (); - - for (i = 0; names[i] != NULL; ++i) - { - *id = get_number (names[i], "id", values[i]); - node->object = GINT_TO_POINTER (get_number (names[i], "object", values[i])); - node->siblings = GINT_TO_POITNER (get_number (names[i], "siblings", values[i])); - node->children = GINT_TO_POINTER (get_number (names[i], "children", values[i])); - node->parent = GINT_TO_POINTER (get_number (names[i], "parent", values[i])); - node->next = GINT_TO_POINTER (get_number (names[i], "next", values[i])); - node->total = get_number (names[i], "total", values[i]); - node->self = get_number (names[i], "self", values[i]); - } - - if (id == -1 || object == -1 || siblings == -1 || - children == -1 || parent == -1 || next == -1 || - total == -1 || self == -1) - { - return NULL; - } - - node->object = GINT_TO_POINTER (object); - node->siblings = GINT_TO_POINTER (siblings); - - - i = 0; - const char *name = attribute_names[i]; - const char *value = attribute_values[i]; - - if (strcmp (name, "id") == 0) - { - } - else if (strcmp (name, "sibling") == 0) - { - - } - - i++; - } - return NULL; -} - -static ProfileObject * -create_object (const char **attribute_names, const char **attribute_values, int *id, GError **err) -{ - int i; - - i = 0; - while (attribute_names[i]) - { - const char *name = attribute_names[i]; - const char *value = attribute_values[i]; - - - - - i++; - } - return NULL; -} - -static void -parse_start_element (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - gpointer user_data, - GError **err) -{ - int id; - LoadContext *lc = user_data; - - if (strcmp (element_name, "object") == 0) - { - ProfileObject *object = create_object (attribute_names, attribute_values, &id, err); - - if (object) - g_hash_table_insert (lc->objects_by_id, GINT_TO_POINTER (id), object); - } - else if (strcmp (element_name, "node") == 0) - { - Node *node = create_node (attribute_names, attribute_values, &id, err); - - if (node) - g_hash_table_insert (lc->nodes_by_id, GINT_TO_POINTER (id), node); - } - else - { - /* ignore anything but object and node */ - } -} - -static void -parse_end_element (GMarkupParseContext *context, - const char *element_name, - gpointer user_data, - GError **error) -{ - -} - -static void -parse_error (GMarkupParseContext *context, - GError **error, - gpointer user_data) -{ -} - -Profile * -profile_load (const char *filename, - GError **err) -{ - char *input = NULL; - Profile *result = NULL; - - GMarkupParser parser = { - parse_start_element, parse_end_element, NULL, NULL, NULL, - }; - - LoadContext load_context; - GMarkupParseContext *parse_context; - - if (!g_file_get_contents (filename, &input, NULL, err)) - return NULL; - - parse_context = g_markup_parse_context_new (&parser, 0, NULL, NULL); - - if (!g_markup_parse_context_parse (parse_context, input, -1, err)) - goto out; - - if (!g_markup_parse_context_end_parse (parse_context, err)) - goto out; - - g_markup_parse_context_free (parse_context); - - out: - g_free (input); - - return result; -} -#endif - static void profile_object_free (ProfileObject *obj) { diff --git a/profile.h b/profile.h index e6a6cbcc..a35abb86 100644 --- a/profile.h +++ b/profile.h @@ -70,5 +70,7 @@ void profile_caller_free (ProfileCaller *caller); void profile_descendant_free (ProfileDescendant *descendant); gboolean profile_save (Profile *profile, - const char *file_name); -Profile * profile_load (const char *filename); + const char *file_name, + GError **err); +Profile * profile_load (const char *filename, + GError **err); diff --git a/sfile.c b/sfile.c index f8c41cb5..ff83c2da 100644 --- a/sfile.c +++ b/sfile.c @@ -152,6 +152,12 @@ sformat_new (gpointer f) return sformat; } +void +sformat_destroy (SFormat *format) +{ + /* FIXME */ +} + static GQueue * fragment_queue (va_list args) { @@ -437,9 +443,9 @@ state_transition_text (const State *state, TransitionType *type, GError **err) /* reading */ typedef struct BuildContext BuildContext; -typedef struct ReadItem ReadItem; +typedef struct Instruction Instruction; -struct ReadItem +struct Instruction { TransitionType type; @@ -448,21 +454,23 @@ struct ReadItem { struct { - int n_items; + int n_instructions; int id; - ReadItem *end_item; + Instruction *end_instruction; } begin; struct { + Instruction *begin_instruction; gpointer object; } end; struct { int target_id; - ReadItem *target_item; + Instruction *target_instruction; gpointer *location; + gpointer object; } pointer; struct @@ -481,7 +489,7 @@ struct BuildContext { const State *state; - GArray *items; + GArray *instructions; }; static gboolean @@ -506,32 +514,32 @@ get_number (const char *text, int *number) struct SFileInput { - int n_items; - ReadItem *items; - ReadItem *current_item; - GHashTable *items_by_location; + int n_instructions; + Instruction *instructions; + Instruction *current_instruction; + GHashTable *instructions_by_location; GHashTable *objects_by_id; }; void sfile_begin_get_record (SFileInput *file, const char *name) { - ReadItem *item = file->current_item++; + Instruction *instruction = file->current_instruction++; - g_return_if_fail (item->type == BEGIN_RECORD && - strcmp (item->name, name) == 0); + g_return_if_fail (instruction->type == BEGIN_RECORD && + strcmp (instruction->name, name) == 0); } int sfile_begin_get_list (SFileInput *file, const char *name) { - ReadItem *item = file->current_item++; + Instruction *instruction = file->current_instruction++; - g_return_val_if_fail (item->type == BEGIN_LIST && - strcmp (item->name, name) == 0, 0); + g_return_val_if_fail (instruction->type == BEGIN_LIST && + strcmp (instruction->name, name) == 0, 0); - return item->u.begin.n_items; + return instruction->u.begin.n_instructions; } void @@ -539,20 +547,20 @@ sfile_get_pointer (SFileInput *file, const char *name, gpointer *location) { - ReadItem *item = file->current_item++; - g_return_if_fail (item->type == POINTER && - strcmp (item->name, name) == 0); + Instruction *instruction = file->current_instruction++; + g_return_if_fail (instruction->type == POINTER && + strcmp (instruction->name, name) == 0); - item->u.pointer.location = location; + instruction->u.pointer.location = location; *location = (gpointer) 0xFedeAbe; if (location) { - if (g_hash_table_lookup (file->items_by_location, location)) + if (g_hash_table_lookup (file->instructions_by_location, location)) g_warning ("Reading into the same location twice\n"); - g_hash_table_insert (file->items_by_location, location, item); + g_hash_table_insert (file->instructions_by_location, location, instruction); } } @@ -561,12 +569,12 @@ sfile_get_integer (SFileInput *file, const char *name, int *integer) { - ReadItem *item = file->current_item++; - g_return_if_fail (item->type == INTEGER && - strcmp (item->name, name) == 0); + Instruction *instruction = file->current_instruction++; + g_return_if_fail (instruction->type == INTEGER && + strcmp (instruction->name, name) == 0); if (integer) - *integer = item->u.integer.value; + *integer = instruction->u.integer.value; } void @@ -574,12 +582,12 @@ sfile_get_string (SFileInput *file, const char *name, char **string) { - ReadItem *item = file->current_item++; - g_return_if_fail (item->type == STRING && - strcmp (item->name, name) == 0); + Instruction *instruction = file->current_instruction++; + g_return_if_fail (instruction->type == STRING && + strcmp (instruction->name, name) == 0); if (string) - *string = g_strdup (item->u.string.value); + *string = g_strdup (instruction->u.string.value); } static void @@ -587,16 +595,16 @@ hook_up_pointers (SFileInput *file) { int i; - for (i = 0; i < file->n_items; ++i) + for (i = 0; i < file->n_instructions; ++i) { - ReadItem *item = &(file->items[i]); + Instruction *instruction = &(file->instructions[i]); - if (item->type == POINTER) + if (instruction->type == POINTER) { gpointer target_object = - item->u.pointer.target_item->u.begin.end_item->u.end.object; + instruction->u.pointer.target_instruction->u.begin.end_instruction->u.end.object; - *(item->u.pointer.location) = target_object; + *(instruction->u.pointer.location) = target_object; } } } @@ -606,15 +614,15 @@ sfile_end_get (SFileInput *file, const char *name, gpointer object) { - ReadItem *item = file->current_item++; + Instruction *instruction = file->current_instruction++; - g_return_if_fail ((item->type == END_LIST || - item->type == END_RECORD) && - strcmp (item->name, name) == 0); + g_return_if_fail ((instruction->type == END_LIST || + instruction->type == END_RECORD) && + strcmp (instruction->name, name) == 0); - item->u.end.object = object; + instruction->u.end.object = object; - if (file->current_item == file->items + file->n_items) + if (file->current_instruction == file->instructions + file->n_instructions) hook_up_pointers (file); } @@ -662,17 +670,17 @@ handle_begin_element (GMarkupParseContext *parse_context, GError **err) { BuildContext *build = user_data; - ReadItem item; + Instruction instruction; - item.u.begin.id = get_id (attribute_names, attribute_values, err); + instruction.u.begin.id = get_id (attribute_names, attribute_values, err); - if (item.u.begin.id == -1) + if (instruction.u.begin.id == -1) return; - build->state = state_transition_begin (build->state, element_name, &item.type, err); - item.name = g_strdup (element_name); + build->state = state_transition_begin (build->state, element_name, &instruction.type, err); + instruction.name = g_strdup (element_name); - g_array_append_val (build->items, item); + g_array_append_val (build->instructions, instruction); } static void @@ -682,13 +690,13 @@ handle_end_element (GMarkupParseContext *context, GError **err) { BuildContext *build = user_data; - ReadItem item; + Instruction instruction; - build->state = state_transition_end (build->state, element_name, &item.type, err); + build->state = state_transition_end (build->state, element_name, &instruction.type, err); - item.name = g_strdup (element_name); + instruction.name = g_strdup (element_name); - g_array_append_val (build->items, item); + g_array_append_val (build->instructions, instruction); } static gboolean @@ -716,16 +724,16 @@ handle_text (GMarkupParseContext *context, GError **err) { BuildContext *build = user_data; - ReadItem item; + Instruction instruction; - build->state = state_transition_text (build->state, &item.type, err); + build->state = state_transition_text (build->state, &instruction.type, err); - item.name = NULL; + instruction.name = NULL; - switch (item.type) + switch (instruction.type) { case POINTER: - if (!get_number (text, &item.u.pointer.target_id)) + if (!get_number (text, &instruction.u.pointer.target_id)) { set_invalid_content_error (err, "Contents '%s' of pointer element is not a number", text); return; @@ -733,7 +741,7 @@ handle_text (GMarkupParseContext *context, break; case INTEGER: - if (!get_number (text, &item.u.integer.value)) + if (!get_number (text, &instruction.u.integer.value)) { set_invalid_content_error (err, "Contents '%s' of integer element not a number", text); return; @@ -741,7 +749,7 @@ handle_text (GMarkupParseContext *context, break; case STRING: - if (!decode_text (text, &item.u.string.value)) + if (!decode_text (text, &instruction.u.string.value)) { set_invalid_content_error (err, "Contents '%s' of text element is illformed", text); return; @@ -753,117 +761,119 @@ handle_text (GMarkupParseContext *context, break; } - g_array_append_val (build->items, item); + g_array_append_val (build->instructions, instruction); } static void -free_items (ReadItem *items, int n_items) +free_instructions (Instruction *instructions, int n_instructions) { int i; - for (i = 0; i < n_items; ++i) + for (i = 0; i < n_instructions; ++i) { - ReadItem *item = &(items[i]); + Instruction *instruction = &(instructions[i]); - if (item->name) - g_free (item->name); + if (instruction->name) + g_free (instruction->name); - if (item->type == STRING) - g_free (item->u.string.value); + if (instruction->type == STRING) + g_free (instruction->u.string.value); } - g_free (items); + g_free (instructions); } -/* This functions counts the number of items in each list, and +/* This functions counts the number of instructions in each list, and * matches up pointers with the lists/records they point to. * FIMXE: think of a better name */ -static ReadItem * -post_process_items_recurse (ReadItem *first, GHashTable *items_by_id, GError **err) +static Instruction * +post_process_instructions_recurse (Instruction *first, GHashTable *instructions_by_id, GError **err) { - ReadItem *item; - int n_items; + Instruction *instruction; + int n_instructions; g_assert (first->type >= FIRST_BEGIN_TRANSITION && first->type <= LAST_BEGIN_TRANSITION); - item = first + 1; + instruction = first + 1; - n_items = 0; - while (item->type < FIRST_END_TRANSITION || - item->type > LAST_END_TRANSITION) + n_instructions = 0; + while (instruction->type < FIRST_END_TRANSITION || + instruction->type > LAST_END_TRANSITION) { - if (item->type >= FIRST_BEGIN_TRANSITION && - item->type <= LAST_BEGIN_TRANSITION) + if (instruction->type >= FIRST_BEGIN_TRANSITION && + instruction->type <= LAST_BEGIN_TRANSITION) { - item = post_process_items_recurse (item, items_by_id, err); - if (!item) + instruction = post_process_instructions_recurse (instruction, instructions_by_id, err); + if (!instruction) return NULL; } else { - if (item->type == POINTER) + if (instruction->type == POINTER) { - int target_id = item->u.pointer.target_id; - ReadItem *target = g_hash_table_lookup (items_by_id, GINT_TO_POINTER (target_id)); + int target_id = instruction->u.pointer.target_id; + Instruction *target = g_hash_table_lookup (instructions_by_id, GINT_TO_POINTER (target_id)); if (!target) { set_invalid_content_error (err, "Id %d doesn't reference any record or list\n", - item->u.pointer.target_id); + instruction->u.pointer.target_id); return NULL; } - item->u.pointer.target_item = target; + instruction->u.pointer.target_instruction = target; } - item++; + instruction++; } - n_items++; + n_instructions++; } - first->u.begin.n_items = n_items; - first->u.begin.end_item = item; + first->u.begin.n_instructions = n_instructions; + first->u.begin.end_instruction = instruction; - return item + 1; + instruction->u.end.begin_instruction = first; + + return instruction + 1; } static gboolean -post_process_items (ReadItem *items, int n_items, GError **err) +post_process_read_instructions (Instruction *instructions, int n_instructions, GError **err) { gboolean retval = TRUE; - GHashTable *items_by_id; + GHashTable *instructions_by_id; int i; - /* Build id->item map */ - items_by_id = g_hash_table_new (g_direct_hash, g_direct_equal); - for (i = 0; i < n_items; ++i) + /* Build id->instruction map */ + instructions_by_id = g_hash_table_new (g_direct_hash, g_direct_equal); + for (i = 0; i < n_instructions; ++i) { - ReadItem *item = &(items[i]); + Instruction *instruction = &(instructions[i]); - if (item->type >= FIRST_BEGIN_TRANSITION && - item->type <= LAST_BEGIN_TRANSITION) + if (instruction->type >= FIRST_BEGIN_TRANSITION && + instruction->type <= LAST_BEGIN_TRANSITION) { - int id = item->u.begin.id; + int id = instruction->u.begin.id; if (id) - g_hash_table_insert (items_by_id, GINT_TO_POINTER (id), item); + g_hash_table_insert (instructions_by_id, GINT_TO_POINTER (id), instruction); } } - /* count list items, check pointers */ - if (!post_process_items_recurse (items, items_by_id, err)) + /* count list instructions, check pointers */ + if (!post_process_instructions_recurse (instructions, instructions_by_id, err)) retval = FALSE; - g_hash_table_destroy (items_by_id); + g_hash_table_destroy (instructions_by_id); return retval; } -static ReadItem * -build_items (const char *contents, SFormat *format, int *n_items, GError **err) +static Instruction * +build_instructions (const char *contents, SFormat *format, int *n_instructions, GError **err) { BuildContext build; GMarkupParseContext *parse_context; @@ -877,31 +887,31 @@ build_items (const char *contents, SFormat *format, int *n_items, GError **err) }; build.state = sformat_get_start_state (format); - build.items = g_array_new (TRUE, TRUE, sizeof (ReadItem)); + build.instructions = g_array_new (TRUE, TRUE, sizeof (Instruction)); parse_context = g_markup_parse_context_new (&parser, 0, &build, NULL); if (!sformat_is_end_state (format, build.state)) { set_invalid_content_error (err, "Unexpected end of file\n"); - free_items ((ReadItem *)build.items->data, build.items->len); + free_instructions ((Instruction *)build.instructions->data, build.instructions->len); return NULL; } if (!g_markup_parse_context_parse (parse_context, contents, -1, err)) { - free_items ((ReadItem *)build.items->data, build.items->len); + free_instructions ((Instruction *)build.instructions->data, build.instructions->len); return NULL; } - if (!post_process_items ((ReadItem *)build.items->data, build.items->len, err)) + if (!post_process_read_instructions ((Instruction *)build.instructions->data, build.instructions->len, err)) { - free_items ((ReadItem *)build.items->data, build.items->len); + free_instructions ((Instruction *)build.instructions->data, build.instructions->len); return NULL; } - *n_items = build.items->len; - return (ReadItem *)g_array_free (build.items, FALSE); + *n_instructions = build.instructions->len; + return (Instruction *)g_array_free (build.instructions, FALSE); } SFileInput * @@ -918,9 +928,9 @@ sfile_load (const char *filename, input = g_new (SFileInput, 1); - input->items = build_items (contents, format, &input->n_items, err); + input->instructions = build_instructions (contents, format, &input->n_instructions, err); - if (!input->items) + if (!input->instructions) { g_free (input); g_free (contents); @@ -933,48 +943,10 @@ sfile_load (const char *filename, } /* Writing */ -typedef struct WriteItem WriteItem; - -struct WriteItem -{ - TransitionType type; - union - { - struct - { - char *name; - int id; - } begin; - - struct - { - char *name; - } end; - - struct - { - char *name; - gpointer object; - } pointer; - - struct - { - char *name; - int value; - } integer; - - struct - { - char *name; - char *value; - } string; - } u; -}; - struct SFileOutput { SFormat *format; - GArray *items; + GArray *instructions; const State *state; }; @@ -985,7 +957,7 @@ sfile_output_mew (SFormat *format) SFileOutput *output = g_new (SFileOutput, 1); output->format = format; - output->items = g_array_new (TRUE, TRUE, sizeof (WriteItem)); + output->instructions = g_array_new (TRUE, TRUE, sizeof (Instruction)); output->state = sformat_get_start_state (format); return output; @@ -995,84 +967,104 @@ void sfile_begin_add_record (SFileOutput *file, const char *name) { - WriteItem item; + Instruction instruction; file->state = state_transition_begin ( - file->state, name, &item.type, NULL); + file->state, name, &instruction.type, NULL); - g_return_if_fail (file->state && item.type == BEGIN_RECORD); + g_return_if_fail (file->state && instruction.type == BEGIN_RECORD); - item.u.begin.name = g_strdup (name); + instruction.name = g_strdup (name); - g_array_append_val (file->items, item); + g_array_append_val (file->instructions, instruction); } void sfile_begin_add_list (SFileOutput *file, const char *name) { - WriteItem item; + Instruction instruction; TransitionType type; file->state = state_transition_begin ( - file->state, name, &item.type, NULL); + file->state, name, &instruction.type, NULL); g_return_if_fail (file->state && type == BEGIN_LIST); - item.u.begin.name = g_strdup (name); + instruction.name = g_strdup (name); - g_array_append_val (file->items, item); + g_array_append_val (file->instructions, instruction); } void -sfile_end_add (SFileOutput *file, - const char *name, - gpointer object) +sfile_end_add (SFileOutput *file, + const char *name, + gpointer object) { - WriteItem item; + Instruction instruction; file->state = state_transition_end ( - file->state, name, &item.type, NULL); + file->state, name, &instruction.type, NULL); g_return_if_fail (file->state && - (item.type == END_RECORD || item.type == END_LIST)); + (instruction.type == END_RECORD || instruction.type == END_LIST)); - item.u.end.name = g_strdup (name); + instruction.name = g_strdup (name); + instruction.u.end.object = object; - g_array_append_val (file->items, item); + g_array_append_val (file->instructions, instruction); } -static TransitionType -sfile_add_value (SFileOutput *file, - const char *name, - TransitionType begin, - TransitionType value, - TransitionType end) +static void +sfile_check_value (SFileOutput *file, + const char *name, + TransitionType begin, + TransitionType value, + TransitionType end) { - TransitionType tmp_type; TransitionType type; - file->state = state_transition_begin (file->state, name, &tmp_type, NULL); - file->state = state_transition_text (file->state, &type, NULL); - file->state = state_transition_end (file->state, name, &tmp_type, NULL); + file->state = state_transition_begin (file->state, name, &type, NULL); + g_return_if_fail (file->state && type == begin); - return type; + file->state = state_transition_text (file->state, &type, NULL); + g_return_if_fail (file->state && type == value); + + file->state = state_transition_end (file->state, name, &type, NULL); + g_return_if_fail (file->state && type == end); } void sfile_add_string (SFileOutput *file, const char *name, - const char *string) + const char *string) { - sfile_add_value (file, name, BEGIN_STRING, STRING, END_STRING); + Instruction instruction; + + g_return_if_fail (g_utf8_validate (string, -1, NULL)); + + sfile_check_value (file, name, BEGIN_STRING, STRING, END_STRING); + + instruction.type = STRING; + instruction.u.string.value = g_strdup (string); + + g_array_append_val (file->instructions, instruction); } void -sfile_add_integer (SFileOutput *file, - const char *name, +sfile_add_integer (SFileOutput *file, + const char *name, int integer) { - sfile_add_value (file, name, BEGIN_INTEGER, INTEGER, END_INTEGER); + Instruction instruction; + + sfile_check_value (file, name, BEGIN_INTEGER, INTEGER, END_INTEGER); + + instruction.type = INTEGER; + instruction.name = g_strdup (name); + instruction.u.integer.value = integer; + + g_array_append_val (file->instructions, instruction); } void @@ -1080,13 +1072,22 @@ sfile_add_pointer (SFileOutput *file, const char *name, gpointer pointer) { - sfile_add_value (file, name, BEGIN_POINTER, POINTER, END_POINTER); + Instruction instruction; + + sfile_check_value (file, name, BEGIN_POINTER, POINTER, END_POINTER); + + instruction.type = POINTER; + instruction.name = g_strdup (name); + instruction.u.pointer.object = pointer; + + g_array_append_val (file->instructions, instruction); } gboolean -sfile_save (SFileOutput *sfile, - const char *filename, - GError **err) +sfile_output_save (SFileOutput *sfile, + const char *filename, + GError **err) { + return FALSE; /* FIXME */ } diff --git a/sfile.h b/sfile.h index 3eac1660..d5d2c6bb 100644 --- a/sfile.h +++ b/sfile.h @@ -12,6 +12,7 @@ gpointer sformat_new_list (const char *name, gpointer sformat_new_pointer (const char *name); gpointer sformat_new_integer (const char *name); gpointer sformat_new_string (const char *name); +void sformat_free (SFormat *format); /* - Reading - */ SFileInput * sfile_load (const char *filename, @@ -51,7 +52,7 @@ void sfile_loader_free (SFileLoader *loader); * a way to get the name back then, though. */ -SFileOutput * sfile_output_mew (SFormat *format); +SFileOutput * sfile_output_new (SFormat *format); void sfile_begin_add_record (SFileOutput *file, const char *name); void sfile_begin_add_list (SFileOutput *file, @@ -68,8 +69,8 @@ void sfile_add_integer (SFileOutput *file, void sfile_add_pointer (SFileOutput *file, const char *name, gpointer pointer); -gboolean sfile_save (SFileOutput *sfile, +gboolean sfile_output_save (SFileOutput *sfile, const char *filename, GError **err); - +void sfile_output_free (SFileOutput *sfile); diff --git a/sysprof.c b/sysprof.c index 2a8c98ee..75f6d201 100644 --- a/sysprof.c +++ b/sysprof.c @@ -13,7 +13,7 @@ #include "stackstash.h" #include "profile.h" #include "treeviewutils.h" - +#include "tracing.h" /* FIXME */ #define _(a) a @@ -170,6 +170,62 @@ get_name (pid_t pid) } #endif +#if 0 +static void +on_timeout (gpointer data) +{ + Application *app = data; + GList *pids, *list; + int mypid = getpid(); + + pids = list_processes (); + + for (list = pids; list != NULL; list = list->next) + { + int pid = GPOINTER_TO_INT (list->data); + + if (pid == mypid) + continue; + + if (get_process_state (pid) == PROCESS_RUNNING) + { + Process *process; + SysprofStackTrace trace; + int i; + + if (!generate_stack_trace (pid, &trace)) + { + continue; + } + + process = process_get_from_pid (pid); + +#if 0 + process_ensure_map (process, trace.pid, + (gulong)trace.addresses[i]); +#endif + + g_print ("n addr: %d\n", trace.n_addresses); + for (i = 0; i < trace.n_addresses; ++i) + process_ensure_map (process, trace.pid, + (gulong)trace.addresses[i]); + g_assert (!app->generating_profile); + + stack_stash_add_trace ( + app->stash, process, + (gulong *)trace.addresses, trace.n_addresses, 1); + + app->n_samples++; + } + } + + update_sensitivity (app); + g_list_free (pids); + + return TRUE; +} +#endif + static void on_read (gpointer data) { @@ -413,8 +469,9 @@ on_save_as_clicked (gpointer widget, gpointer data) Application *app = data; ensure_profile (app); - - if (!profile_save (app->profile, NULL)) + + /* FIXME */ + if (!profile_save (app->profile, "name.profile", NULL)) sorry (NULL, "Couldn't save\n"); #if 0 @@ -880,6 +937,11 @@ main (int argc, char **argv) fd_add_watch (app->input_fd, app); fd_set_read_callback (app->input_fd, on_read); + +#if 0 + nice (-19); + g_timeout_add (10, on_timeout, app); +#endif build_gui (app);