Skip to content

Commit f4b07fd

Browse files
namhyungIngo Molnar
authored andcommitted
perf/core: Use POLLHUP for pinned events in error
Pinned performance events can enter an error state when they fail to be scheduled in the context due to a failed constraint or some other conflict or condition. In error state these events won't generate any samples anymore and are silently ignored until they are recovered by PERF_EVENT_IOC_ENABLE, or the condition can also change so that they can be scheduled in. Tooling should be allowed to know about the state change, but currently there's no mechanism to notify tooling when events enter an error state. One way to do this is to issue a POLLHUP event to poll(2) to handle this. Reading events in an error state would return 0 (EOF) and it matches to the behavior of POLLHUP according to the man page. Tooling should remove the fd of the event from pollfd after getting POLLHUP, otherwise it'll be returned repeatedly. [ mingo: Clarified the changelog ] Signed-off-by: Namhyung Kim <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Arnaldo Carvalho de Melo <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Linus Torvalds <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent b6ecb57 commit f4b07fd

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

kernel/events/core.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3984,6 +3984,11 @@ static int merge_sched_in(struct perf_event *event, void *data)
39843984
if (event->attr.pinned) {
39853985
perf_cgroup_event_disable(event, ctx);
39863986
perf_event_set_state(event, PERF_EVENT_STATE_ERROR);
3987+
3988+
if (*perf_event_fasync(event))
3989+
event->pending_kill = POLL_HUP;
3990+
3991+
perf_event_wakeup(event);
39873992
} else {
39883993
struct perf_cpu_pmu_context *cpc = this_cpc(event->pmu_ctx->pmu);
39893994

@@ -5925,6 +5930,10 @@ static __poll_t perf_poll(struct file *file, poll_table *wait)
59255930
if (is_event_hup(event))
59265931
return events;
59275932

5933+
if (unlikely(READ_ONCE(event->state) == PERF_EVENT_STATE_ERROR &&
5934+
event->attr.pinned))
5935+
return events;
5936+
59285937
/*
59295938
* Pin the event->rb by taking event->mmap_mutex; otherwise
59305939
* perf_event_set_output() can swizzle our rb and make us miss wakeups.

0 commit comments

Comments
 (0)