From cdc7ce7e12c22c63bde9a2ccc1474ab8cc6af57d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Mon, 7 Sep 2009 19:16:52 -0400 Subject: [PATCH] Add process and map tracking to tracker --- collector.c | 10 +++- tracker.c | 156 +++++++++++++++++++++++++++++++++++++++++++++------- tracker.h | 16 +++--- 3 files changed, 151 insertions(+), 31 deletions(-) diff --git a/collector.c b/collector.c index acea8f81..b6b1ff24 100644 --- a/collector.c +++ b/collector.c @@ -217,8 +217,13 @@ on_read (gpointer data) } if (!skip_samples || header->type != PERF_EVENT_SAMPLE) + { + if (header->type == PERF_EVENT_SAMPLE) + collector->n_samples++; + process_event (collector, (counter_event_t *)header); - + } + tail += header->size; } @@ -422,7 +427,6 @@ process_sample (Collector *collector, { uint64_t *ips; int n_ips; - if (sample->n_ips == 0) { ips = &sample->ip; @@ -433,7 +437,7 @@ process_sample (Collector *collector, ips = sample->ips; n_ips = sample->n_ips; } - + tracker_add_sample (collector->tracker, sample->pid, ips, n_ips); } diff --git a/tracker.c b/tracker.c index 7f8b2e01..bb76cd24 100644 --- a/tracker.c +++ b/tracker.c @@ -5,6 +5,7 @@ #include "tracker.h" #include "stackstash.h" +#include "binfile.h" typedef struct new_process_t new_process_t; typedef struct new_map_t new_map_t; @@ -13,10 +14,10 @@ typedef struct sample_t sample_t; struct tracker_t { StackStash *stash; - - size_t n_event_bytes; - size_t n_allocated_bytes; - uint8_t *events; + + size_t n_event_bytes; + size_t n_allocated_bytes; + uint8_t * events; }; typedef enum @@ -37,7 +38,7 @@ struct new_map_t { event_type_t type; int32_t pid; - char file_name[PATH_MAX]; + char filename[PATH_MAX]; uint64_t start; uint64_t end; uint64_t offset; @@ -274,7 +275,7 @@ tracker_add_map (tracker_t * tracker, event.type = NEW_MAP; event.pid = pid; - COPY_STRING (event.file_name, filename); + COPY_STRING (event.filename, filename); event.start = start; event.end = end; event.offset = offset; @@ -304,26 +305,135 @@ tracker_add_sample (tracker_t *tracker, /* */ typedef struct state_t state_t; +typedef struct process_t process_t; +typedef struct map_t map_t; + +struct process_t +{ + pid_t pid; + + char * comm; + char * undefined; + + GPtrArray * maps; +}; + +struct map_t +{ + char * filename; + uint64_t start; + uint64_t end; + uint64_t offset; + uint64_t inode; + + BinFile * bin_file; +}; struct state_t { - + GHashTable *processes_by_pid; }; static void -new_process (state_t *tracker, new_process_t *new_process) +destroy_map (map_t *map) { + if (map->bin_file) + bin_file_free (map->bin_file); + g_free (map->filename); + g_free (map); } static void -new_map (state_t *tracker, new_map_t *new_map) +create_map (state_t *state, new_map_t *new_map) { + process_t *process; + map_t *map; + int i; + process = g_hash_table_lookup ( + state->processes_by_pid, GINT_TO_POINTER (new_map->pid)); + + if (!process) + return; + + map = g_new0 (map_t, 1); + map->filename = g_strdup (new_map->filename); + map->start = new_map->start; + map->end = new_map->end; + map->offset = new_map->offset; + map->inode = new_map->inode; + + /* Remove existing maps that overlap the new one */ + for (i = 0; i < process->maps->len; ++i) + { + map_t *m = process->maps->pdata[i]; + + if (m->start < map->end && m->end > map->start) + { + destroy_map (m); + + g_ptr_array_remove_index (process->maps, i); + } + } + + g_ptr_array_add (process->maps, map); } static void -sample (state_t *tracker, sample_t *sample) +destroy_process (process_t *process) +{ + int i; + + g_free (process->comm); + g_free (process->undefined); + + for (i = 0; i < process->maps->len; ++i) + { + map_t *map = process->maps->pdata[i]; + + destroy_map (map); + } + + g_ptr_array_free (process->maps, TRUE); + g_free (process); +} + +static void +create_process (state_t *state, new_process_t *new_process) +{ + process_t *process = g_new0 (process_t, 1); + + process->pid = new_process->pid; + process->comm = g_strdup (new_process->command_line); + process->undefined = NULL; + process->maps = g_ptr_array_new (); + + g_hash_table_insert ( + state->processes_by_pid, GINT_TO_POINTER (process->pid), process); +} + +static void +free_process (gpointer data) +{ + process_t *process = data; + + destroy_process (process); +} + +static state_t * +state_new (void) +{ + state_t *state = g_new0 (state_t, 1); + + state->processes_by_pid = + g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_process); + + return state; +} + +static void +process_sample (state_t *tracker, sample_t *sample) { } @@ -331,33 +441,39 @@ Profile * tracker_create_profile (tracker_t *tracker) { uint8_t *end = tracker->events + tracker->n_event_bytes; + StackStash *resolved_stash; + Profile *profile; + state_t *state; uint8_t *event; - + + state = state_new (); + resolved_stash = stack_stash_new (g_free); + event = tracker->events; while (event < end) { event_type_t type = *(event_type_t *)event; - new_process_t *new_process; - new_map_t *new_map; - sample_t *sample; switch (type) { case NEW_PROCESS: - - + create_process (state, (new_process_t *)event); break; case NEW_MAP: - - + create_map (state, (new_map_t *)event); break; case SAMPLE: - - + process_sample (state, (sample_t *)event); break; } } + + profile = profile_new (resolved_stash); + + stack_stash_unref (resolved_stash); + + return profile; } diff --git a/tracker.h b/tracker.h index e4caf603..71b33d84 100644 --- a/tracker.h +++ b/tracker.h @@ -9,16 +9,16 @@ void tracker_free (tracker_t *); void tracker_add_process (tracker_t *tracker, pid_t pid, const char *command_line); -void -tracker_add_map (tracker_t * tracker, - pid_t pid, - uint64_t start, - uint64_t end, - uint64_t offset, - uint64_t inode, - const char *filename); +void tracker_add_map (tracker_t * tracker, + pid_t pid, + uint64_t start, + uint64_t end, + uint64_t offset, + uint64_t inode, + const char *filename); void tracker_add_sample (tracker_t *tracker, pid_t pid, uint64_t *ips, int n_ips); + Profile *tracker_create_profile (tracker_t *tracker);