[sysprof] Initial support for fork/exit events
- From: Søren Sandmann Pedersen <ssp src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [sysprof] Initial support for fork/exit events
- Date: Mon, 14 Sep 2009 09:09:07 +0000 (UTC)
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]