aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/core.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 733c61636f0d..15e58d4ea035 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3587,6 +3587,19 @@ static int perf_event_read_one(struct perf_event *event,
3587 return n * sizeof(u64); 3587 return n * sizeof(u64);
3588} 3588}
3589 3589
3590static bool is_event_hup(struct perf_event *event)
3591{
3592 bool no_children;
3593
3594 if (event->state != PERF_EVENT_STATE_EXIT)
3595 return false;
3596
3597 mutex_lock(&event->child_mutex);
3598 no_children = list_empty(&event->child_list);
3599 mutex_unlock(&event->child_mutex);
3600 return no_children;
3601}
3602
3590/* 3603/*
3591 * Read the performance event - simple non blocking version for now 3604 * Read the performance event - simple non blocking version for now
3592 */ 3605 */
@@ -3632,7 +3645,7 @@ static unsigned int perf_poll(struct file *file, poll_table *wait)
3632 3645
3633 poll_wait(file, &event->waitq, wait); 3646 poll_wait(file, &event->waitq, wait);
3634 3647
3635 if (event->state == PERF_EVENT_STATE_EXIT) 3648 if (is_event_hup(event))
3636 return events; 3649 return events;
3637 3650
3638 /* 3651 /*
@@ -7580,6 +7593,12 @@ static void sync_child_event(struct perf_event *child_event,
7580 mutex_unlock(&parent_event->child_mutex); 7593 mutex_unlock(&parent_event->child_mutex);
7581 7594
7582 /* 7595 /*
7596 * Make sure user/parent get notified, that we just
7597 * lost one event.
7598 */
7599 perf_event_wakeup(parent_event);
7600
7601 /*
7583 * Release the parent event, if this was the last 7602 * Release the parent event, if this was the last
7584 * reference to it. 7603 * reference to it.
7585 */ 7604 */