mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-11 23:51:06 +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:
|
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
|
* Find out what's up with weird two-step flash when you hit start when
|
||||||
a profile is loaded.
|
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 sample_event_t sample_event_t;
|
||||||
typedef struct mmap_event_t mmap_event_t;
|
typedef struct mmap_event_t mmap_event_t;
|
||||||
typedef struct comm_event_t comm_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;
|
typedef union counter_event_t counter_event_t;
|
||||||
|
|
||||||
static void process_event (Collector *collector, counter_event_t *event);
|
static void process_event (Collector *collector, counter_event_t *event);
|
||||||
@ -89,12 +91,30 @@ struct mmap_event_t
|
|||||||
char filename[1];
|
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
|
union counter_event_t
|
||||||
{
|
{
|
||||||
struct perf_event_header header;
|
struct perf_event_header header;
|
||||||
mmap_event_t mmap;
|
mmap_event_t mmap;
|
||||||
comm_event_t comm;
|
comm_event_t comm;
|
||||||
sample_event_t sample;
|
sample_event_t sample;
|
||||||
|
fork_event_t fork;
|
||||||
|
exit_event_t exit;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Collector
|
struct Collector
|
||||||
@ -312,8 +332,13 @@ counter_new (Collector *collector,
|
|||||||
attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_CALLCHAIN;
|
attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_CALLCHAIN;
|
||||||
attr.wakeup_events = 100000;
|
attr.wakeup_events = 100000;
|
||||||
attr.disabled = TRUE;
|
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);
|
fd = sysprof_perf_counter_open (&attr, -1, cpu, -1, 0);
|
||||||
|
|
||||||
@ -429,11 +454,27 @@ process_mmap (Collector *collector, mmap_event_t *mmap)
|
|||||||
static void
|
static void
|
||||||
process_comm (Collector *collector, comm_event_t *comm)
|
process_comm (Collector *collector, comm_event_t *comm)
|
||||||
{
|
{
|
||||||
|
g_print ("comm: pid: %d\n", comm->pid);
|
||||||
|
|
||||||
tracker_add_process (collector->tracker,
|
tracker_add_process (collector->tracker,
|
||||||
comm->pid,
|
comm->pid,
|
||||||
comm->comm);
|
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
|
static void
|
||||||
process_sample (Collector *collector,
|
process_sample (Collector *collector,
|
||||||
sample_event_t *sample)
|
sample_event_t *sample)
|
||||||
@ -473,6 +514,7 @@ process_event (Collector *collector,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PERF_EVENT_EXIT:
|
case PERF_EVENT_EXIT:
|
||||||
|
process_exit (collector, &event->exit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PERF_EVENT_THROTTLE:
|
case PERF_EVENT_THROTTLE:
|
||||||
@ -482,6 +524,7 @@ process_event (Collector *collector,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PERF_EVENT_FORK:
|
case PERF_EVENT_FORK:
|
||||||
|
process_fork (collector, &event->fork);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PERF_EVENT_READ:
|
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_process_t new_process_t;
|
||||||
typedef struct new_map_t new_map_t;
|
typedef struct new_map_t new_map_t;
|
||||||
typedef struct sample_t sample_t;
|
typedef struct sample_t sample_t;
|
||||||
|
typedef struct fork_t fork_t;
|
||||||
|
typedef struct exit_t exit_t;
|
||||||
|
|
||||||
struct tracker_t
|
struct tracker_t
|
||||||
{
|
{
|
||||||
@ -27,7 +29,9 @@ typedef enum
|
|||||||
{
|
{
|
||||||
NEW_PROCESS,
|
NEW_PROCESS,
|
||||||
NEW_MAP,
|
NEW_MAP,
|
||||||
SAMPLE
|
SAMPLE,
|
||||||
|
FORK,
|
||||||
|
EXIT
|
||||||
} event_type_t;
|
} event_type_t;
|
||||||
|
|
||||||
struct new_process_t
|
struct new_process_t
|
||||||
@ -37,6 +41,19 @@ struct new_process_t
|
|||||||
char command_line[256];
|
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
|
struct new_map_t
|
||||||
{
|
{
|
||||||
event_type_t type;
|
event_type_t type;
|
||||||
@ -279,9 +296,33 @@ tracker_add_process (tracker_t * tracker,
|
|||||||
|
|
||||||
tracker_append (tracker, &event, sizeof (event));
|
tracker_append (tracker, &event, sizeof (event));
|
||||||
|
|
||||||
#if 0
|
|
||||||
g_print ("Added new process: %d (%s)\n", pid, command_line);
|
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
|
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);
|
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
|
static void
|
||||||
free_process (gpointer data)
|
free_process (gpointer data)
|
||||||
{
|
{
|
||||||
@ -811,7 +900,7 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
|
|||||||
static gboolean warned;
|
static gboolean warned;
|
||||||
if (!warned || sample->pid != 0)
|
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;
|
warned = TRUE;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -890,6 +979,16 @@ tracker_create_profile (tracker_t *tracker)
|
|||||||
create_map (state, (new_map_t *)event);
|
create_map (state, (new_map_t *)event);
|
||||||
event += sizeof (new_map_t);
|
event += sizeof (new_map_t);
|
||||||
break;
|
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:
|
case SAMPLE:
|
||||||
process_sample (state, resolved_stash, (sample_t *)event);
|
process_sample (state, resolved_stash, (sample_t *)event);
|
||||||
|
|||||||
@ -9,6 +9,11 @@ void tracker_free (tracker_t *);
|
|||||||
void tracker_add_process (tracker_t *tracker,
|
void tracker_add_process (tracker_t *tracker,
|
||||||
pid_t pid,
|
pid_t pid,
|
||||||
const char *command_line);
|
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,
|
void tracker_add_map (tracker_t * tracker,
|
||||||
pid_t pid,
|
pid_t pid,
|
||||||
uint64_t start,
|
uint64_t start,
|
||||||
|
|||||||
Reference in New Issue
Block a user