From c5b66034c5a14a6fc5ba3e1a756a3174450ffeac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Tue, 23 Nov 2004 00:10:55 +0000 Subject: [PATCH] *** empty log message *** --- TODO | 3 +- binfile.c | 3 ++ process.c | 122 +++++++++++++++++++++++++++++++++++------------ profile.c | 28 +++++------ sfile.c | 19 ++++++-- sysprof-module.c | 2 +- 6 files changed, 125 insertions(+), 52 deletions(-) diff --git a/TODO b/TODO index 1470307c..6c79fb1b 100644 --- a/TODO +++ b/TODO @@ -3,6 +3,7 @@ Should avoid a lot of potential broken/raciness with dlopen etc. - grep FIXME - hide internal stuff in ProfileDescendant +- add an 'everything' object. It _is_ really needed for a lot of things - loading and saving @@ -13,8 +14,6 @@ - Port to GtkAction -- If we can't get a name, look in /proc//status - - Charge 'self' properly to processes that don't get any stack trace at all - figure out a way to deal with both disk and CPU. Need to make sure that diff --git a/binfile.c b/binfile.c index 1a48956c..c673c2fa 100644 --- a/binfile.c +++ b/binfile.c @@ -154,6 +154,9 @@ separate_debug_file_exists (const char *name, unsigned long crc) file_crc = calc_crc32 (file_crc, buffer, count); close (fd); + + if (crc != file_crc) + g_print ("warning: %s has wrong crc\n", name); return crc == file_crc; } diff --git a/process.c b/process.c index d5fd9c56..a3f84dcf 100644 --- a/process.c +++ b/process.c @@ -217,44 +217,106 @@ process_ensure_map (Process *process, int pid, gulong addr) g_list_prepend (process->bad_pages, (gpointer)addr); } +static gboolean +do_idle_free (gpointer d) +{ + g_free (d); + return FALSE; +} + +static char * +idle_free (char *d) +{ + g_idle_add (do_idle_free, d); + return d; +} + +static char * +get_cmdline (int pid) +{ + char *cmdline; + char *filename = idle_free (g_strdup_printf ("/proc/%d/cmdline", pid)); + + if (g_file_get_contents (filename, &cmdline, NULL, NULL)) + { + if (*cmdline == '\0') + { + g_free (cmdline); + return NULL; + } + return cmdline; + } + + return NULL; +} + +static char * +get_statname (int pid) +{ + char *stat; + char *filename = idle_free (g_strdup_printf ("/proc/%d/stat", pid)); + +#if 0 + g_print ("stat %d\n", pid); +#endif + + if (g_file_get_contents (filename, &stat, NULL, NULL)) + { + char result[200]; + + idle_free (stat); + + if (sscanf (stat, "%*d %200s %*s", result) == 1) + return g_strndup (result, 200); + } +#if 0 + g_print ("return null\n"); +#endif + + return NULL; +} + +static char * +get_pidname (int pid) +{ + return g_strdup_printf ("[pid %d]", pid); +} + +static char * +get_name (int pid) +{ + char *cmdline = NULL; + + if ((cmdline = get_cmdline (pid))) + return cmdline; + + if ((cmdline = get_statname (pid))) + return cmdline; + + return get_pidname (pid); +} + Process * process_get_from_pid (int pid) { Process *p; - gchar *filename = NULL; gchar *cmdline = NULL; initialize(); - - p = g_hash_table_lookup (processes_by_pid, GINT_TO_POINTER (pid)); - if (p) - goto out; - - filename = g_strdup_printf ("/proc/%d/cmdline", pid); - - if (g_file_get_contents (filename, &cmdline, NULL, NULL)) - { - p = g_hash_table_lookup (processes_by_cmdline, cmdline); - if (p) - goto out; - } - else - { - cmdline = g_strdup_printf ("[pid %d]", pid); - } - - p = create_process (cmdline, pid); - -out: - if (cmdline) - g_free (cmdline); - - if (filename) - g_free (filename); - - return p; -} + p = g_hash_table_lookup (processes_by_pid, GINT_TO_POINTER (pid)); + + if (p) + return p; + + cmdline = get_name (pid); + + p = g_hash_table_lookup (processes_by_cmdline, cmdline); + if (p) + return p; + else + return create_process (idle_free (cmdline), pid); +} const Symbol * process_lookup_symbol (Process *process, gulong address) diff --git a/profile.c b/profile.c index 03bc0248..fadefeed 100644 --- a/profile.c +++ b/profile.c @@ -391,7 +391,7 @@ generate_presentation_name (Process *process, gulong address) } static void -ensure_profile_node (GHashTable *profile_objects, Process *process, gulong address) +ensure_profile_object (GHashTable *profile_objects, Process *process, gulong address) { char *key = generate_key (process, address); @@ -434,12 +434,12 @@ generate_object_table (Process *process, GSList *trace, gint size, gpointer data Info *info = data; GSList *list; - ensure_profile_node (info->profile_objects, process, 0); + ensure_profile_object (info->profile_objects, process, 0); for (list = trace; list != NULL; list = list->next) { update (); - ensure_profile_node (info->profile_objects, process, (gulong)list->data); + ensure_profile_object (info->profile_objects, process, (gulong)list->data); } info->profile->size += size; @@ -592,29 +592,27 @@ compute_object_total (gpointer key, gpointer value, gpointer data) Profile * profile_new (StackStash *stash) { - Profile *profile = g_new (Profile, 1); Info info; - - profile->call_tree = NULL; - - profile->nodes_by_object = + + info.profile = g_new (Profile, 1); + info.profile->call_tree = NULL; + info.profile->nodes_by_object = g_hash_table_new (direct_hash_no_null, g_direct_equal); - - profile->size = 0; - - info.profile = profile; + info.profile->size = 0; + + /* profile objects */ info.profile_objects = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); stack_stash_foreach (stash, generate_object_table, &info); stack_stash_foreach (stash, generate_call_tree, &info); - link_parents (profile->call_tree, NULL); + link_parents (info.profile->call_tree, NULL); - g_hash_table_foreach (profile->nodes_by_object, compute_object_total, NULL); + g_hash_table_foreach (info.profile->nodes_by_object, compute_object_total, NULL); g_hash_table_destroy (info.profile_objects); - return profile; + return info.profile; } static void diff --git a/sfile.c b/sfile.c index e6f94bd3..5c68f3fb 100644 --- a/sfile.c +++ b/sfile.c @@ -727,17 +727,26 @@ handle_text (GMarkupParseContext *context, { case POINTER: if (!get_number (text, &action.u.pointer.target_id)) - /* FIXME: set error */; + { + set_invalid_content_error (err, "Contents '%s' of pointer element is not a number", text); + return; + } break; case INTEGER: if (!get_number (text, &action.u.integer.value)) - /* FIXME: set error */; + { + set_invalid_content_error (err, "Contents '%s' of integer element not a number", text); + return; + } break; case STRING: if (!decode_text (text, &action.u.string.value)) - /* FIXME: set error */ + { + set_invalid_content_error (err, "Contents '%s' of text element is illformed", text); + return; + } break; default: @@ -947,6 +956,7 @@ void sfile_begin_add_record (SFileOutput *file, const char *name) { + Action action; TransitionType type; file->state = state_transition_begin (file->state, name, &type, NULL); @@ -960,9 +970,10 @@ void sfile_begin_add_list (SFileOutput *file, const char *name) { + Action action; TransitionType type; - file->state = state_transition_begin (file->state, name, &type, NULL); + file->state = state_transition_begin (file->state, name, &action.type, NULL); g_return_if_fail (file->state && type == BEGIN_LIST); diff --git a/sysprof-module.c b/sysprof-module.c index 05a1cfa5..4b5711a9 100644 --- a/sysprof-module.c +++ b/sysprof-module.c @@ -304,7 +304,7 @@ on_timer(unsigned long dong) { struct task_struct *p; - static const int cpu_profiler = 0; /* set to 0 to profile disk */ + static const int cpu_profiler = 1; /* set to 0 to profile disk */ for_each_process (p) { if (p->state == (cpu_profiler? TASK_RUNNING : TASK_UNINTERRUPTIBLE)) {