[sysprof] Fake new_process and new_map events when a tracker is created



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]