Skip to content

Commit

Permalink
Merge tag 'perf-urgent-2025-04-06' of git://git.kernel.org/pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/kernel/git/tip/tip

Pull perf event fix from Ingo Molnar:
 "Fix a perf events time accounting bug"

* tag 'perf-urgent-2025-04-06' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/core: Fix child_total_time_enabled accounting bug at task exit
  • Loading branch information
Linus Torvalds committed Apr 6, 2025
2 parents 302deb1 + a3c3c66 commit dda8887
Showing 1 changed file with 9 additions and 9 deletions.
18 changes: 9 additions & 9 deletions kernel/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2451,6 +2451,7 @@ ctx_time_update_event(struct perf_event_context *ctx, struct perf_event *event)
#define DETACH_GROUP 0x01UL
#define DETACH_CHILD 0x02UL
#define DETACH_DEAD 0x04UL
#define DETACH_EXIT 0x08UL

/*
* Cross CPU call to remove a performance event
Expand All @@ -2465,6 +2466,7 @@ __perf_remove_from_context(struct perf_event *event,
void *info)
{
struct perf_event_pmu_context *pmu_ctx = event->pmu_ctx;
enum perf_event_state state = PERF_EVENT_STATE_OFF;
unsigned long flags = (unsigned long)info;

ctx_time_update(cpuctx, ctx);
Expand All @@ -2473,16 +2475,19 @@ __perf_remove_from_context(struct perf_event *event,
* Ensure event_sched_out() switches to OFF, at the very least
* this avoids raising perf_pending_task() at this time.
*/
if (flags & DETACH_DEAD)
if (flags & DETACH_EXIT)
state = PERF_EVENT_STATE_EXIT;
if (flags & DETACH_DEAD) {
event->pending_disable = 1;
state = PERF_EVENT_STATE_DEAD;
}
event_sched_out(event, ctx);
perf_event_set_state(event, min(event->state, state));
if (flags & DETACH_GROUP)
perf_group_detach(event);
if (flags & DETACH_CHILD)
perf_child_detach(event);
list_del_event(event, ctx);
if (flags & DETACH_DEAD)
event->state = PERF_EVENT_STATE_DEAD;

if (!pmu_ctx->nr_events) {
pmu_ctx->rotate_necessary = 0;
Expand Down Expand Up @@ -13731,12 +13736,7 @@ perf_event_exit_event(struct perf_event *event, struct perf_event_context *ctx)
mutex_lock(&parent_event->child_mutex);
}

perf_remove_from_context(event, detach_flags);

raw_spin_lock_irq(&ctx->lock);
if (event->state > PERF_EVENT_STATE_EXIT)
perf_event_set_state(event, PERF_EVENT_STATE_EXIT);
raw_spin_unlock_irq(&ctx->lock);
perf_remove_from_context(event, detach_flags | DETACH_EXIT);

/*
* Child events can be freed.
Expand Down

0 comments on commit dda8887

Please sign in to comment.