mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
Initial support for fork/exit events
This commit is contained in:
9
TODO
9
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.
|
||||
|
||||
47
collector.c
47
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,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
107
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);
|
||||
|
||||
@ -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,
|
||||
|
||||
Reference in New Issue
Block a user