|
@@ -6722,17 +6722,20 @@ __perf_event_exit_task(struct perf_event *child_event,
|
|
|
struct perf_event_context *child_ctx,
|
|
|
struct task_struct *child)
|
|
|
{
|
|
|
- struct perf_event *parent_event;
|
|
|
+ if (child_event->parent) {
|
|
|
+ raw_spin_lock_irq(&child_ctx->lock);
|
|
|
+ perf_group_detach(child_event);
|
|
|
+ raw_spin_unlock_irq(&child_ctx->lock);
|
|
|
+ }
|
|
|
|
|
|
perf_remove_from_context(child_event);
|
|
|
|
|
|
- parent_event = child_event->parent;
|
|
|
/*
|
|
|
- * It can happen that parent exits first, and has events
|
|
|
+ * It can happen that the parent exits first, and has events
|
|
|
* that are still around due to the child reference. These
|
|
|
- * events need to be zapped - but otherwise linger.
|
|
|
+ * events need to be zapped.
|
|
|
*/
|
|
|
- if (parent_event) {
|
|
|
+ if (child_event->parent) {
|
|
|
sync_child_event(child_event, child);
|
|
|
free_event(child_event);
|
|
|
}
|