From nobody Wed Oct 8 03:52:24 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 041BE1DB346; Thu, 3 Jul 2025 01:49:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507386; cv=none; b=E8SraMek8z9lMiF7GmNYJzRCAKhcOcZO12HSI1JGRqfHbkUFbtZYKz57AVARO4EsoAbVrqAZpOW+9xwTXURspzFmnA41nmuv6H3mg7S9Xi0wRcnlkVdpau5+Am/DYETiNFm3EdcU/5GPNO090xq8h9m4Dk6z2brOf/PW2mAp0N4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751507386; c=relaxed/simple; bh=X4NV6G18FdzyzBwiRrfRrm4NvowTBnkgrW9f4n3GILw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lUVnljDoxWsRcTd6hQd6ZfbqPWyKKqX3DH0Gnwq+mCxZTFH1YD8SL6kRfU4+wBBVjIUV0bCQOeXUhodtyYmKXhFFtIL6v/0wZbCpaylSBeBevlsXOPHjszXnPd/bx4Ke2VMjGTZtPB9ZJe5G8gfATGvFMNe530slq6MxYktE3fo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fg5/IrHz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fg5/IrHz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B2964C4CEE7; Thu, 3 Jul 2025 01:49:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1751507385; bh=X4NV6G18FdzyzBwiRrfRrm4NvowTBnkgrW9f4n3GILw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fg5/IrHzbk+tlq4J5jHHqQkvqiaHNVFXD4UJP10jArnzloZASWD8Vej0H2UNLq0JC OtK1qxzKhtCFNeg1wIJMyzc7mbqUgiTEZAIOKrad+an7T1+2EwcNpnIWDwOzQu/caj GRuZe0xtxutTPs0RUB5fLlQI5Y2GfzkXYlVABfkZ+HKx2b8D7UYGU54NSGDb1e+I6a tfLGS5ZN3y2WdOz53ZmO5DKPkq9RQVBdQZfJ8pmCa6hKQEk+G1v2sWZN//U1MgPYC4 f/szS9zB5McZA7OzjyVnfR4P8JbfU1JSDk+Qecyw8gx37eAOJQt8DCzKMlKFZKbfBJ Bkz/yqhA22MUg== From: Namhyung Kim To: Arnaldo Carvalho de Melo , Ian Rogers , Kan Liang Cc: Jiri Olsa , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org Subject: [PATCH 4/8] perf sched: Fix thread leaks in 'perf sched timehist' Date: Wed, 2 Jul 2025 18:49:38 -0700 Message-ID: <20250703014942.1369397-5-namhyung@kernel.org> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog In-Reply-To: <20250703014942.1369397-1-namhyung@kernel.org> References: <20250703014942.1369397-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add missing thread__put() after machine__findnew_thread() or timehist_get_thread(). Also idle threads' last_thread should be refcounted properly. Signed-off-by: Namhyung Kim Reviewed-by: Ian Rogers --- tools/perf/builtin-sched.c | 48 +++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index b73989fb6acef8d6..83b5a85a91b7ffbd 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -2313,8 +2313,10 @@ static void save_task_callchain(struct perf_sched *s= ched, return; } =20 - if (!sched->show_callchain || sample->callchain =3D=3D NULL) + if (!sched->show_callchain || sample->callchain =3D=3D NULL) { + thread__put(thread); return; + } =20 cursor =3D get_tls_callchain_cursor(); =20 @@ -2323,10 +2325,12 @@ static void save_task_callchain(struct perf_sched *= sched, if (verbose > 0) pr_err("Failed to resolve callchain. Skipping\n"); =20 + thread__put(thread); return; } =20 callchain_cursor_commit(cursor); + thread__put(thread); =20 while (true) { struct callchain_cursor_node *node; @@ -2403,8 +2407,17 @@ static void free_idle_threads(void) return; =20 for (i =3D 0; i < idle_max_cpu; ++i) { - if ((idle_threads[i])) - thread__delete(idle_threads[i]); + struct thread *idle =3D idle_threads[i]; + + if (idle) { + struct idle_thread_runtime *itr; + + itr =3D thread__priv(idle); + if (itr) + thread__put(itr->last_thread); + + thread__delete(idle); + } } =20 free(idle_threads); @@ -2441,7 +2454,7 @@ static struct thread *get_idle_thread(int cpu) } } =20 - return idle_threads[cpu]; + return thread__get(idle_threads[cpu]); } =20 static void save_idle_callchain(struct perf_sched *sched, @@ -2496,7 +2509,8 @@ static struct thread *timehist_get_thread(struct perf= _sched *sched, if (itr =3D=3D NULL) return NULL; =20 - itr->last_thread =3D thread; + thread__put(itr->last_thread); + itr->last_thread =3D thread__get(thread); =20 /* copy task callchain when entering to idle */ if (evsel__intval(evsel, sample, "next_pid") =3D=3D 0) @@ -2567,6 +2581,7 @@ static void timehist_print_wakeup_event(struct perf_s= ched *sched, /* show wakeup unless both awakee and awaker are filtered */ if (timehist_skip_sample(sched, thread, evsel, sample) && timehist_skip_sample(sched, awakened, evsel, sample)) { + thread__put(thread); return; } =20 @@ -2583,6 +2598,8 @@ static void timehist_print_wakeup_event(struct perf_s= ched *sched, printf("awakened: %s", timehist_get_commstr(awakened)); =20 printf("\n"); + + thread__put(thread); } =20 static int timehist_sched_wakeup_ignore(const struct perf_tool *tool __may= be_unused, @@ -2611,8 +2628,10 @@ static int timehist_sched_wakeup_event(const struct = perf_tool *tool, return -1; =20 tr =3D thread__get_runtime(thread); - if (tr =3D=3D NULL) + if (tr =3D=3D NULL) { + thread__put(thread); return -1; + } =20 if (tr->ready_to_run =3D=3D 0) tr->ready_to_run =3D sample->time; @@ -2622,6 +2641,7 @@ static int timehist_sched_wakeup_event(const struct p= erf_tool *tool, !perf_time__skip_sample(&sched->ptime, sample->time)) timehist_print_wakeup_event(sched, evsel, sample, machine, thread); =20 + thread__put(thread); return 0; } =20 @@ -2649,6 +2669,7 @@ static void timehist_print_migration_event(struct per= f_sched *sched, =20 if (timehist_skip_sample(sched, thread, evsel, sample) && timehist_skip_sample(sched, migrated, evsel, sample)) { + thread__put(thread); return; } =20 @@ -2676,6 +2697,7 @@ static void timehist_print_migration_event(struct per= f_sched *sched, printf(" cpu %d =3D> %d", ocpu, dcpu); =20 printf("\n"); + thread__put(thread); } =20 static int timehist_migrate_task_event(const struct perf_tool *tool, @@ -2695,8 +2717,10 @@ static int timehist_migrate_task_event(const struct = perf_tool *tool, return -1; =20 tr =3D thread__get_runtime(thread); - if (tr =3D=3D NULL) + if (tr =3D=3D NULL) { + thread__put(thread); return -1; + } =20 tr->migrations++; tr->migrated =3D sample->time; @@ -2706,6 +2730,7 @@ static int timehist_migrate_task_event(const struct p= erf_tool *tool, timehist_print_migration_event(sched, evsel, sample, machine, thread); } + thread__put(thread); =20 return 0; } @@ -2728,10 +2753,10 @@ static void timehist_update_task_prio(struct evsel = *evsel, return; =20 tr =3D thread__get_runtime(thread); - if (tr =3D=3D NULL) - return; + if (tr !=3D NULL) + tr->prio =3D next_prio; =20 - tr->prio =3D next_prio; + thread__put(thread); } =20 static int timehist_sched_change_event(const struct perf_tool *tool, @@ -2743,7 +2768,7 @@ static int timehist_sched_change_event(const struct p= erf_tool *tool, struct perf_sched *sched =3D container_of(tool, struct perf_sched, tool); struct perf_time_interval *ptime =3D &sched->ptime; struct addr_location al; - struct thread *thread; + struct thread *thread =3D NULL; struct thread_runtime *tr =3D NULL; u64 tprev, t =3D sample->time; int rc =3D 0; @@ -2867,6 +2892,7 @@ static int timehist_sched_change_event(const struct p= erf_tool *tool, =20 evsel__save_time(evsel, sample->time, sample->cpu); =20 + thread__put(thread); addr_location__exit(&al); return rc; } --=20 2.50.0.727.gbf7dc18ff4-goog