aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2017-03-16 08:47:51 -0400
committerIngo Molnar <mingo@kernel.org>2017-03-16 09:16:53 -0400
commitd8a8cfc76919b6c830305266b23ba671623f37ff (patch)
tree52dea33ceea0a01448a526ebb31524e4e8417d28
parent15121c789e001168decac6483d192bdb7ea29e74 (diff)
perf/core: Better explain the inherit magic
While going through the event inheritance code Oleg got confused. Add some comments to better explain the silent dissapearance of orphaned events. So what happens is that at perf_event_release_kernel() time; when an event looses its connection to userspace (and ceases to exist from the user's perspective) we can still have an arbitrary amount of inherited copies of the event. We want to synchronously find and remove all these child events. Since that requires a bit of lock juggling, there is the possibility that concurrent clone()s will create new child events. Therefore we first mark the parent event as DEAD, which marks all the extant child events as orphaned. We then avoid copying orphaned events; in order to avoid getting more of them. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Vince Weaver <vincent.weaver@maine.edu> Cc: fweisbec@gmail.com Link: http://lkml.kernel.org/r/20170316125823.289567442@infradead.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--kernel/events/core.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 5f21e5e09ba4..7298e149b732 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4254,7 +4254,7 @@ int perf_event_release_kernel(struct perf_event *event)
4254 4254
4255 raw_spin_lock_irq(&ctx->lock); 4255 raw_spin_lock_irq(&ctx->lock);
4256 /* 4256 /*
4257 * Mark this even as STATE_DEAD, there is no external reference to it 4257 * Mark this event as STATE_DEAD, there is no external reference to it
4258 * anymore. 4258 * anymore.
4259 * 4259 *
4260 * Anybody acquiring event->child_mutex after the below loop _must_ 4260 * Anybody acquiring event->child_mutex after the below loop _must_
@@ -10468,7 +10468,12 @@ const struct perf_event_attr *perf_event_attrs(struct perf_event *event)
10468} 10468}
10469 10469
10470/* 10470/*
10471 * inherit a event from parent task to child task: 10471 * Inherit a event from parent task to child task.
10472 *
10473 * Returns:
10474 * - valid pointer on success
10475 * - NULL for orphaned events
10476 * - IS_ERR() on error
10472 */ 10477 */
10473static struct perf_event * 10478static struct perf_event *
10474inherit_event(struct perf_event *parent_event, 10479inherit_event(struct perf_event *parent_event,
@@ -10562,6 +10567,16 @@ inherit_event(struct perf_event *parent_event,
10562 return child_event; 10567 return child_event;
10563} 10568}
10564 10569
10570/*
10571 * Inherits an event group.
10572 *
10573 * This will quietly suppress orphaned events; !inherit_event() is not an error.
10574 * This matches with perf_event_release_kernel() removing all child events.
10575 *
10576 * Returns:
10577 * - 0 on success
10578 * - <0 on error
10579 */
10565static int inherit_group(struct perf_event *parent_event, 10580static int inherit_group(struct perf_event *parent_event,
10566 struct task_struct *parent, 10581 struct task_struct *parent,
10567 struct perf_event_context *parent_ctx, 10582 struct perf_event_context *parent_ctx,
@@ -10576,6 +10591,11 @@ static int inherit_group(struct perf_event *parent_event,
10576 child, NULL, child_ctx); 10591 child, NULL, child_ctx);
10577 if (IS_ERR(leader)) 10592 if (IS_ERR(leader))
10578 return PTR_ERR(leader); 10593 return PTR_ERR(leader);
10594 /*
10595 * @leader can be NULL here because of is_orphaned_event(). In this
10596 * case inherit_event() will create individual events, similar to what
10597 * perf_group_detach() would do anyway.
10598 */
10579 list_for_each_entry(sub, &parent_event->sibling_list, group_entry) { 10599 list_for_each_entry(sub, &parent_event->sibling_list, group_entry) {
10580 child_ctr = inherit_event(sub, parent, parent_ctx, 10600 child_ctr = inherit_event(sub, parent, parent_ctx,
10581 child, leader, child_ctx); 10601 child, leader, child_ctx);
@@ -10585,6 +10605,17 @@ static int inherit_group(struct perf_event *parent_event,
10585 return 0; 10605 return 0;
10586} 10606}
10587 10607
10608/*
10609 * Creates the child task context and tries to inherit the event-group.
10610 *
10611 * Clears @inherited_all on !attr.inherited or error. Note that we'll leave
10612 * inherited_all set when we 'fail' to inherit an orphaned event; this is
10613 * consistent with perf_event_release_kernel() removing all child events.
10614 *
10615 * Returns:
10616 * - 0 on success
10617 * - <0 on error
10618 */
10588static int 10619static int
10589inherit_task_group(struct perf_event *event, struct task_struct *parent, 10620inherit_task_group(struct perf_event *event, struct task_struct *parent,
10590 struct perf_event_context *parent_ctx, 10621 struct perf_event_context *parent_ctx,
@@ -10607,7 +10638,6 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent,
10607 * First allocate and initialize a context for the 10638 * First allocate and initialize a context for the
10608 * child. 10639 * child.
10609 */ 10640 */
10610
10611 child_ctx = alloc_perf_context(parent_ctx->pmu, child); 10641 child_ctx = alloc_perf_context(parent_ctx->pmu, child);
10612 if (!child_ctx) 10642 if (!child_ctx)
10613 return -ENOMEM; 10643 return -ENOMEM;