Commit dc633982 authored by Jiri Olsa's avatar Jiri Olsa Committed by Ingo Molnar

perf: Do not POLLHUP event if it has children

Currently we return POLLHUP in event polling if the monitored
process is done, but we didn't consider possible children,
that might be still running and producing data.

Before returning POLLHUP making sure that:

   1) the monitored task has exited and that
   2) we don't have any children to monitor

Also adding parent wakeup when the child event is gone.
Suggested-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1410520708-19275-1-git-send-email-jolsa@kernel.org
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 4f7cf3a9
...@@ -3587,6 +3587,19 @@ static int perf_event_read_one(struct perf_event *event, ...@@ -3587,6 +3587,19 @@ static int perf_event_read_one(struct perf_event *event,
return n * sizeof(u64); return n * sizeof(u64);
} }
static bool is_event_hup(struct perf_event *event)
{
bool no_children;
if (event->state != PERF_EVENT_STATE_EXIT)
return false;
mutex_lock(&event->child_mutex);
no_children = list_empty(&event->child_list);
mutex_unlock(&event->child_mutex);
return no_children;
}
/* /*
* Read the performance event - simple non blocking version for now * Read the performance event - simple non blocking version for now
*/ */
...@@ -3632,7 +3645,7 @@ static unsigned int perf_poll(struct file *file, poll_table *wait) ...@@ -3632,7 +3645,7 @@ static unsigned int perf_poll(struct file *file, poll_table *wait)
poll_wait(file, &event->waitq, wait); poll_wait(file, &event->waitq, wait);
if (event->state == PERF_EVENT_STATE_EXIT) if (is_event_hup(event))
return events; return events;
/* /*
...@@ -7579,6 +7592,12 @@ static void sync_child_event(struct perf_event *child_event, ...@@ -7579,6 +7592,12 @@ static void sync_child_event(struct perf_event *child_event,
list_del_init(&child_event->child_list); list_del_init(&child_event->child_list);
mutex_unlock(&parent_event->child_mutex); mutex_unlock(&parent_event->child_mutex);
/*
* Make sure user/parent get notified, that we just
* lost one event.
*/
perf_event_wakeup(parent_event);
/* /*
* Release the parent event, if this was the last * Release the parent event, if this was the last
* reference to it. * reference to it.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment