[sysprof] Initial support for fork/exit events



commit e277712037058ef04bdc671dd070a9e0e5d3b43f
Author: Søren Sandmann Pedersen <ssp redhat com>
Date:   Tue Sep 8 02:26:04 2009 -0400

    Initial support for fork/exit events

 TODO        |    9 ++++-
 collector.c |   47 +++++++++++++++++++++++++-
 tracker.c   |  107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 tracker.h   |    5 +++
 4 files changed, 161 insertions(+), 7 deletions(-)
---
diff --git a/TODO b/TODO
index 92cb8a0..f83a6b9 100644
--- a/TODO
+++ b/TODO
@@ -23,7 +23,14 @@ Before 1.0.4:
 
 Before 1.2:
 
-* Flash when double clicking in descendants view
+* Counters must not be destroyed during tracker setup. They have to exist
+  but be disabled so that we can track creation of processes.
+
+* Check that we don't use too much memory (in particular with the timeline).
+
+* Fix names. "new process" is really "exec"
+
+* Fix flash when double clicking in descendants view
 
 * Find out what's up with weird two-step flash when you hit start when
   a profile is loaded.
diff --git a/collector.c b/collector.c
index df0172a..56b181d 100644
--- a/collector.c
+++ b/collector.c
@@ -44,6 +44,8 @@ typedef struct counter_t counter_t;
 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 struct exit_event_t exit_event_t;
+typedef struct fork_event_t fork_event_t;
 typedef union counter_event_t counter_event_t;
 
 static void process_event (Collector *collector, counter_event_t *event);
@@ -89,12 +91,30 @@ struct mmap_event_t
     char			filename[1];
 };
 
+struct fork_event_t
+{
+    struct perf_event_header	header;
+    
+    uint32_t			pid, ppid;
+    uint32_t			tid, ptid;
+};
+
+struct exit_event_t
+{
+    struct perf_event_header	header;
+
+    uint32_t			pid, ppid;
+    uint32_t			tid, ptid;
+};
+
 union counter_event_t
 {
     struct perf_event_header	header;
     mmap_event_t		mmap;
     comm_event_t		comm;
     sample_event_t		sample;
+    fork_event_t		fork;
+    exit_event_t		exit;
 };
 
 struct Collector
@@ -312,8 +332,13 @@ counter_new (Collector *collector,
     attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_CALLCHAIN;
     attr.wakeup_events = 100000;
     attr.disabled = TRUE;
-    attr.mmap = TRUE;
-    attr.comm = TRUE;
+
+    if (cpu == 0)
+    {
+	attr.mmap = 1;
+	attr.comm = 1;
+	attr.task = 1;
+    }
     
     fd = sysprof_perf_counter_open (&attr, -1, cpu, -1,  0);
     
@@ -429,12 +454,28 @@ process_mmap (Collector *collector, mmap_event_t *mmap)
 static void
 process_comm (Collector *collector, comm_event_t *comm)
 {
+    g_print ("comm: pid: %d\n", comm->pid);
+    
     tracker_add_process (collector->tracker,
 			 comm->pid,
 			 comm->comm);
 }
 
 static void
+process_fork (Collector *collector, fork_event_t *fork)
+{
+    g_print ("fork: ppid: %d  pid: %d\n", fork->ppid, fork->pid);
+    
+    tracker_add_fork (collector->tracker, fork->ppid, fork->pid);
+}
+
+static void
+process_exit (Collector *collector, exit_event_t *exit)
+{
+    tracker_add_exit (collector->tracker, exit->pid);
+}
+
+static void
 process_sample (Collector      *collector,
 		sample_event_t *sample)
 {
@@ -473,6 +514,7 @@ process_event (Collector       *collector,
 	break;
 	
     case PERF_EVENT_EXIT:
+	process_exit (collector, &event->exit);
 	break;
 	
     case PERF_EVENT_THROTTLE:
@@ -482,6 +524,7 @@ process_event (Collector       *collector,
 	break;
 	
     case PERF_EVENT_FORK:
+	process_fork (collector, &event->fork);
 	break;
 	
     case PERF_EVENT_READ:
diff --git a/tracker.c b/tracker.c
index f89abcf..2b93318 100644
--- a/tracker.c
+++ b/tracker.c
@@ -13,6 +13,8 @@
 typedef struct new_process_t new_process_t;
 typedef struct new_map_t new_map_t;
 typedef struct sample_t sample_t;
+typedef struct fork_t fork_t;
+typedef struct exit_t exit_t;
 
 struct tracker_t
 {
@@ -27,7 +29,9 @@ typedef enum
 {
     NEW_PROCESS,
     NEW_MAP,
-    SAMPLE
+    SAMPLE,
+    FORK,
+    EXIT
 } event_type_t;
 
 struct new_process_t
@@ -37,6 +41,19 @@ struct new_process_t
     char		command_line[256];
 };
 
+struct fork_t
+{
+    event_type_t	type;
+    int32_t		pid;
+    int32_t		child_pid;
+};
+
+struct exit_t
+{
+    event_type_t	type;
+    int32_t		pid;
+};
+
 struct new_map_t
 {
     event_type_t	type;
@@ -279,9 +296,33 @@ tracker_add_process (tracker_t * tracker,
     
     tracker_append (tracker, &event, sizeof (event));
     
-#if 0
     g_print ("Added new process: %d (%s)\n", pid, command_line);
-#endif
+}
+
+void
+tracker_add_fork (tracker_t *tracker,
+		  pid_t      pid,
+		  pid_t	     child_pid)
+{
+    fork_t event;
+
+    event.type = FORK;
+    event.pid = pid;
+    event.child_pid = child_pid;
+
+    tracker_append (tracker, &event, sizeof (event));
+}
+
+void
+tracker_add_exit (tracker_t *tracker,
+		  pid_t      pid)
+{
+    exit_t event;
+    
+    event.type = EXIT;
+    event.pid = pid;
+
+    tracker_append (tracker, &event, sizeof (event));
 }
 
 void
@@ -426,6 +467,54 @@ create_process (state_t *state, new_process_t *new_process)
 	state->processes_by_pid, GINT_TO_POINTER (process->pid), process);
 }
 
+static map_t *
+copy_map (map_t *map)
+{
+    map_t *copy = g_new0 (map_t, 1);
+
+    *copy = *map;
+    copy->filename = g_strdup (map->filename);
+
+    return copy;
+}
+
+static void
+process_fork (state_t *state, fork_t *fork)
+{
+    process_t *parent = g_hash_table_lookup (
+	state->processes_by_pid, GINT_TO_POINTER (fork->pid));
+
+    if (parent)
+    {
+	process_t *process = g_new0 (process_t, 1);
+	int i;
+
+	g_print ("new child %d\n", fork->child_pid);
+	
+	process->pid = fork->child_pid;
+	process->comm = g_strdup (parent->comm);
+	process->maps = g_ptr_array_new ();
+
+	for (i = 0; i < parent->maps->len; ++i)
+	{
+	    map_t *map = copy_map (parent->maps->pdata[i]);
+	    
+	    g_ptr_array_add (process->maps, map);
+	}
+
+	g_hash_table_insert (
+	    state->processes_by_pid, GINT_TO_POINTER (process->pid), process);
+    }
+    else
+	g_print ("no parent for %d\n", fork->child_pid);
+}
+
+static void
+process_exit (state_t *state, exit_t *exit)
+{
+    /* ignore for now */
+}
+
 static void
 free_process (gpointer data)
 {
@@ -811,7 +900,7 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
 	static gboolean warned;
 	if (!warned || sample->pid != 0)
 	{
-	    g_warning ("sample for unknown process %d", sample->pid);
+	    g_print ("sample for unknown process %d\n", sample->pid);
 	    warned = TRUE;
 	}
 	return;
@@ -890,6 +979,16 @@ tracker_create_profile (tracker_t *tracker)
 	    create_map (state, (new_map_t *)event);
 	    event += sizeof (new_map_t);
 	    break;
+
+	case FORK:
+	    process_fork (state, (fork_t *)event);
+	    event += sizeof (fork_t);
+	    break;
+
+	case EXIT:
+	    process_exit (state, (exit_t *)exit);
+	    event += sizeof (exit_t);
+	    break;
 	    
 	case SAMPLE:
 	    process_sample (state, resolved_stash, (sample_t *)event);
diff --git a/tracker.h b/tracker.h
index 71b33d8..098f4a1 100644
--- a/tracker.h
+++ b/tracker.h
@@ -9,6 +9,11 @@ void	   tracker_free (tracker_t *);
 void tracker_add_process (tracker_t  *tracker,
 			  pid_t	      pid,
 			  const char *command_line);
+void tracker_add_fork (tracker_t *tracker,
+		       pid_t      pid,
+		       pid_t	  child_pid);
+void tracker_add_exit (tracker_t *tracker,
+		       pid_t      pid);
 void tracker_add_map (tracker_t * tracker,
 		      pid_t	     pid,
 		      uint64_t    start,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]