From b7f2caf385a1d29b872a8d94d0bc1a4cb6dea4ef Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 2 Aug 2010 18:18:28 -0300 Subject: [PATCH] --- yaml --- r: 205365 b: refs/heads/master c: 076c6e45215aea0de1ed34d3d5079fabeaabf5e1 h: refs/heads/master i: 205363: 41f70b73ecb780dcbc996dcfc2e6de867b785edd v: v3 --- [refs] | 2 +- .../arch/powerpc/kernel/perf_event_fsl_emb.c | 29 ++++++------- trunk/tools/perf/util/map.c | 18 +++++--- trunk/tools/perf/util/map.h | 7 +++ trunk/tools/perf/util/session.c | 7 +++ trunk/tools/perf/util/symbol.c | 43 +++++++++++++++++++ trunk/tools/perf/util/symbol.h | 2 + 7 files changed, 85 insertions(+), 23 deletions(-) diff --git a/[refs] b/[refs] index 05ff6c28c667..b8b48b99e7ba 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 69e77a8b0426ded5d924eea7dbe4eca51e09f530 +refs/heads/master: 076c6e45215aea0de1ed34d3d5079fabeaabf5e1 diff --git a/trunk/arch/powerpc/kernel/perf_event_fsl_emb.c b/trunk/arch/powerpc/kernel/perf_event_fsl_emb.c index 1ba45471ae43..babcceecd2ea 100644 --- a/trunk/arch/powerpc/kernel/perf_event_fsl_emb.c +++ b/trunk/arch/powerpc/kernel/perf_event_fsl_emb.c @@ -162,15 +162,15 @@ static void fsl_emb_pmu_read(struct perf_event *event) * Therefore we treat them like NMIs. */ do { - prev = local64_read(&event->hw.prev_count); + prev = atomic64_read(&event->hw.prev_count); barrier(); val = read_pmc(event->hw.idx); - } while (local64_cmpxchg(&event->hw.prev_count, prev, val) != prev); + } while (atomic64_cmpxchg(&event->hw.prev_count, prev, val) != prev); /* The counters are only 32 bits wide */ delta = (val - prev) & 0xfffffffful; - local64_add(delta, &event->count); - local64_sub(delta, &event->hw.period_left); + atomic64_add(delta, &event->count); + atomic64_sub(delta, &event->hw.period_left); } /* @@ -296,11 +296,11 @@ static int fsl_emb_pmu_enable(struct perf_event *event) val = 0; if (event->hw.sample_period) { - s64 left = local64_read(&event->hw.period_left); + s64 left = atomic64_read(&event->hw.period_left); if (left < 0x80000000L) val = 0x80000000L - left; } - local64_set(&event->hw.prev_count, val); + atomic64_set(&event->hw.prev_count, val); write_pmc(i, val); perf_event_update_userpage(event); @@ -371,8 +371,8 @@ static void fsl_emb_pmu_unthrottle(struct perf_event *event) if (left < 0x80000000L) val = 0x80000000L - left; write_pmc(event->hw.idx, val); - local64_set(&event->hw.prev_count, val); - local64_set(&event->hw.period_left, left); + atomic64_set(&event->hw.prev_count, val); + atomic64_set(&event->hw.period_left, left); perf_event_update_userpage(event); perf_enable(); local_irq_restore(flags); @@ -500,7 +500,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) return ERR_PTR(-ENOTSUPP); event->hw.last_period = event->hw.sample_period; - local64_set(&event->hw.period_left, event->hw.last_period); + atomic64_set(&event->hw.period_left, event->hw.last_period); /* * See if we need to reserve the PMU. @@ -541,16 +541,16 @@ static void record_and_restart(struct perf_event *event, unsigned long val, int record = 0; /* we don't have to worry about interrupts here */ - prev = local64_read(&event->hw.prev_count); + prev = atomic64_read(&event->hw.prev_count); delta = (val - prev) & 0xfffffffful; - local64_add(delta, &event->count); + atomic64_add(delta, &event->count); /* * See if the total period for this event has expired, * and update for the next period. */ val = 0; - left = local64_read(&event->hw.period_left) - delta; + left = atomic64_read(&event->hw.period_left) - delta; if (period) { if (left <= 0) { left += period; @@ -569,7 +569,6 @@ static void record_and_restart(struct perf_event *event, unsigned long val, struct perf_sample_data data; perf_sample_data_init(&data, 0); - data.period = event->hw.last_period; if (perf_event_overflow(event, nmi, &data, regs)) { /* @@ -585,8 +584,8 @@ static void record_and_restart(struct perf_event *event, unsigned long val, } write_pmc(event->hw.idx, val); - local64_set(&event->hw.prev_count, val); - local64_set(&event->hw.period_left, left); + atomic64_set(&event->hw.prev_count, val); + atomic64_set(&event->hw.period_left, left); perf_event_update_userpage(event); } diff --git a/trunk/tools/perf/util/map.c b/trunk/tools/perf/util/map.c index 15d6a6dd50c5..801e6962b0a6 100644 --- a/trunk/tools/perf/util/map.c +++ b/trunk/tools/perf/util/map.c @@ -506,6 +506,11 @@ void maps__insert(struct rb_root *maps, struct map *map) rb_insert_color(&map->rb_node, maps); } +void maps__remove(struct rb_root *self, struct map *map) +{ + rb_erase(&map->rb_node, self); +} + struct map *maps__find(struct rb_root *maps, u64 ip) { struct rb_node **p = &maps->rb_node; @@ -551,13 +556,6 @@ static void dsos__delete(struct list_head *self) void machine__exit(struct machine *self) { - struct kmap *kmap = map__kmap(self->vmlinux_maps[MAP__FUNCTION]); - - if (kmap->ref_reloc_sym) { - free((char *)kmap->ref_reloc_sym->name); - free(kmap->ref_reloc_sym); - } - map_groups__exit(&self->kmaps); dsos__delete(&self->user_dsos); dsos__delete(&self->kernel_dsos); @@ -565,6 +563,12 @@ void machine__exit(struct machine *self) self->root_dir = NULL; } +void machine__delete(struct machine *self) +{ + machine__exit(self); + free(self); +} + struct machine *machines__add(struct rb_root *self, pid_t pid, const char *root_dir) { diff --git a/trunk/tools/perf/util/map.h b/trunk/tools/perf/util/map.h index 0e0984e86fce..5b51bbd2f734 100644 --- a/trunk/tools/perf/util/map.h +++ b/trunk/tools/perf/util/map.h @@ -125,6 +125,7 @@ void map__reloc_vmlinux(struct map *self); size_t __map_groups__fprintf_maps(struct map_groups *self, enum map_type type, int verbose, FILE *fp); void maps__insert(struct rb_root *maps, struct map *map); +void maps__remove(struct rb_root *self, struct map *map); struct map *maps__find(struct rb_root *maps, u64 addr); void map_groups__init(struct map_groups *self); void map_groups__exit(struct map_groups *self); @@ -144,6 +145,7 @@ struct machine *machines__findnew(struct rb_root *self, pid_t pid); char *machine__mmap_name(struct machine *self, char *bf, size_t size); int machine__init(struct machine *self, const char *root_dir, pid_t pid); void machine__exit(struct machine *self); +void machine__delete(struct machine *self); /* * Default guest kernel is defined by parameter --guestkallsyms @@ -165,6 +167,11 @@ static inline void map_groups__insert(struct map_groups *self, struct map *map) map->groups = self; } +static inline void map_groups__remove(struct map_groups *self, struct map *map) +{ + maps__remove(&self->maps[map->type], map); +} + static inline struct map *map_groups__find(struct map_groups *self, enum map_type type, u64 addr) { diff --git a/trunk/tools/perf/util/session.c b/trunk/tools/perf/util/session.c index 04a3b3db9e90..5d2fd52fe7b5 100644 --- a/trunk/tools/perf/util/session.c +++ b/trunk/tools/perf/util/session.c @@ -79,6 +79,12 @@ int perf_session__create_kernel_maps(struct perf_session *self) return ret; } +static void perf_session__destroy_kernel_maps(struct perf_session *self) +{ + machine__destroy_kernel_maps(&self->host_machine); + machines__destroy_guest_kernel_maps(&self->machines); +} + struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) { size_t len = filename ? strlen(filename) + 1 : 0; @@ -150,6 +156,7 @@ static void perf_session__delete_threads(struct perf_session *self) void perf_session__delete(struct perf_session *self) { perf_header__exit(&self->header); + perf_session__destroy_kernel_maps(self); perf_session__delete_dead_threads(self); perf_session__delete_threads(self); machine__exit(&self->host_machine); diff --git a/trunk/tools/perf/util/symbol.c b/trunk/tools/perf/util/symbol.c index 3b8c00506672..6f0dd90c36ce 100644 --- a/trunk/tools/perf/util/symbol.c +++ b/trunk/tools/perf/util/symbol.c @@ -2107,6 +2107,36 @@ int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) return 0; } +void machine__destroy_kernel_maps(struct machine *self) +{ + enum map_type type; + + for (type = 0; type < MAP__NR_TYPES; ++type) { + struct kmap *kmap; + + if (self->vmlinux_maps[type] == NULL) + continue; + + kmap = map__kmap(self->vmlinux_maps[type]); + map_groups__remove(&self->kmaps, self->vmlinux_maps[type]); + if (kmap->ref_reloc_sym) { + /* + * ref_reloc_sym is shared among all maps, so free just + * on one of them. + */ + if (type == MAP__FUNCTION) { + free((char *)kmap->ref_reloc_sym->name); + kmap->ref_reloc_sym->name = NULL; + free(kmap->ref_reloc_sym); + } + kmap->ref_reloc_sym = NULL; + } + + map__delete(self->vmlinux_maps[type]); + self->vmlinux_maps[type] = NULL; + } +} + int machine__create_kernel_maps(struct machine *self) { struct dso *kernel = machine__create_kernel(self); @@ -2351,6 +2381,19 @@ int machines__create_guest_kernel_maps(struct rb_root *self) return ret; } +void machines__destroy_guest_kernel_maps(struct rb_root *self) +{ + struct rb_node *next = rb_first(self); + + while (next) { + struct machine *pos = rb_entry(next, struct machine, rb_node); + + next = rb_next(&pos->rb_node); + rb_erase(&pos->rb_node, self); + machine__delete(pos); + } +} + int machine__load_kallsyms(struct machine *self, const char *filename, enum map_type type, symbol_filter_t filter) { diff --git a/trunk/tools/perf/util/symbol.h b/trunk/tools/perf/util/symbol.h index 33d53ce28958..906be20011d9 100644 --- a/trunk/tools/perf/util/symbol.h +++ b/trunk/tools/perf/util/symbol.h @@ -212,11 +212,13 @@ int kallsyms__parse(const char *filename, void *arg, int (*process_symbol)(void *arg, const char *name, char type, u64 start)); +void machine__destroy_kernel_maps(struct machine *self); int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); int machine__create_kernel_maps(struct machine *self); int machines__create_kernel_maps(struct rb_root *self, pid_t pid); int machines__create_guest_kernel_maps(struct rb_root *self); +void machines__destroy_guest_kernel_maps(struct rb_root *self); int symbol__init(void); void symbol__exit(void);