Commit 7ee227f6 authored by Ian Rogers's avatar Ian Rogers Committed by Arnaldo Carvalho de Melo
Browse files

perf thread: Make threads rbtree non-invasive



Separate the rbtree out of thread and into a new struct
thread_rb_node. The refcnt is in thread and the rbtree is responsible
for a single count.

Signed-off-by: default avatarIan Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ali Saidi <alisaidi@amazon.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Brian Robbins <brianrob@linux.microsoft.com>
Cc: Changbin Du <changbin.du@huawei.com>
Cc: Dmitrii Dolgov <9erthalion6@gmail.com>
Cc: Fangrui Song <maskray@google.com>
Cc: German Gomez <german.gomez@arm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Ivan Babrou <ivan@cloudflare.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: K Prateek Nayak <kprateek.nayak@amd.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Steinar H. Gunderson <sesse@google.com>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Wenyu Liu <liuwenyu7@huawei.com>
Cc: Will Deacon <will@kernel.org>
Cc: Yang Jihong <yangjihong1@huawei.com>
Cc: Ye Xingchen <ye.xingchen@zte.com.cn>
Cc: Yuan Can <yuancan@huawei.com>
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/20230608232823.4027869-3-irogers@google.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 40826c45
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -911,7 +911,7 @@ static int tasks_print(struct report *rep, FILE *fp)
		     nd = rb_next(nd)) {
			task = tasks + itask++;

			task->thread = rb_entry(nd, struct thread, rb_node);
			task->thread = rb_entry(nd, struct thread_rb_node, rb_node)->thread;
			INIT_LIST_HEAD(&task->children);
			INIT_LIST_HEAD(&task->list);
			thread__set_priv(task->thread, task);
+1 −1
Original line number Diff line number Diff line
@@ -4348,7 +4348,7 @@ DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_event
	struct thread *thread;
)
{
	entry->thread = rb_entry(nd, struct thread, rb_node);
	entry->thread = rb_entry(nd, struct thread_rb_node, rb_node)->thread;
}

static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
+66 −35
Original line number Diff line number Diff line
@@ -43,7 +43,8 @@
#include <linux/string.h>
#include <linux/zalloc.h>

static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
static void __machine__remove_thread(struct machine *machine, struct thread_rb_node *nd,
				     struct thread *th, bool lock);
static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms, u64 ip);

static struct dso *machine__kernel_dso(struct machine *machine)
@@ -72,6 +73,21 @@ static void machine__threads_init(struct machine *machine)
	}
}

static int thread_rb_node__cmp_tid(const void *key, const struct rb_node *nd)
{
	int to_find = (int) *((pid_t *)key);

	return to_find - (int)rb_entry(nd, struct thread_rb_node, rb_node)->thread->tid;
}

static struct thread_rb_node *thread_rb_node__find(const struct thread *th,
						   struct rb_root *tree)
{
	struct rb_node *nd = rb_find(&th->tid, tree, thread_rb_node__cmp_tid);

	return rb_entry(nd, struct thread_rb_node, rb_node);
}

static int machine__set_mmap_name(struct machine *machine)
{
	if (machine__is_host(machine))
@@ -214,10 +230,10 @@ void machine__delete_threads(struct machine *machine)
		down_write(&threads->lock);
		nd = rb_first_cached(&threads->entries);
		while (nd) {
			struct thread *t = rb_entry(nd, struct thread, rb_node);
			struct thread_rb_node *trb = rb_entry(nd, struct thread_rb_node, rb_node);

			nd = rb_next(nd);
			__machine__remove_thread(machine, t, false);
			__machine__remove_thread(machine, trb, trb->thread, false);
		}
		up_write(&threads->lock);
	}
@@ -605,6 +621,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
	struct rb_node **p = &threads->entries.rb_root.rb_node;
	struct rb_node *parent = NULL;
	struct thread *th;
	struct thread_rb_node *nd;
	bool leftmost = true;

	th = threads__get_last_match(threads, machine, pid, tid);
@@ -613,7 +630,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,

	while (*p != NULL) {
		parent = *p;
		th = rb_entry(parent, struct thread, rb_node);
		th = rb_entry(parent, struct thread_rb_node, rb_node)->thread;

		if (th->tid == tid) {
			threads__set_last_match(threads, th);
@@ -633,20 +650,30 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
		return NULL;

	th = thread__new(pid, tid);
	if (th != NULL) {
		rb_link_node(&th->rb_node, parent, p);
		rb_insert_color_cached(&th->rb_node, &threads->entries, leftmost);
	if (th == NULL)
		return NULL;

	nd = malloc(sizeof(*nd));
	if (nd == NULL) {
		thread__put(th);
		return NULL;
	}
	nd->thread = th;

	rb_link_node(&nd->rb_node, parent, p);
	rb_insert_color_cached(&nd->rb_node, &threads->entries, leftmost);

	/*
	 * We have to initialize maps separately after rb tree is updated.
	 *
		 * The reason is that we call machine__findnew_thread
		 * within thread__init_maps to find the thread
		 * leader and that would screwed the rb tree.
	 * The reason is that we call machine__findnew_thread within
	 * thread__init_maps to find the thread leader and that would screwed
	 * the rb tree.
	 */
	if (thread__init_maps(th, machine)) {
			rb_erase_cached(&th->rb_node, &threads->entries);
			RB_CLEAR_NODE(&th->rb_node);
		rb_erase_cached(&nd->rb_node, &threads->entries);
		RB_CLEAR_NODE(&nd->rb_node);
		free(nd);
		thread__put(th);
		return NULL;
	}
@@ -656,7 +683,6 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
	thread__get(th);
	threads__set_last_match(threads, th);
	++threads->nr;
	}

	return th;
}
@@ -1109,7 +1135,7 @@ size_t machine__fprintf(struct machine *machine, FILE *fp)

		for (nd = rb_first_cached(&threads->entries); nd;
		     nd = rb_next(nd)) {
			struct thread *pos = rb_entry(nd, struct thread, rb_node);
			struct thread *pos = rb_entry(nd, struct thread_rb_node, rb_node)->thread;

			ret += thread__fprintf(pos, fp);
		}
@@ -2020,10 +2046,14 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
	return 0;
}

static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock)
static void __machine__remove_thread(struct machine *machine, struct thread_rb_node *nd,
				     struct thread *th, bool lock)
{
	struct threads *threads = machine__threads(machine, th->tid);

	if (!nd)
		nd = thread_rb_node__find(th, &threads->entries.rb_root);

	if (threads->last_match == th)
		threads__set_last_match(threads, NULL);

@@ -2032,11 +2062,12 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,

	BUG_ON(refcount_read(&th->refcnt) == 0);

	rb_erase_cached(&th->rb_node, &threads->entries);
	RB_CLEAR_NODE(&th->rb_node);
	thread__put(nd->thread);
	rb_erase_cached(&nd->rb_node, &threads->entries);
	RB_CLEAR_NODE(&nd->rb_node);
	--threads->nr;

	thread__put(th);
	free(nd);

	if (lock)
		up_write(&threads->lock);
@@ -2044,7 +2075,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,

void machine__remove_thread(struct machine *machine, struct thread *th)
{
	return __machine__remove_thread(machine, th, true);
	return __machine__remove_thread(machine, NULL, th, true);
}

int machine__process_fork_event(struct machine *machine, union perf_event *event,
@@ -3167,7 +3198,6 @@ int machine__for_each_thread(struct machine *machine,
{
	struct threads *threads;
	struct rb_node *nd;
	struct thread *thread;
	int rc = 0;
	int i;

@@ -3175,8 +3205,9 @@ int machine__for_each_thread(struct machine *machine,
		threads = &machine->threads[i];
		for (nd = rb_first_cached(&threads->entries); nd;
		     nd = rb_next(nd)) {
			thread = rb_entry(nd, struct thread, rb_node);
			rc = fn(thread, priv);
			struct thread_rb_node *trb = rb_entry(nd, struct thread_rb_node, rb_node);

			rc = fn(trb->thread, priv);
			if (rc != 0)
				return rc;
		}
+0 −3
Original line number Diff line number Diff line
@@ -66,7 +66,6 @@ struct thread *thread__new(pid_t pid, pid_t tid)

		list_add(&comm->list, &thread->comm_list);
		refcount_set(&thread->refcnt, 1);
		RB_CLEAR_NODE(&thread->rb_node);
		/* Thread holds first ref to nsdata. */
		thread->nsinfo = nsinfo__new(pid);
		srccode_state_init(&thread->srccode_state);
@@ -84,8 +83,6 @@ void thread__delete(struct thread *thread)
	struct namespaces *namespaces, *tmp_namespaces;
	struct comm *comm, *tmp_comm;

	BUG_ON(!RB_EMPTY_NODE(&thread->rb_node));

	thread_stack__free(thread);

	if (thread->maps) {
+5 −1
Original line number Diff line number Diff line
@@ -29,8 +29,12 @@ struct lbr_stitch {
	struct callchain_cursor_node	*prev_lbr_cursor;
};

struct thread {
struct thread_rb_node {
	struct rb_node rb_node;
	struct thread *thread;
};

struct thread {
	struct maps		*maps;
	pid_t			pid_; /* Not all tools update this */
	pid_t			tid;