Re: [BUG] PREEMPT_RT: sleeping function called from invalid context in perf_event_wakeup()
From: Peter Zijlstra
Date: Thu Feb 05 2026 - 06:09:08 EST
On Thu, Feb 05, 2026 at 06:42:05PM +0800, Zw Tang wrote:
> Hi,
>
> I am reporting a PREEMPT_RT “sleeping function called from invalid
> context” bug triggered by a syzkaller reproducer on Linux 6.19.0-rc7.
>
> The kernel reports:
>
> BUG: sleeping function called from invalid context at
> kernel/locking/spinlock_rt.c:48
> in_atomic(): 1, irqs_disabled(): 1, preempt_count: 4
>
> The splat points to perf’s wakeup path taking an RT spinlock while
> running in an atomic/IRQs-disabled context:
>
> merge_sched_in()
> -> perf_event_wakeup()
> -> __wake_up_common_lock()
> -> rt_spin_lock()
> -> __might_resched() (complains about sleeping in invalid context)
>
> This suggests a locking semantic mismatch on PREEMPT_RT:
> perf_event_wakeup() (via __wake_up_common_lock()) ends up taking a
> lock that maps to rt_spin_lock(), which may sleep on RT kernels, but
> the current context is explicitly atomic with IRQs disabled.
Fixes: f4b07fd62d4d ("perf/core: Use POLLHUP for pinned events in error")
diff --git a/kernel/events/core.c b/kernel/events/core.c
index dad0d3d2e85f..216cf6ae1c7d 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4017,7 +4017,8 @@ static int merge_sched_in(struct perf_event *event, void *data)
if (*perf_event_fasync(event))
event->pending_kill = POLL_ERR;
- perf_event_wakeup(event);
+ event->pending_wakeup = 1;
+ irq_work_queue(&event->pending_irq);
} else {
struct perf_cpu_pmu_context *cpc = this_cpc(event->pmu_ctx->pmu);