All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Ian Rogers <irogers@google.com>
Cc: "Peter Zijlstra" <peterz@infradead.org>,
	"Ingo Molnar" <mingo@redhat.com>,
	"Mark Rutland" <mark.rutland@arm.com>,
	"Alexander Shishkin" <alexander.shishkin@linux.intel.com>,
	"Jiri Olsa" <jolsa@kernel.org>,
	"Namhyung Kim" <namhyung@kernel.org>,
	"Thomas Gleixner" <tglx@linutronix.de>,
	"Darren Hart" <dvhart@infradead.org>,
	"Davidlohr Bueso" <dave@stgolabs.net>,
	"André Almeida" <andrealmeid@collabora.com>,
	"James Clark" <james.clark@arm.com>,
	"John Garry" <john.garry@huawei.com>,
	"Riccardo Mancini" <rickyman7@gmail.com>,
	"Yury Norov" <yury.norov@gmail.com>,
	"Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Jin Yao" <yao.jin@linux.intel.com>,
	"Adrian Hunter" <adrian.hunter@intel.com>,
	"Leo Yan" <leo.yan@linaro.org>, "Andi Kleen" <ak@linux.intel.com>,
	"Thomas Richter" <tmricht@linux.ibm.com>,
	"Kan Liang" <kan.liang@linux.intel.com>,
	"Madhavan Srinivasan" <maddy@linux.ibm.com>,
	"Shunsuke Nakamura" <nakamura.shun@fujitsu.com>,
	"Song Liu" <song@kernel.org>,
	"Masami Hiramatsu" <mhiramat@kernel.org>,
	"Steven Rostedt" <rostedt@goodmis.org>,
	"Miaoqian Lin" <linmq006@gmail.com>,
	"Stephen Brennan" <stephen.s.brennan@oracle.com>,
	"Kajol Jain" <kjain@linux.ibm.com>,
	"Alexey Bayduraev" <alexey.v.bayduraev@linux.intel.com>,
	"German Gomez" <german.gomez@arm.com>,
	linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Eric Dumazet" <edumazet@google.com>,
	"Dmitry Vyukov" <dvyukov@google.com>,
	"Hao Luo" <haoluo@google.com>,
	eranian@google.com
Subject: Re: [PATCH v3 08/22] perf maps: Move maps code to own C file
Date: Fri, 11 Feb 2022 14:27:16 -0300	[thread overview]
Message-ID: <YgacdG+/M519DZQ+@kernel.org> (raw)
In-Reply-To: <20220211103415.2737789-9-irogers@google.com>

Em Fri, Feb 11, 2022 at 02:34:01AM -0800, Ian Rogers escreveu:
> The maps code has its own header, move the corresponding C function
> definitions to their own C file. In the process tidy and minimize
> includes.

Depends on previously not processed patches.
 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  tools/perf/util/Build  |   1 +
>  tools/perf/util/map.c  | 417 +----------------------------------------
>  tools/perf/util/map.h  |   2 +
>  tools/perf/util/maps.c | 403 +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 414 insertions(+), 409 deletions(-)
>  create mode 100644 tools/perf/util/maps.c
> 
> diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> index 2a403cefcaf2..9a7209a99e16 100644
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -56,6 +56,7 @@ perf-y += debug.o
>  perf-y += fncache.o
>  perf-y += machine.o
>  perf-y += map.o
> +perf-y += maps.o
>  perf-y += pstack.o
>  perf-y += session.o
>  perf-y += sample-raw.o
> diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
> index 4d1de363c19a..2cfe5744b86c 100644
> --- a/tools/perf/util/map.c
> +++ b/tools/perf/util/map.c
> @@ -1,31 +1,20 @@
>  // SPDX-License-Identifier: GPL-2.0
> -#include "symbol.h"
> -#include <assert.h>
> -#include <errno.h>
>  #include <inttypes.h>
>  #include <limits.h>
> +#include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> -#include <stdio.h>
> -#include <unistd.h>
> +#include <linux/string.h>
> +#include <linux/zalloc.h>
>  #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
> +#include "debug.h"
>  #include "dso.h"
>  #include "map.h"
> -#include "map_symbol.h"
> +#include "namespaces.h"
> +#include "srcline.h"
> +#include "symbol.h"
>  #include "thread.h"
>  #include "vdso.h"
> -#include "build-id.h"
> -#include "debug.h"
> -#include "machine.h"
> -#include <linux/string.h>
> -#include <linux/zalloc.h>
> -#include "srcline.h"
> -#include "namespaces.h"
> -#include "unwind.h"
> -#include "srccode.h"
> -#include "ui/ui.h"
> -
> -static void __maps__insert(struct maps *maps, struct map *map);
>  
>  static inline int is_android_lib(const char *filename)
>  {
> @@ -527,403 +516,13 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
>  	return ip + map->reloc;
>  }
>  
> -static void maps__init(struct maps *maps, struct machine *machine)
> -{
> -	maps->entries = RB_ROOT;
> -	init_rwsem(&maps->lock);
> -	maps->machine = machine;
> -	maps->last_search_by_name = NULL;
> -	maps->nr_maps = 0;
> -	maps->maps_by_name = NULL;
> -	refcount_set(&maps->refcnt, 1);
> -}
> -
> -static void __maps__free_maps_by_name(struct maps *maps)
> -{
> -	/*
> -	 * Free everything to try to do it from the rbtree in the next search
> -	 */
> -	zfree(&maps->maps_by_name);
> -	maps->nr_maps_allocated = 0;
> -}
> -
> -void maps__insert(struct maps *maps, struct map *map)
> -{
> -	down_write(&maps->lock);
> -	__maps__insert(maps, map);
> -	++maps->nr_maps;
> -
> -	if (map->dso && map->dso->kernel) {
> -		struct kmap *kmap = map__kmap(map);
> -
> -		if (kmap)
> -			kmap->kmaps = maps;
> -		else
> -			pr_err("Internal error: kernel dso with non kernel map\n");
> -	}
> -
> -
> -	/*
> -	 * If we already performed some search by name, then we need to add the just
> -	 * inserted map and resort.
> -	 */
> -	if (maps->maps_by_name) {
> -		if (maps->nr_maps > maps->nr_maps_allocated) {
> -			int nr_allocate = maps->nr_maps * 2;
> -			struct map **maps_by_name = realloc(maps->maps_by_name, nr_allocate * sizeof(map));
> -
> -			if (maps_by_name == NULL) {
> -				__maps__free_maps_by_name(maps);
> -				up_write(&maps->lock);
> -				return;
> -			}
> -
> -			maps->maps_by_name = maps_by_name;
> -			maps->nr_maps_allocated = nr_allocate;
> -		}
> -		maps->maps_by_name[maps->nr_maps - 1] = map;
> -		__maps__sort_by_name(maps);
> -	}
> -	up_write(&maps->lock);
> -}
> -
> -static void __maps__remove(struct maps *maps, struct map *map)
> -{
> -	rb_erase_init(&map->rb_node, &maps->entries);
> -	map__put(map);
> -}
> -
> -void maps__remove(struct maps *maps, struct map *map)
> -{
> -	down_write(&maps->lock);
> -	if (maps->last_search_by_name == map)
> -		maps->last_search_by_name = NULL;
> -
> -	__maps__remove(maps, map);
> -	--maps->nr_maps;
> -	if (maps->maps_by_name)
> -		__maps__free_maps_by_name(maps);
> -	up_write(&maps->lock);
> -}
> -
> -static void __maps__purge(struct maps *maps)
> -{
> -	struct map *pos, *next;
> -
> -	maps__for_each_entry_safe(maps, pos, next) {
> -		rb_erase_init(&pos->rb_node,  &maps->entries);
> -		map__put(pos);
> -	}
> -}
> -
> -static void maps__exit(struct maps *maps)
> -{
> -	down_write(&maps->lock);
> -	__maps__purge(maps);
> -	up_write(&maps->lock);
> -}
> -
> -bool maps__empty(struct maps *maps)
> -{
> -	return !maps__first(maps);
> -}
> -
> -struct maps *maps__new(struct machine *machine)
> -{
> -	struct maps *maps = zalloc(sizeof(*maps));
> -
> -	if (maps != NULL)
> -		maps__init(maps, machine);
> -
> -	return maps;
> -}
> -
> -void maps__delete(struct maps *maps)
> -{
> -	maps__exit(maps);
> -	unwind__finish_access(maps);
> -	free(maps);
> -}
> -
> -void maps__put(struct maps *maps)
> -{
> -	if (maps && refcount_dec_and_test(&maps->refcnt))
> -		maps__delete(maps);
> -}
> -
> -struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp)
> -{
> -	struct map *map = maps__find(maps, addr);
> -
> -	/* Ensure map is loaded before using map->map_ip */
> -	if (map != NULL && map__load(map) >= 0) {
> -		if (mapp != NULL)
> -			*mapp = map;
> -		return map__find_symbol(map, map->map_ip(map, addr));
> -	}
> -
> -	return NULL;
> -}
> -
> -static bool map__contains_symbol(struct map *map, struct symbol *sym)
> +bool map__contains_symbol(struct map *map, struct symbol *sym)
>  {
>  	u64 ip = map->unmap_ip(map, sym->start);
>  
>  	return ip >= map->start && ip < map->end;
>  }
>  
> -struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp)
> -{
> -	struct symbol *sym;
> -	struct map *pos;
> -
> -	down_read(&maps->lock);
> -
> -	maps__for_each_entry(maps, pos) {
> -		sym = map__find_symbol_by_name(pos, name);
> -
> -		if (sym == NULL)
> -			continue;
> -		if (!map__contains_symbol(pos, sym)) {
> -			sym = NULL;
> -			continue;
> -		}
> -		if (mapp != NULL)
> -			*mapp = pos;
> -		goto out;
> -	}
> -
> -	sym = NULL;
> -out:
> -	up_read(&maps->lock);
> -	return sym;
> -}
> -
> -int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams)
> -{
> -	if (ams->addr < ams->ms.map->start || ams->addr >= ams->ms.map->end) {
> -		if (maps == NULL)
> -			return -1;
> -		ams->ms.map = maps__find(maps, ams->addr);
> -		if (ams->ms.map == NULL)
> -			return -1;
> -	}
> -
> -	ams->al_addr = ams->ms.map->map_ip(ams->ms.map, ams->addr);
> -	ams->ms.sym = map__find_symbol(ams->ms.map, ams->al_addr);
> -
> -	return ams->ms.sym ? 0 : -1;
> -}
> -
> -size_t maps__fprintf(struct maps *maps, FILE *fp)
> -{
> -	size_t printed = 0;
> -	struct map *pos;
> -
> -	down_read(&maps->lock);
> -
> -	maps__for_each_entry(maps, pos) {
> -		printed += fprintf(fp, "Map:");
> -		printed += map__fprintf(pos, fp);
> -		if (verbose > 2) {
> -			printed += dso__fprintf(pos->dso, fp);
> -			printed += fprintf(fp, "--\n");
> -		}
> -	}
> -
> -	up_read(&maps->lock);
> -
> -	return printed;
> -}
> -
> -int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
> -{
> -	struct rb_root *root;
> -	struct rb_node *next, *first;
> -	int err = 0;
> -
> -	down_write(&maps->lock);
> -
> -	root = &maps->entries;
> -
> -	/*
> -	 * Find first map where end > map->start.
> -	 * Same as find_vma() in kernel.
> -	 */
> -	next = root->rb_node;
> -	first = NULL;
> -	while (next) {
> -		struct map *pos = rb_entry(next, struct map, rb_node);
> -
> -		if (pos->end > map->start) {
> -			first = next;
> -			if (pos->start <= map->start)
> -				break;
> -			next = next->rb_left;
> -		} else
> -			next = next->rb_right;
> -	}
> -
> -	next = first;
> -	while (next) {
> -		struct map *pos = rb_entry(next, struct map, rb_node);
> -		next = rb_next(&pos->rb_node);
> -
> -		/*
> -		 * Stop if current map starts after map->end.
> -		 * Maps are ordered by start: next will not overlap for sure.
> -		 */
> -		if (pos->start >= map->end)
> -			break;
> -
> -		if (verbose >= 2) {
> -
> -			if (use_browser) {
> -				pr_debug("overlapping maps in %s (disable tui for more info)\n",
> -					   map->dso->name);
> -			} else {
> -				fputs("overlapping maps:\n", fp);
> -				map__fprintf(map, fp);
> -				map__fprintf(pos, fp);
> -			}
> -		}
> -
> -		rb_erase_init(&pos->rb_node, root);
> -		/*
> -		 * Now check if we need to create new maps for areas not
> -		 * overlapped by the new map:
> -		 */
> -		if (map->start > pos->start) {
> -			struct map *before = map__clone(pos);
> -
> -			if (before == NULL) {
> -				err = -ENOMEM;
> -				goto put_map;
> -			}
> -
> -			before->end = map->start;
> -			__maps__insert(maps, before);
> -			if (verbose >= 2 && !use_browser)
> -				map__fprintf(before, fp);
> -			map__put(before);
> -		}
> -
> -		if (map->end < pos->end) {
> -			struct map *after = map__clone(pos);
> -
> -			if (after == NULL) {
> -				err = -ENOMEM;
> -				goto put_map;
> -			}
> -
> -			after->start = map->end;
> -			after->pgoff += map->end - pos->start;
> -			assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end));
> -			__maps__insert(maps, after);
> -			if (verbose >= 2 && !use_browser)
> -				map__fprintf(after, fp);
> -			map__put(after);
> -		}
> -put_map:
> -		map__put(pos);
> -
> -		if (err)
> -			goto out;
> -	}
> -
> -	err = 0;
> -out:
> -	up_write(&maps->lock);
> -	return err;
> -}
> -
> -/*
> - * XXX This should not really _copy_ te maps, but refcount them.
> - */
> -int maps__clone(struct thread *thread, struct maps *parent)
> -{
> -	struct maps *maps = thread->maps;
> -	int err;
> -	struct map *map;
> -
> -	down_read(&parent->lock);
> -
> -	maps__for_each_entry(parent, map) {
> -		struct map *new = map__clone(map);
> -
> -		if (new == NULL) {
> -			err = -ENOMEM;
> -			goto out_unlock;
> -		}
> -
> -		err = unwind__prepare_access(maps, new, NULL);
> -		if (err)
> -			goto out_unlock;
> -
> -		maps__insert(maps, new);
> -		map__put(new);
> -	}
> -
> -	err = 0;
> -out_unlock:
> -	up_read(&parent->lock);
> -	return err;
> -}
> -
> -static void __maps__insert(struct maps *maps, struct map *map)
> -{
> -	struct rb_node **p = &maps->entries.rb_node;
> -	struct rb_node *parent = NULL;
> -	const u64 ip = map->start;
> -	struct map *m;
> -
> -	while (*p != NULL) {
> -		parent = *p;
> -		m = rb_entry(parent, struct map, rb_node);
> -		if (ip < m->start)
> -			p = &(*p)->rb_left;
> -		else
> -			p = &(*p)->rb_right;
> -	}
> -
> -	rb_link_node(&map->rb_node, parent, p);
> -	rb_insert_color(&map->rb_node, &maps->entries);
> -	map__get(map);
> -}
> -
> -struct map *maps__find(struct maps *maps, u64 ip)
> -{
> -	struct rb_node *p;
> -	struct map *m;
> -
> -	down_read(&maps->lock);
> -
> -	p = maps->entries.rb_node;
> -	while (p != NULL) {
> -		m = rb_entry(p, struct map, rb_node);
> -		if (ip < m->start)
> -			p = p->rb_left;
> -		else if (ip >= m->end)
> -			p = p->rb_right;
> -		else
> -			goto out;
> -	}
> -
> -	m = NULL;
> -out:
> -	up_read(&maps->lock);
> -	return m;
> -}
> -
> -struct map *maps__first(struct maps *maps)
> -{
> -	struct rb_node *first = rb_first(&maps->entries);
> -
> -	if (first)
> -		return rb_entry(first, struct map, rb_node);
> -	return NULL;
> -}
> -
>  static struct map *__map__next(struct map *map)
>  {
>  	struct rb_node *next = rb_next(&map->rb_node);
> diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
> index d32f5b28c1fb..973dce27b253 100644
> --- a/tools/perf/util/map.h
> +++ b/tools/perf/util/map.h
> @@ -160,6 +160,8 @@ static inline bool __map__is_kmodule(const struct map *map)
>  
>  bool map__has_symbols(const struct map *map);
>  
> +bool map__contains_symbol(struct map *map, struct symbol *sym);
> +
>  #define ENTRY_TRAMPOLINE_NAME "__entry_SYSCALL_64_trampoline"
>  
>  static inline bool is_entry_trampoline(const char *name)
> diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c
> new file mode 100644
> index 000000000000..ededabf0a230
> --- /dev/null
> +++ b/tools/perf/util/maps.c
> @@ -0,0 +1,403 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <linux/zalloc.h>
> +#include "debug.h"
> +#include "dso.h"
> +#include "map.h"
> +#include "maps.h"
> +#include "thread.h"
> +#include "ui/ui.h"
> +#include "unwind.h"
> +
> +static void __maps__insert(struct maps *maps, struct map *map);
> +
> +void maps__init(struct maps *maps, struct machine *machine)
> +{
> +	maps->entries = RB_ROOT;
> +	init_rwsem(&maps->lock);
> +	maps->machine = machine;
> +	maps->last_search_by_name = NULL;
> +	maps->nr_maps = 0;
> +	maps->maps_by_name = NULL;
> +	refcount_set(&maps->refcnt, 1);
> +}
> +
> +static void __maps__free_maps_by_name(struct maps *maps)
> +{
> +	/*
> +	 * Free everything to try to do it from the rbtree in the next search
> +	 */
> +	zfree(&maps->maps_by_name);
> +	maps->nr_maps_allocated = 0;
> +}
> +
> +void maps__insert(struct maps *maps, struct map *map)
> +{
> +	down_write(&maps->lock);
> +	__maps__insert(maps, map);
> +	++maps->nr_maps;
> +
> +	if (map->dso && map->dso->kernel) {
> +		struct kmap *kmap = map__kmap(map);
> +
> +		if (kmap)
> +			kmap->kmaps = maps;
> +		else
> +			pr_err("Internal error: kernel dso with non kernel map\n");
> +	}
> +
> +
> +	/*
> +	 * If we already performed some search by name, then we need to add the just
> +	 * inserted map and resort.
> +	 */
> +	if (maps->maps_by_name) {
> +		if (maps->nr_maps > maps->nr_maps_allocated) {
> +			int nr_allocate = maps->nr_maps * 2;
> +			struct map **maps_by_name = realloc(maps->maps_by_name, nr_allocate * sizeof(map));
> +
> +			if (maps_by_name == NULL) {
> +				__maps__free_maps_by_name(maps);
> +				up_write(&maps->lock);
> +				return;
> +			}
> +
> +			maps->maps_by_name = maps_by_name;
> +			maps->nr_maps_allocated = nr_allocate;
> +		}
> +		maps->maps_by_name[maps->nr_maps - 1] = map;
> +		__maps__sort_by_name(maps);
> +	}
> +	up_write(&maps->lock);
> +}
> +
> +static void __maps__remove(struct maps *maps, struct map *map)
> +{
> +	rb_erase_init(&map->rb_node, &maps->entries);
> +	map__put(map);
> +}
> +
> +void maps__remove(struct maps *maps, struct map *map)
> +{
> +	down_write(&maps->lock);
> +	if (maps->last_search_by_name == map)
> +		maps->last_search_by_name = NULL;
> +
> +	__maps__remove(maps, map);
> +	--maps->nr_maps;
> +	if (maps->maps_by_name)
> +		__maps__free_maps_by_name(maps);
> +	up_write(&maps->lock);
> +}
> +
> +static void __maps__purge(struct maps *maps)
> +{
> +	struct map *pos, *next;
> +
> +	maps__for_each_entry_safe(maps, pos, next) {
> +		rb_erase_init(&pos->rb_node,  &maps->entries);
> +		map__put(pos);
> +	}
> +}
> +
> +void maps__exit(struct maps *maps)
> +{
> +	down_write(&maps->lock);
> +	__maps__purge(maps);
> +	up_write(&maps->lock);
> +}
> +
> +bool maps__empty(struct maps *maps)
> +{
> +	return !maps__first(maps);
> +}
> +
> +struct maps *maps__new(struct machine *machine)
> +{
> +	struct maps *maps = zalloc(sizeof(*maps));
> +
> +	if (maps != NULL)
> +		maps__init(maps, machine);
> +
> +	return maps;
> +}
> +
> +void maps__delete(struct maps *maps)
> +{
> +	maps__exit(maps);
> +	unwind__finish_access(maps);
> +	free(maps);
> +}
> +
> +void maps__put(struct maps *maps)
> +{
> +	if (maps && refcount_dec_and_test(&maps->refcnt))
> +		maps__delete(maps);
> +}
> +
> +struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp)
> +{
> +	struct map *map = maps__find(maps, addr);
> +
> +	/* Ensure map is loaded before using map->map_ip */
> +	if (map != NULL && map__load(map) >= 0) {
> +		if (mapp != NULL)
> +			*mapp = map;
> +		return map__find_symbol(map, map->map_ip(map, addr));
> +	}
> +
> +	return NULL;
> +}
> +
> +struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp)
> +{
> +	struct symbol *sym;
> +	struct map *pos;
> +
> +	down_read(&maps->lock);
> +
> +	maps__for_each_entry(maps, pos) {
> +		sym = map__find_symbol_by_name(pos, name);
> +
> +		if (sym == NULL)
> +			continue;
> +		if (!map__contains_symbol(pos, sym)) {
> +			sym = NULL;
> +			continue;
> +		}
> +		if (mapp != NULL)
> +			*mapp = pos;
> +		goto out;
> +	}
> +
> +	sym = NULL;
> +out:
> +	up_read(&maps->lock);
> +	return sym;
> +}
> +
> +int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams)
> +{
> +	if (ams->addr < ams->ms.map->start || ams->addr >= ams->ms.map->end) {
> +		if (maps == NULL)
> +			return -1;
> +		ams->ms.map = maps__find(maps, ams->addr);
> +		if (ams->ms.map == NULL)
> +			return -1;
> +	}
> +
> +	ams->al_addr = ams->ms.map->map_ip(ams->ms.map, ams->addr);
> +	ams->ms.sym = map__find_symbol(ams->ms.map, ams->al_addr);
> +
> +	return ams->ms.sym ? 0 : -1;
> +}
> +
> +size_t maps__fprintf(struct maps *maps, FILE *fp)
> +{
> +	size_t printed = 0;
> +	struct map *pos;
> +
> +	down_read(&maps->lock);
> +
> +	maps__for_each_entry(maps, pos) {
> +		printed += fprintf(fp, "Map:");
> +		printed += map__fprintf(pos, fp);
> +		if (verbose > 2) {
> +			printed += dso__fprintf(pos->dso, fp);
> +			printed += fprintf(fp, "--\n");
> +		}
> +	}
> +
> +	up_read(&maps->lock);
> +
> +	return printed;
> +}
> +
> +int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
> +{
> +	struct rb_root *root;
> +	struct rb_node *next, *first;
> +	int err = 0;
> +
> +	down_write(&maps->lock);
> +
> +	root = &maps->entries;
> +
> +	/*
> +	 * Find first map where end > map->start.
> +	 * Same as find_vma() in kernel.
> +	 */
> +	next = root->rb_node;
> +	first = NULL;
> +	while (next) {
> +		struct map *pos = rb_entry(next, struct map, rb_node);
> +
> +		if (pos->end > map->start) {
> +			first = next;
> +			if (pos->start <= map->start)
> +				break;
> +			next = next->rb_left;
> +		} else
> +			next = next->rb_right;
> +	}
> +
> +	next = first;
> +	while (next) {
> +		struct map *pos = rb_entry(next, struct map, rb_node);
> +		next = rb_next(&pos->rb_node);
> +
> +		/*
> +		 * Stop if current map starts after map->end.
> +		 * Maps are ordered by start: next will not overlap for sure.
> +		 */
> +		if (pos->start >= map->end)
> +			break;
> +
> +		if (verbose >= 2) {
> +
> +			if (use_browser) {
> +				pr_debug("overlapping maps in %s (disable tui for more info)\n",
> +					   map->dso->name);
> +			} else {
> +				fputs("overlapping maps:\n", fp);
> +				map__fprintf(map, fp);
> +				map__fprintf(pos, fp);
> +			}
> +		}
> +
> +		rb_erase_init(&pos->rb_node, root);
> +		/*
> +		 * Now check if we need to create new maps for areas not
> +		 * overlapped by the new map:
> +		 */
> +		if (map->start > pos->start) {
> +			struct map *before = map__clone(pos);
> +
> +			if (before == NULL) {
> +				err = -ENOMEM;
> +				goto put_map;
> +			}
> +
> +			before->end = map->start;
> +			__maps__insert(maps, before);
> +			if (verbose >= 2 && !use_browser)
> +				map__fprintf(before, fp);
> +			map__put(before);
> +		}
> +
> +		if (map->end < pos->end) {
> +			struct map *after = map__clone(pos);
> +
> +			if (after == NULL) {
> +				err = -ENOMEM;
> +				goto put_map;
> +			}
> +
> +			after->start = map->end;
> +			after->pgoff += map->end - pos->start;
> +			assert(pos->map_ip(pos, map->end) == after->map_ip(after, map->end));
> +			__maps__insert(maps, after);
> +			if (verbose >= 2 && !use_browser)
> +				map__fprintf(after, fp);
> +			map__put(after);
> +		}
> +put_map:
> +		map__put(pos);
> +
> +		if (err)
> +			goto out;
> +	}
> +
> +	err = 0;
> +out:
> +	up_write(&maps->lock);
> +	return err;
> +}
> +
> +/*
> + * XXX This should not really _copy_ te maps, but refcount them.
> + */
> +int maps__clone(struct thread *thread, struct maps *parent)
> +{
> +	struct maps *maps = thread->maps;
> +	int err;
> +	struct map *map;
> +
> +	down_read(&parent->lock);
> +
> +	maps__for_each_entry(parent, map) {
> +		struct map *new = map__clone(map);
> +
> +		if (new == NULL) {
> +			err = -ENOMEM;
> +			goto out_unlock;
> +		}
> +
> +		err = unwind__prepare_access(maps, new, NULL);
> +		if (err)
> +			goto out_unlock;
> +
> +		maps__insert(maps, new);
> +		map__put(new);
> +	}
> +
> +	err = 0;
> +out_unlock:
> +	up_read(&parent->lock);
> +	return err;
> +}
> +
> +static void __maps__insert(struct maps *maps, struct map *map)
> +{
> +	struct rb_node **p = &maps->entries.rb_node;
> +	struct rb_node *parent = NULL;
> +	const u64 ip = map->start;
> +	struct map *m;
> +
> +	while (*p != NULL) {
> +		parent = *p;
> +		m = rb_entry(parent, struct map, rb_node);
> +		if (ip < m->start)
> +			p = &(*p)->rb_left;
> +		else
> +			p = &(*p)->rb_right;
> +	}
> +
> +	rb_link_node(&map->rb_node, parent, p);
> +	rb_insert_color(&map->rb_node, &maps->entries);
> +	map__get(map);
> +}
> +
> +struct map *maps__find(struct maps *maps, u64 ip)
> +{
> +	struct rb_node *p;
> +	struct map *m;
> +
> +	down_read(&maps->lock);
> +
> +	p = maps->entries.rb_node;
> +	while (p != NULL) {
> +		m = rb_entry(p, struct map, rb_node);
> +		if (ip < m->start)
> +			p = p->rb_left;
> +		else if (ip >= m->end)
> +			p = p->rb_right;
> +		else
> +			goto out;
> +	}
> +
> +	m = NULL;
> +out:
> +	up_read(&maps->lock);
> +	return m;
> +}
> +
> +struct map *maps__first(struct maps *maps)
> +{
> +	struct rb_node *first = rb_first(&maps->entries);
> +
> +	if (first)
> +		return rb_entry(first, struct map, rb_node);
> +	return NULL;
> +}
> -- 
> 2.35.1.265.g69c8d7142f-goog

-- 

- Arnaldo

  reply	other threads:[~2022-02-11 17:27 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-11 10:33 [PATCH v3 00/22] Reference count checker and related fixes Ian Rogers
2022-02-11 10:33 ` [PATCH v3 01/22] perf cpumap: Migrate to libperf cpumap api Ian Rogers
2022-02-11 17:02   ` Arnaldo Carvalho de Melo
2022-02-11 10:33 ` [PATCH v3 02/22] perf cpumap: Use for each loop Ian Rogers
2022-02-11 17:04   ` Arnaldo Carvalho de Melo
2022-02-11 10:33 ` [PATCH v3 03/22] perf dso: Make lock error check and add BUG_ONs Ian Rogers
2022-02-11 17:13   ` Arnaldo Carvalho de Melo
2022-02-11 17:43     ` Ian Rogers
2022-02-11 19:21       ` Arnaldo Carvalho de Melo
2022-02-11 19:35         ` Ian Rogers
2022-02-12 15:48           ` Arnaldo Carvalho de Melo
2022-02-12 15:49             ` Arnaldo Carvalho de Melo
2022-02-12 20:59               ` Ian Rogers
2022-02-11 10:33 ` [PATCH v3 04/22] perf dso: Hold lock when accessing nsinfo Ian Rogers
2022-02-11 17:14   ` Arnaldo Carvalho de Melo
2022-02-12 11:30   ` Jiri Olsa
2022-02-11 10:33 ` [PATCH v3 05/22] perf maps: Use a pointer for kmaps Ian Rogers
2022-02-11 17:23   ` Arnaldo Carvalho de Melo
2022-02-14 19:45     ` Arnaldo Carvalho de Melo
2022-02-11 10:33 ` [PATCH v3 06/22] perf test: Use pointer for maps Ian Rogers
2022-02-11 17:24   ` Arnaldo Carvalho de Melo
2022-02-14 19:48   ` Arnaldo Carvalho de Melo
2022-02-14 19:50     ` Arnaldo Carvalho de Melo
2022-02-11 10:34 ` [PATCH v3 07/22] perf maps: Reduce scope of init and exit Ian Rogers
2022-02-11 17:26   ` Arnaldo Carvalho de Melo
2022-02-11 10:34 ` [PATCH v3 08/22] perf maps: Move maps code to own C file Ian Rogers
2022-02-11 17:27   ` Arnaldo Carvalho de Melo [this message]
2022-02-14 19:58   ` Arnaldo Carvalho de Melo
2022-02-11 10:34 ` [PATCH v3 09/22] perf map: Add const to map_ip and unmap_ip Ian Rogers
2022-02-11 17:28   ` Arnaldo Carvalho de Melo
2022-02-11 10:34 ` [PATCH v3 10/22] perf map: Make map__contains_symbol args const Ian Rogers
2022-02-11 17:28   ` Arnaldo Carvalho de Melo
2022-02-11 10:34 ` [PATCH v3 11/22] perf map: Move map list node into symbol Ian Rogers
2022-02-11 10:34 ` [PATCH v3 12/22] perf maps: Remove rb_node from struct map Ian Rogers
2022-02-16 14:08   ` Arnaldo Carvalho de Melo
2022-02-16 17:36     ` Ian Rogers
2022-02-16 20:12       ` Arnaldo Carvalho de Melo
2022-02-16 22:07         ` Ian Rogers
2022-02-11 10:34 ` [PATCH v3 13/22] perf namespaces: Add functions to access nsinfo Ian Rogers
2022-02-11 17:31   ` Arnaldo Carvalho de Melo
2022-02-11 10:34 ` [PATCH v3 14/22] perf maps: Add functions to access maps Ian Rogers
2022-02-11 17:33   ` Arnaldo Carvalho de Melo
2022-02-11 10:34 ` [PATCH v3 15/22] perf map: Use functions to access the variables in map Ian Rogers
2022-02-11 17:35   ` Arnaldo Carvalho de Melo
2022-02-11 17:36   ` Arnaldo Carvalho de Melo
2022-02-11 17:54     ` Ian Rogers
2022-02-11 19:22       ` Arnaldo Carvalho de Melo
2022-02-11 10:34 ` [PATCH v3 16/22] perf test: Add extra diagnostics to maps test Ian Rogers
2022-02-11 10:34 ` [PATCH v3 17/22] perf map: Changes to reference counting Ian Rogers
2022-02-12  8:45   ` Masami Hiramatsu
2022-02-12 20:48     ` Ian Rogers
2022-02-14  2:00       ` Masami Hiramatsu
2022-02-14 18:56       ` Arnaldo Carvalho de Melo
2022-02-11 10:34 ` [PATCH v3 18/22] libperf: Add reference count checking macros Ian Rogers
2022-02-11 10:34 ` [PATCH v3 19/22] perf cpumap: Add reference count checking Ian Rogers
2022-02-11 10:34 ` [PATCH v3 20/22] perf namespaces: " Ian Rogers
2022-02-11 10:34 ` [PATCH v3 21/22] perf maps: " Ian Rogers
2022-02-11 10:34 ` [PATCH v3 22/22] perf map: " Ian Rogers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YgacdG+/M519DZQ+@kernel.org \
    --to=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=ak@linux.intel.com \
    --cc=akpm@linux-foundation.org \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=alexey.v.bayduraev@linux.intel.com \
    --cc=andrealmeid@collabora.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=dave@stgolabs.net \
    --cc=dvhart@infradead.org \
    --cc=dvyukov@google.com \
    --cc=edumazet@google.com \
    --cc=eranian@google.com \
    --cc=german.gomez@arm.com \
    --cc=haoluo@google.com \
    --cc=irogers@google.com \
    --cc=james.clark@arm.com \
    --cc=john.garry@huawei.com \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@linux.intel.com \
    --cc=kjain@linux.ibm.com \
    --cc=leo.yan@linaro.org \
    --cc=linmq006@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=maddy@linux.ibm.com \
    --cc=mark.rutland@arm.com \
    --cc=mhiramat@kernel.org \
    --cc=mingo@redhat.com \
    --cc=nakamura.shun@fujitsu.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rickyman7@gmail.com \
    --cc=rostedt@goodmis.org \
    --cc=song@kernel.org \
    --cc=stephen.s.brennan@oracle.com \
    --cc=tglx@linutronix.de \
    --cc=tmricht@linux.ibm.com \
    --cc=yao.jin@linux.intel.com \
    --cc=yury.norov@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.