[sysprof] Fake new_process and new_map events when a tracker is created
- From: Søren Sandmann Pedersen <ssp src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [sysprof] Fake new_process and new_map events when a tracker is created
- Date: Mon, 14 Sep 2009 09:07:51 +0000 (UTC)
commit b86b04910fe50e3ccd256c8da3e6934f29702bff
Author: Søren Sandmann Pedersen <ssp redhat com>
Date: Mon Sep 7 18:18:26 2009 -0400
Fake new_process and new_map events when a tracker is created
collector.c | 42 ++++++++++-
sysprof.c | 2 +-
tracker.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 263 insertions(+), 20 deletions(-)
---
diff --git a/collector.c b/collector.c
index 7315da9..31bfdd8 100644
--- a/collector.c
+++ b/collector.c
@@ -34,6 +34,7 @@
#include "watch.h"
#include "process.h"
#include "elfparser.h"
+#include "tracker.h"
#include "perf_counter.h"
#include "barrier.h"
@@ -45,7 +46,6 @@ typedef struct sample_event_t sample_event_t;
typedef struct mmap_event_t mmap_event_t;
typedef struct comm_event_t comm_event_t;
typedef union counter_event_t counter_event_t;
-typedef void (* event_callback_t) (counter_event_t *event, gpointer data);
static void process_event (Collector *collector, counter_event_t *event);
@@ -103,6 +103,7 @@ struct Collector
gpointer data;
StackStash * stash;
+ tracker_t * tracker;
GTimeVal latest_reset;
int n_samples;
@@ -240,6 +241,10 @@ map_buffer (counter_t *counter)
int n_bytes = N_PAGES * process_get_page_size();
void *address, *a;
+ /* We use the old trick of mapping the ring buffer twice
+ * consecutively, so that we don't need special-case code
+ * to deal with wrapping.
+ */
address = mmap (NULL, n_bytes * 2 + process_get_page_size(), PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
@@ -281,7 +286,7 @@ counter_new (Collector *collector,
attr.type = PERF_TYPE_HARDWARE;
attr.config = PERF_COUNT_HW_CPU_CYCLES;
attr.sample_period = 1200000 ; /* In number of clock cycles -
- * use frequency instead FIXME
+ * FIXME: consider using frequency instead
*/
attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_CALLCHAIN;
attr.wakeup_events = 100000;
@@ -343,15 +348,34 @@ counter_free (counter_t *counter)
void
collector_reset (Collector *collector)
{
+ gboolean restart = FALSE;
+
+ if (collector->counters)
+ {
+ collector_stop (collector);
+ restart = TRUE;
+ }
+
if (collector->stash)
+ {
stack_stash_unref (collector->stash);
+ collector->stash = NULL;
+ }
+ if (collector->tracker)
+ {
+ tracker_free (collector->tracker);
+ collector->tracker = NULL;
+ }
+
process_flush_caches();
- collector->stash = stack_stash_new (NULL);
collector->n_samples = 0;
g_get_current_time (&collector->latest_reset);
+
+ if (restart)
+ collector_start (collector, NULL);
}
/* callback is called whenever a new sample arrives */
@@ -364,6 +388,7 @@ collector_new (CollectorFunc callback,
collector->callback = callback;
collector->data = data;
collector->stash = NULL;
+ collector->tracker = NULL;
collector_reset (collector);
@@ -507,6 +532,15 @@ collector_start (Collector *collector,
GList *list;
int i;
+ g_print ("starting\n");
+
+ if (!collector->stash)
+ collector->stash = stack_stash_new (NULL);
+ if (!collector->tracker)
+ collector->tracker = tracker_new ();
+
+ g_assert (collector->stash);
+
for (i = 0; i < n_cpus; ++i)
{
counter_t *counter = counter_new (collector, i);
@@ -522,6 +556,8 @@ collector_start (Collector *collector,
for (list = collector->counters; list != NULL; list = list->next)
counter_enable (list->data);
+
+ g_print ("started\n");
return TRUE;
}
diff --git a/sysprof.c b/sysprof.c
index fd689b7..f3b8d77 100644
--- a/sysprof.c
+++ b/sysprof.c
@@ -374,7 +374,7 @@ on_start_toggled (GtkWidget *widget, gpointer data)
}
else
{
- sorry (app->main_window, err->message);
+ sorry (app->main_window, err->message);
g_error_free (err);
}
diff --git a/tracker.c b/tracker.c
index 65978eb..8970718 100644
--- a/tracker.c
+++ b/tracker.c
@@ -1,5 +1,7 @@
#include <glib.h>
#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "tracker.h"
#include "stackstash.h"
@@ -22,31 +24,31 @@ typedef enum
NEW_PROCESS,
NEW_MAP,
SAMPLE
-} event_type;
+} event_type_t;
struct new_process_t
{
- event_type type;
- int32_t pid;
- char command_line[256];
+ event_type_t type;
+ int32_t pid;
+ char command_line[256];
};
struct new_map_t
{
- event_type type;
- int32_t pid;
- char file_name[PATH_MAX];
- uint64_t start;
- uint64_t end;
- uint64_t offset;
- uint64_t inode;
+ event_type_t type;
+ int32_t pid;
+ char file_name[PATH_MAX];
+ uint64_t start;
+ uint64_t end;
+ uint64_t offset;
+ uint64_t inode;
};
struct sample_t
{
- event_type type;
- int32_t pid;
- StackNode * trace;
+ event_type_t type;
+ int32_t pid;
+ StackNode * trace;
};
#define DEFAULT_SIZE (1024 * 1024 * 4)
@@ -70,6 +72,136 @@ tracker_append (tracker_t *tracker,
memcpy (tracker->events + tracker->n_event_bytes, event, n_bytes);
}
+static char **
+get_lines (const char *format, pid_t pid)
+{
+ char *filename = g_strdup_printf (format, pid);
+ char **result = NULL;
+ char *contents;
+
+ if (g_file_get_contents (filename, &contents, NULL, NULL))
+ {
+ result = g_strsplit (contents, "\n", -1);
+
+ g_free (contents);
+ }
+
+ g_free (filename);
+
+ return result;
+}
+
+static void
+fake_new_process (tracker_t *tracker, pid_t pid)
+{
+ char **lines;
+
+ if ((lines = get_lines ("/proc/%d/status", pid)))
+ {
+ int i;
+
+ for (i = 0; lines[i] != NULL; ++i)
+ {
+ if (strncmp ("Name:", lines[i], 5) == 0)
+ {
+ tracker_add_process (tracker, pid, g_strstrip (strchr (lines[i], ':')));
+ break;
+ }
+ }
+
+ g_strfreev (lines);
+ }
+}
+
+static void
+fake_new_map (tracker_t *tracker, pid_t pid)
+{
+ char **lines;
+
+ if ((lines = get_lines ("/proc/%d/maps", pid)))
+ {
+ int i;
+
+ for (i = 0; lines[i] != NULL; ++i)
+ {
+ char file[256];
+ gulong start;
+ gulong end;
+ gulong offset;
+ gulong inode;
+ int count;
+
+ file[255] = '\0';
+
+ count = sscanf (
+ lines[i], "%lx-%lx %*15s %lx %*x:%*x %lu %255s",
+ &start, &end, &offset, &inode, file);
+
+ if (count == 5)
+ {
+ if (strcmp (file, "[vdso]") == 0)
+ {
+ /* For the vdso, the kernel reports 'offset' as the
+ * the same as the mapping addres. This doesn't make
+ * any sense to me, so we just zero it here. There
+ * is code in binfile.c (read_inode) that returns 0
+ * for [vdso].
+ */
+ offset = 0;
+ inode = 0;
+ }
+
+ tracker_add_map (tracker, pid, start, end, offset, inode, file);
+ }
+ }
+
+ g_strfreev (lines);
+ }
+}
+
+static void
+populate_from_proc (tracker_t *tracker)
+{
+ GDir *proc = g_dir_open ("/proc", 0, NULL);
+ const char *name;
+
+ if (!proc)
+ return;
+
+ while ((name = g_dir_read_name (proc)))
+ {
+ pid_t pid;
+ char *end;
+
+ pid = strtol (name, &end, 10);
+
+ if (*end == 0)
+ {
+ fake_new_process (tracker, pid);
+ fake_new_map (tracker, pid);
+ }
+ }
+
+ g_dir_close (proc);
+}
+
+
+static double
+timeval_to_ms (const GTimeVal *timeval)
+{
+ return (timeval->tv_sec * G_USEC_PER_SEC + timeval->tv_usec) / 1000.0;
+}
+
+static double
+time_diff (const GTimeVal *first,
+ const GTimeVal *second)
+{
+ double first_ms = timeval_to_ms (first);
+ double second_ms = timeval_to_ms (second);
+
+ return first_ms - second_ms;
+}
+
tracker_t *
tracker_new (void)
{
@@ -80,6 +212,16 @@ tracker_new (void)
tracker->events = g_malloc (DEFAULT_SIZE);
tracker->stash = stack_stash_new (NULL);
+
+ GTimeVal before, after;
+
+ g_get_current_time (&before);
+
+ populate_from_proc (tracker);
+
+ g_get_current_time (&after);
+
+ g_print ("Time to populate %f\n", time_diff (&after, &before));
return tracker;
}
@@ -87,7 +229,9 @@ tracker_new (void)
void
tracker_free (tracker_t *tracker)
{
-
+ stack_stash_unref (tracker->stash);
+ g_free (tracker->events);
+ g_free (tracker);
}
#define COPY_STRING(dest, src) \
@@ -111,6 +255,10 @@ tracker_add_process (tracker_t * tracker,
COPY_STRING (event.command_line, command_line);
tracker_append (tracker, &event, sizeof (event));
+
+#if 0
+ g_print ("Added new process: %d (%s)\n", pid, command_line);
+#endif
}
void
@@ -133,6 +281,10 @@ tracker_add_map (tracker_t * tracker,
event.inode = inode;
tracker_append (tracker, &event, sizeof (event));
+
+#if 0
+ g_print (" Added new map: %d (%s)\n", pid, filename);
+#endif
}
void
@@ -150,8 +302,63 @@ tracker_add_sample (tracker_t *tracker,
tracker_append (tracker, &event, sizeof (event));
}
+/* */
+typedef struct state_t state_t;
+
+struct state_t
+{
+
+};
+
+static void
+new_process (state_t *tracker, new_process_t *new_process)
+{
+
+}
+
+static void
+new_map (state_t *tracker, new_map_t *new_map)
+{
+
+}
+
+static void
+sample (state_t *tracker, sample_t *sample)
+{
+
+}
+
Profile *
tracker_create_profile (tracker_t *tracker)
{
-
+ uint8_t *end = tracker->events + tracker->n_event_bytes;
+ uint8_t *event;
+
+ event = tracker->events;
+ while (event < end)
+ {
+ event_type_t type = *(event_type_t *)event;
+ new_process_t *new_process;
+ new_map_t *new_map;
+ sample_t *sample;
+
+ switch (type)
+ {
+ case NEW_PROCESS:
+
+
+ break;
+
+ case NEW_MAP:
+
+
+ break;
+
+ case SAMPLE:
+
+
+ break;
+ }
+
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]