From nobody Sun Feb 8 00:11:34 2026 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 54A5E374168 for ; Mon, 12 Jan 2026 16:52:02 +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=1768236722; cv=none; b=cAzNmXUGrsCg6DftTfe/G5ytWw8hpmZvnM1hJb25g1Cp6VLdege/fU5FRSX1wjvHxnkiyZUXI+IU4jPTYcn0l05IDzXCC6wckHLhxK+l6JLkgDEiXnMDfXcqA9y7NhTP2vskGl8yDguMKD1Lsl9Gy7CQBEG2yatX0FH/x+xOT6U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768236722; c=relaxed/simple; bh=+sHlTlx8tNtDhypDGdmJo5UgC6x9rmGgClmM2GUos28=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=Hs+spweXUH6p21dqHsvFrvQjaBg6sZ44EUMkSZ2ggMGoAeHHCj3ppg46cdgc1Sl50gg1BTIAbdcwrZcmKz02QO9+wEscw6j/qXJAampkY6UYErzu3EJmsKmQdfs8PCkwHWDwKC7VwIrcdqWnxUa9V9yZT1r+J11CqCzSd5/QZf8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GRxedk+A; 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="GRxedk+A" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E5C15C116D0; Mon, 12 Jan 2026 16:51:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1768236720; bh=+sHlTlx8tNtDhypDGdmJo5UgC6x9rmGgClmM2GUos28=; h=From:To:Cc:Subject:Date:From; b=GRxedk+ACWPJfYMChfbhZv26+DYQwWJtbw/BTf6tMu9MQEn/Fgd/xlz5RLc/I95Jr 0DdX22CaY2GeJPNpbvSWT/VtuYtvtSH38LRQAatSXAkSlRTRuowl3Mu6bckp/rSDwk XlMjqBsKXFg/yaFnKTSTYHayUo3G/x8TlrzbZ9IH7Kpv498k6+SKslzzwojRYFBVsd R6N35UPMcgZH1oTwSGCVpoJt7XJ/+jMlBI+U05TK+u9Hy0Ew2TmHggbvSrFcN2mUWn 0Jsimqf2Yc7K2gB3k6I7VKqHIeIBLTQJKcsk9vTqE7ototW5899n+/4yJHFaxM6ykM /3YeC3B/y9BFw== From: Namhyung Kim To: Peter Zijlstra , Ingo Molnar Cc: Mark Rutland , Alexander Shishkin , Arnaldo Carvalho de Melo , LKML , Rosalie Fang Subject: [PATCH] perf/core: Fix slow perf_event_task_exit() with LBR callstacks Date: Mon, 12 Jan 2026 08:51:57 -0800 Message-ID: <20260112165157.1919624-1-namhyung@kernel.org> X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog 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" I got a report that a task is stuck in perf_event_exit_task() waiting for global_ctx_data_rwsem. On large systems with lots threads, it'd have performance issues when it grabs the lock to iterate all threads in the system to allocate the context data. And it'd block task exit path which is problematic especially under memory pressure. perf_event_open perf_event_alloc attach_perf_ctx_data attach_global_ctx_data percpu_down_write (global_ctx_data_rwsem) for_each_process_thread alloc_task_ctx_data do_exit perf_event_exit_task percpu_down_read (global= _ctx_data_rwsem) It should not hold the global_ctx_data_rwsem on the exit path. Let's skip allocation for exiting tasks and free the data carefully. Reported-by: Rosalie Fang Suggested-by: Peter Zijlstra Signed-off-by: Namhyung Kim --- kernel/events/core.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 376fb07d869b8b50..e87bb43b7bb3dd4b 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5421,9 +5421,20 @@ attach_task_ctx_data(struct task_struct *task, struc= t kmem_cache *ctx_cache, return -ENOMEM; =20 for (;;) { - if (try_cmpxchg((struct perf_ctx_data **)&task->perf_ctx_data, &old, cd)= ) { + if (try_cmpxchg(&task->perf_ctx_data, &old, cd)) { if (old) perf_free_ctx_data_rcu(old); + /* + * Above try_cmpxchg() pairs with try_cmpxchg() from + * detach_task_ctx_data() such that + * if we race with perf_event_exit_task(), we must + * observe PF_EXITING. + */ + if (task->flags & PF_EXITING) { + /* detach_task_ctx_data() may free it already */ + if (try_cmpxchg(&task->perf_ctx_data, &cd, NULL)) + perf_free_ctx_data_rcu(cd); + } return 0; } =20 @@ -5469,6 +5480,8 @@ attach_global_ctx_data(struct kmem_cache *ctx_cache) /* Allocate everything */ scoped_guard (rcu) { for_each_process_thread(g, p) { + if (p->flags & PF_EXITING) + continue; cd =3D rcu_dereference(p->perf_ctx_data); if (cd && !cd->global) { cd->global =3D 1; @@ -14562,8 +14575,11 @@ void perf_event_exit_task(struct task_struct *task) =20 /* * Detach the perf_ctx_data for the system-wide event. + * + * Done without holding global_ctx_data_rwsem; typically + * attach_global_ctx_data() will skip over this task, but otherwise + * attach_task_ctx_data() will observe PF_EXITING. */ - guard(percpu_read)(&global_ctx_data_rwsem); detach_task_ctx_data(task); } =20 --=20 2.52.0.457.g6b5491de43-goog