Initial support for fork/exit events

This commit is contained in:
Søren Sandmann Pedersen
2009-09-08 02:26:04 -04:00
parent 6e1e43ff3b
commit e277712037
4 changed files with 161 additions and 7 deletions

9
TODO
View File

@ -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.

View File

@ -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,11 +454,27 @@ 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:

107
tracker.c
View File

@ -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);

View File

@ -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,