LKML Archive mirror
 help / color / mirror / Atom feed
From: Ian Rogers <irogers@google.com>
To: John Garry <john.g.garry@oracle.com>,
	Will Deacon <will@kernel.org>, James Clark <james.clark@arm.com>,
	Mike Leach <mike.leach@linaro.org>, Leo Yan <leo.yan@linaro.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>, Namhyung Kim <namhyung@kernel.org>,
	Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	"Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com>,
	Kan Liang <kan.liang@linux.intel.com>,
	German Gomez <german.gomez@arm.com>,
	Ali Saidi <alisaidi@amazon.com>,
	Jing Zhang <renyu.zj@linux.alibaba.com>,
	Athira Rajeev <atrajeev@linux.vnet.ibm.com>,
	Miguel Ojeda <ojeda@kernel.org>,
	ye xingchen <ye.xingchen@zte.com.cn>,
	Liam Howlett <liam.howlett@oracle.com>,
	Dmitrii Dolgov <9erthalion6@gmail.com>,
	Yang Jihong <yangjihong1@huawei.com>,
	K Prateek Nayak <kprateek.nayak@amd.com>,
	Changbin Du <changbin.du@huawei.com>,
	Ravi Bangoria <ravi.bangoria@amd.com>,
	Sean Christopherson <seanjc@google.com>,
	Andi Kleen <ak@linux.intel.com>,
	"Steinar H. Gunderson" <sesse@google.com>,
	Yuan Can <yuancan@huawei.com>,
	Brian Robbins <brianrob@linux.microsoft.com>,
	liuwenyu <liuwenyu7@huawei.com>,
	Ivan Babrou <ivan@cloudflare.com>,
	Fangrui Song <maskray@google.com>,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-perf-users@vger.kernel.org, coresight@lists.linaro.org
Subject: [PATCH v2 01/26] perf thread: Remove notion of dead threads
Date: Thu,  8 Jun 2023 16:27:58 -0700	[thread overview]
Message-ID: <20230608232823.4027869-2-irogers@google.com> (raw)
In-Reply-To: <20230608232823.4027869-1-irogers@google.com>

The dead thread list is best effort. Threads live on it until the
reference count hits zero and they are removed. With correct reference
counting this should never happen. It is, however, part of the 'perf
sched' output that is now removed. If this is an issue we should
implement tracking of dead threads in a robust not best-effort way.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/builtin-sched.c | 23 +----------------------
 tools/perf/util/cs-etm.c   |  6 ------
 tools/perf/util/intel-pt.c |  8 --------
 tools/perf/util/machine.c  | 32 +-------------------------------
 tools/perf/util/thread.c   | 25 +------------------------
 tools/perf/util/thread.h   | 11 +----------
 6 files changed, 4 insertions(+), 101 deletions(-)

diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index cc4ba506e119..3a30c2ac5b47 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -2760,7 +2760,7 @@ struct total_run_stats {
 	u64  total_run_time;
 };
 
-static int __show_thread_runtime(struct thread *t, void *priv)
+static int show_thread_runtime(struct thread *t, void *priv)
 {
 	struct total_run_stats *stats = priv;
 	struct thread_runtime *r;
@@ -2783,22 +2783,6 @@ static int __show_thread_runtime(struct thread *t, void *priv)
 	return 0;
 }
 
-static int show_thread_runtime(struct thread *t, void *priv)
-{
-	if (t->dead)
-		return 0;
-
-	return __show_thread_runtime(t, priv);
-}
-
-static int show_deadthread_runtime(struct thread *t, void *priv)
-{
-	if (!t->dead)
-		return 0;
-
-	return __show_thread_runtime(t, priv);
-}
-
 static size_t callchain__fprintf_folded(FILE *fp, struct callchain_node *node)
 {
 	const char *sep = " <- ";
@@ -2890,11 +2874,6 @@ static void timehist_print_summary(struct perf_sched *sched,
 	if (!task_count)
 		printf("<no still running tasks>\n");
 
-	printf("\nTerminated tasks:\n");
-	machine__for_each_thread(m, show_deadthread_runtime, &totals);
-	if (task_count == totals.task_count)
-		printf("<no terminated tasks>\n");
-
 	/* CPU idle stats not tracked when samples were skipped */
 	if (sched->skipped_samples && !sched->idle_hist)
 		return;
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 91299cc56bf7..0f5be4ad24ba 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -3292,12 +3292,6 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event,
 		goto err_free_queues;
 	}
 
-	/*
-	 * Initialize list node so that at thread__zput() we can avoid
-	 * segmentation fault at list_del_init().
-	 */
-	INIT_LIST_HEAD(&etm->unknown_thread->node);
-
 	err = thread__set_comm(etm->unknown_thread, "unknown", 0);
 	if (err)
 		goto err_delete_thread;
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index fe893c9bab3f..dde2ca77a005 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -4311,14 +4311,6 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 		goto err_free_queues;
 	}
 
-	/*
-	 * Since this thread will not be kept in any rbtree not in a
-	 * list, initialize its list node so that at thread__put() the
-	 * current thread lifetime assumption is kept and we don't segfault
-	 * at list_del_init().
-	 */
-	INIT_LIST_HEAD(&pt->unknown_thread->node);
-
 	err = thread__set_comm(pt->unknown_thread, "unknown", 0);
 	if (err)
 		goto err_delete_thread;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 9e02e19c1b7a..a1954ac85f59 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -241,17 +241,6 @@ void machine__exit(struct machine *machine)
 
 	for (i = 0; i < THREADS__TABLE_SIZE; i++) {
 		struct threads *threads = &machine->threads[i];
-		struct thread *thread, *n;
-		/*
-		 * Forget about the dead, at this point whatever threads were
-		 * left in the dead lists better have a reference count taken
-		 * by who is using them, and then, when they drop those references
-		 * and it finally hits zero, thread__put() will check and see that
-		 * its not in the dead threads list and will not try to remove it
-		 * from there, just calling thread__delete() straight away.
-		 */
-		list_for_each_entry_safe(thread, n, &threads->dead, node)
-			list_del_init(&thread->node);
 
 		exit_rwsem(&threads->lock);
 	}
@@ -2046,18 +2035,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,
 	rb_erase_cached(&th->rb_node, &threads->entries);
 	RB_CLEAR_NODE(&th->rb_node);
 	--threads->nr;
-	/*
-	 * Move it first to the dead_threads list, then drop the reference,
-	 * if this is the last reference, then the thread__delete destructor
-	 * will be called and we will remove it from the dead_threads list.
-	 */
-	list_add_tail(&th->node, &threads->dead);
 
-	/*
-	 * We need to do the put here because if this is the last refcount,
-	 * then we will be touching the threads->dead head when removing the
-	 * thread.
-	 */
 	thread__put(th);
 
 	if (lock)
@@ -2145,10 +2123,8 @@ int machine__process_exit_event(struct machine *machine, union perf_event *event
 	if (dump_trace)
 		perf_event__fprintf_task(event, stdout);
 
-	if (thread != NULL) {
-		thread__exited(thread);
+	if (thread != NULL)
 		thread__put(thread);
-	}
 
 	return 0;
 }
@@ -3204,12 +3180,6 @@ int machine__for_each_thread(struct machine *machine,
 			if (rc != 0)
 				return rc;
 		}
-
-		list_for_each_entry(thread, &threads->dead, node) {
-			rc = fn(thread, priv);
-			if (rc != 0)
-				return rc;
-		}
 	}
 	return rc;
 }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 4b5bdc277baa..d949bffc0ed6 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -125,31 +125,8 @@ struct thread *thread__get(struct thread *thread)
 
 void thread__put(struct thread *thread)
 {
-	if (thread && refcount_dec_and_test(&thread->refcnt)) {
-		/*
-		 * Remove it from the dead threads list, as last reference is
-		 * gone, if it is in a dead threads list.
-		 *
-		 * We may not be there anymore if say, the machine where it was
-		 * stored was already deleted, so we already removed it from
-		 * the dead threads and some other piece of code still keeps a
-		 * reference.
-		 *
-		 * This is what 'perf sched' does and finally drops it in
-		 * perf_sched__lat(), where it calls perf_sched__read_events(),
-		 * that processes the events by creating a session and deleting
-		 * it, which ends up destroying the list heads for the dead
-		 * threads, but before it does that it removes all threads from
-		 * it using list_del_init().
-		 *
-		 * So we need to check here if it is in a dead threads list and
-		 * if so, remove it before finally deleting the thread, to avoid
-		 * an use after free situation.
-		 */
-		if (!list_empty(&thread->node))
-			list_del_init(&thread->node);
+	if (thread && refcount_dec_and_test(&thread->refcnt))
 		thread__delete(thread);
-	}
 }
 
 static struct namespaces *__thread__namespaces(const struct thread *thread)
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 395c626699a9..86737812e06b 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -30,10 +30,7 @@ struct lbr_stitch {
 };
 
 struct thread {
-	union {
-		struct rb_node	 rb_node;
-		struct list_head node;
-	};
+	struct rb_node		rb_node;
 	struct maps		*maps;
 	pid_t			pid_; /* Not all tools update this */
 	pid_t			tid;
@@ -43,7 +40,6 @@ struct thread {
 	refcount_t		refcnt;
 	bool			comm_set;
 	int			comm_len;
-	bool			dead; /* if set thread has exited */
 	struct list_head	namespaces_list;
 	struct rw_semaphore	namespaces_lock;
 	struct list_head	comm_list;
@@ -81,11 +77,6 @@ static inline void __thread__zput(struct thread **thread)
 
 #define thread__zput(thread) __thread__zput(&thread)
 
-static inline void thread__exited(struct thread *thread)
-{
-	thread->dead = true;
-}
-
 struct namespaces *thread__namespaces(struct thread *thread);
 int thread__set_namespaces(struct thread *thread, u64 timestamp,
 			   struct perf_record_namespaces *event);
-- 
2.41.0.162.gfafddb0af9-goog


  reply	other threads:[~2023-06-08 23:29 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-08 23:27 [PATCH v2 00/26] Fix memory leaks (was reference count checking for thread) Ian Rogers
2023-06-08 23:27 ` Ian Rogers [this message]
2023-06-08 23:27 ` [PATCH v2 02/26] perf thread: Make threads rbtree non-invasive Ian Rogers
2023-06-09 14:13   ` Arnaldo Carvalho de Melo
2023-06-08 23:28 ` [PATCH v2 03/26] perf thread: Add accessor functions for thread Ian Rogers
2023-06-09 14:15   ` Arnaldo Carvalho de Melo
2023-06-09 14:50   ` Arnaldo Carvalho de Melo
2023-06-08 23:28 ` [PATCH v2 04/26] perf maps: Make delete static, always use put Ian Rogers
2023-06-09 14:17   ` Arnaldo Carvalho de Melo
2023-06-08 23:28 ` [PATCH v2 05/26] perf addr_location: Move to its own header Ian Rogers
2023-06-09 14:18   ` Arnaldo Carvalho de Melo
2023-06-08 23:28 ` [PATCH v2 06/26] perf addr_location: Add init/exit/copy functions Ian Rogers
2023-06-09 19:48   ` Arnaldo Carvalho de Melo
2023-06-08 23:28 ` [PATCH v2 07/26] perf thread: Add reference count checking Ian Rogers
2023-06-08 23:28 ` [PATCH v2 08/26] perf machine: Make delete_threads part of machine__exit Ian Rogers
2023-06-08 23:28 ` [PATCH v2 09/26] perf report: Avoid thread leak Ian Rogers
2023-06-08 23:28 ` [PATCH v2 10/26] perf header: Ensure bitmaps are freed Ian Rogers
2023-06-08 23:28 ` [PATCH v2 11/26] perf stat: Avoid evlist leak Ian Rogers
2023-06-08 23:28 ` [PATCH v2 12/26] perf intel-pt: Fix missed put and leak Ian Rogers
2023-06-08 23:28 ` [PATCH v2 13/26] perf evlist: Free stats in all evlist destruction Ian Rogers
2023-06-08 23:28 ` [PATCH v2 14/26] perf python: Avoid 2 leak sanitizer issues Ian Rogers
2023-06-08 23:28 ` [PATCH v2 15/26] perf jit: Fix two thread leaks Ian Rogers
2023-06-08 23:28 ` [PATCH v2 16/26] perf symbol-elf: Correct holding a reference Ian Rogers
2023-06-08 23:28 ` [PATCH v2 17/26] perf maps: Fix overlapping memory leak Ian Rogers
2023-06-08 23:28 ` [PATCH v2 18/26] perf machine: Fix leak of kernel dso Ian Rogers
2023-06-08 23:28 ` [PATCH v2 19/26] perf machine: Don't leak module maps Ian Rogers
2023-06-08 23:28 ` [PATCH v2 20/26] perf map/maps/thread: Changes to reference counting Ian Rogers
2023-06-08 23:28 ` [PATCH v2 21/26] perf annotate: Fix parse_objdump_line memory leak Ian Rogers
2023-06-08 23:28 ` [PATCH v2 22/26] perf top: Add exit routine for main thread Ian Rogers
2023-06-08 23:28 ` [PATCH v2 23/26] perf header: Avoid out-of-bounds read Ian Rogers
2023-06-08 23:28 ` [PATCH v2 24/26] perf callchain: Use pthread keys for tls callchain_cursor Ian Rogers
2023-06-09 19:49   ` Arnaldo Carvalho de Melo
2023-06-08 23:28 ` [PATCH v2 25/26] perf srcline: Change free_srcline to zfree_srcline Ian Rogers
2023-06-08 23:28 ` [PATCH v2 26/26] perf hist: Fix srcline memory leak Ian Rogers
2023-06-12 14:13   ` Arnaldo Carvalho de Melo
2023-06-12 14:16     ` Arnaldo Carvalho de Melo
2023-06-12 14:46       ` Ian Rogers
2023-06-12 17:23         ` Arnaldo Carvalho de Melo
2023-06-12 21:16           ` Andi Kleen
2023-06-12 21:30             ` Arnaldo Carvalho de Melo

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=20230608232823.4027869-2-irogers@google.com \
    --to=irogers@google.com \
    --cc=9erthalion6@gmail.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=ak@linux.intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=alisaidi@amazon.com \
    --cc=atrajeev@linux.vnet.ibm.com \
    --cc=brianrob@linux.microsoft.com \
    --cc=changbin.du@huawei.com \
    --cc=coresight@lists.linaro.org \
    --cc=german.gomez@arm.com \
    --cc=ivan@cloudflare.com \
    --cc=james.clark@arm.com \
    --cc=john.g.garry@oracle.com \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@linux.intel.com \
    --cc=kprateek.nayak@amd.com \
    --cc=leo.yan@linaro.org \
    --cc=liam.howlett@oracle.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=liuwenyu7@huawei.com \
    --cc=mark.rutland@arm.com \
    --cc=maskray@google.com \
    --cc=mike.leach@linaro.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=naveen.n.rao@linux.vnet.ibm.com \
    --cc=ojeda@kernel.org \
    --cc=peterz@infradead.org \
    --cc=ravi.bangoria@amd.com \
    --cc=renyu.zj@linux.alibaba.com \
    --cc=seanjc@google.com \
    --cc=sesse@google.com \
    --cc=suzuki.poulose@arm.com \
    --cc=will@kernel.org \
    --cc=yangjihong1@huawei.com \
    --cc=ye.xingchen@zte.com.cn \
    --cc=yuancan@huawei.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).