[tip: perf/core] perf: Simplify perf_event_free_task() wait
From: tip-bot2 for Peter Zijlstra
Date: Tue Apr 08 2025 - 15:07:48 EST
The following commit has been merged into the perf/core branch of tip:
Commit-ID: 59f3aa4a3ee27e96132e16d2d2bdc3acadb4bf79
Gitweb: https://git.kernel.org/tip/59f3aa4a3ee27e96132e16d2d2bdc3acadb4bf79
Author: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
AuthorDate: Fri, 17 Jan 2025 15:27:07 +01:00
Committer: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
CommitterDate: Tue, 08 Apr 2025 20:55:46 +02:00
perf: Simplify perf_event_free_task() wait
Simplify the code by moving the duplicated wakeup condition into
put_ctx().
Notably, wait_var_event() is in perf_event_free_task() and will have
set ctx->task = TASK_TOMBSTONE.
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Reviewed-by: Ravi Bangoria <ravi.bangoria@xxxxxxx>
Link: https://lkml.kernel.org/r/20250307193723.044499344@xxxxxxxxxxxxx
---
kernel/events/core.c | 25 +++----------------------
1 file changed, 3 insertions(+), 22 deletions(-)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 3c92b75..fa6dab0 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1270,6 +1270,9 @@ static void put_ctx(struct perf_event_context *ctx)
if (ctx->task && ctx->task != TASK_TOMBSTONE)
put_task_struct(ctx->task);
call_rcu(&ctx->rcu_head, free_ctx);
+ } else if (ctx->task == TASK_TOMBSTONE) {
+ smp_mb(); /* pairs with wait_var_event() */
+ wake_up_var(&ctx->refcount);
}
}
@@ -5729,8 +5732,6 @@ int perf_event_release_kernel(struct perf_event *event)
again:
mutex_lock(&event->child_mutex);
list_for_each_entry(child, &event->child_list, child_list) {
- void *var = NULL;
-
/*
* Cannot change, child events are not migrated, see the
* comment with perf_event_ctx_lock_nested().
@@ -5765,40 +5766,20 @@ again:
if (tmp == child) {
perf_remove_from_context(child, DETACH_GROUP | DETACH_CHILD);
list_add(&child->child_list, &free_list);
- } else {
- var = &ctx->refcount;
}
mutex_unlock(&event->child_mutex);
mutex_unlock(&ctx->mutex);
put_ctx(ctx);
- if (var) {
- /*
- * If perf_event_free_task() has deleted all events from the
- * ctx while the child_mutex got released above, make sure to
- * notify about the preceding put_ctx().
- */
- smp_mb(); /* pairs with wait_var_event() */
- wake_up_var(var);
- }
goto again;
}
mutex_unlock(&event->child_mutex);
list_for_each_entry_safe(child, tmp, &free_list, child_list) {
- void *var = &child->ctx->refcount;
-
list_del(&child->child_list);
/* Last reference unless ->pending_task work is pending */
put_event(child);
-
- /*
- * Wake any perf_event_free_task() waiting for this event to be
- * freed.
- */
- smp_mb(); /* pairs with wait_var_event() */
- wake_up_var(var);
}
no_ctx: