[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251021144751.GQ3245006@noisy.programming.kicks-ass.net>
Date: Tue, 21 Oct 2025 16:47:51 +0200
From: Peter Zijlstra <peterz@...radead.org>
To: Dapeng Mi <dapeng1.mi@...ux.intel.com>
Cc: Ingo Molnar <mingo@...hat.com>,
Arnaldo Carvalho de Melo <acme@...nel.org>,
Namhyung Kim <namhyung@...nel.org>, Ian Rogers <irogers@...gle.com>,
Adrian Hunter <adrian.hunter@...el.com>,
Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
Andi Kleen <ak@...ux.intel.com>,
Eranian Stephane <eranian@...gle.com>, linux-kernel@...r.kernel.org,
linux-perf-users@...r.kernel.org, Dapeng Mi <dapeng1.mi@...el.com>,
Octavia Togami <octavia.togami@...il.com>
Subject: Re: [PATCH] perf: Fix system hang caused by cpu-clock
On Wed, Oct 15, 2025 at 01:18:28PM +0800, Dapeng Mi wrote:
> A system hang issue caused by cpu-clock is reported and bisection
> indicates the commit 18dbcbfabfff ("perf: Fix the POLL_HUP delivery
> breakage") causes this issue.
>
> The root cause of the hang issue is that cpu-clock is a specific SW
> event which relies on the hrtimer. The __perf_event_overflow()
> is invoked from the hrtimer handler for cpu-clock event, and
> __perf_event_overflow() tries to call event stop callback
> (cpu_clock_event_stop()) to stop the event, and cpu_clock_event_stop()
> calls htimer_cancel() to cancel the hrtimer. But unfortunately the
> hrtimer callback is currently executing and then traps into deadlock.
>
> To avoid this deadlock, use hrtimer_try_to_cancel() instead of
> hrtimer_cancel() to cancel the hrtimer, and set PERF_HES_STOPPED flag
> for the stopping events. perf_swevent_hrtimer() would stop the event
> hrtimer once it detects the PERF_HES_STOPPED flag.
>
> Reported-by: Octavia Togami <octavia.togami@...il.com>
> Closes: https://lore.kernel.org/all/CAHPNGSQpXEopYreir+uDDEbtXTBvBvi8c6fYXJvceqtgTPao3Q@mail.gmail.com/
> Suggested-by: Peter Zijlstra <peterz@...radead.org>
> Fixes: 18dbcbfabfff ("perf: Fix the POLL_HUP delivery breakage")
> Tested-by: Octavia Togami <octavia.togami@...il.com>
> Signed-off-by: Dapeng Mi <dapeng1.mi@...ux.intel.com>
> ---
> kernel/events/core.c | 18 +++++++++++++-----
> 1 file changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 7541f6f85fcb..f90105d5f26a 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -11773,7 +11773,8 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
>
> event = container_of(hrtimer, struct perf_event, hw.hrtimer);
>
> - if (event->state != PERF_EVENT_STATE_ACTIVE)
> + if (event->state != PERF_EVENT_STATE_ACTIVE ||
> + event->hw.state & PERF_HES_STOPPED)
> return HRTIMER_NORESTART;
>
> event->pmu->read(event);
I was wondering if we need a HES_STOPPED check after calling
__perf_event_overflow(), but typically that will return 1 when it does
the stop itself, which then already does NORESTART.
So yeah, I suppose this works. Let me go queue this up.
Thanks!
Powered by blists - more mailing lists