perf, hw_breakpoint: Fix crash in hw_breakpoint creation
hw_breakpoint creation needs to account stuff per-task to ensure there is always sufficient hardware resources to back these things due to ptrace. With the perf per pmu context changes the event initialization no longer has access to the event context, for the simple reason that we need to first find the pmu (result of initialization) before we can find the context. This makes hw_breakpoints unhappy, because it can no longer do per task accounting, cure this by frobbing a task pointer in the event::hw bits for now... Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20101014203625.391543667@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
c6be5a5cb6
commit
d580ff8699
3 changed files with 29 additions and 9 deletions
|
@ -5255,9 +5255,10 @@ unlock:
|
|||
*/
|
||||
static struct perf_event *
|
||||
perf_event_alloc(struct perf_event_attr *attr, int cpu,
|
||||
struct perf_event *group_leader,
|
||||
struct perf_event *parent_event,
|
||||
perf_overflow_handler_t overflow_handler)
|
||||
struct task_struct *task,
|
||||
struct perf_event *group_leader,
|
||||
struct perf_event *parent_event,
|
||||
perf_overflow_handler_t overflow_handler)
|
||||
{
|
||||
struct pmu *pmu;
|
||||
struct perf_event *event;
|
||||
|
@ -5299,6 +5300,17 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
|
|||
|
||||
event->state = PERF_EVENT_STATE_INACTIVE;
|
||||
|
||||
if (task) {
|
||||
event->attach_state = PERF_ATTACH_TASK;
|
||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||
/*
|
||||
* hw_breakpoint is a bit difficult here..
|
||||
*/
|
||||
if (attr->type == PERF_TYPE_BREAKPOINT)
|
||||
event->hw.bp_target = task;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!overflow_handler && parent_event)
|
||||
overflow_handler = parent_event->overflow_handler;
|
||||
|
||||
|
@ -5559,7 +5571,7 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||
}
|
||||
}
|
||||
|
||||
event = perf_event_alloc(&attr, cpu, group_leader, NULL, NULL);
|
||||
event = perf_event_alloc(&attr, cpu, task, group_leader, NULL, NULL);
|
||||
if (IS_ERR(event)) {
|
||||
err = PTR_ERR(event);
|
||||
goto err_task;
|
||||
|
@ -5728,7 +5740,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
|
|||
* Get the target context (task or percpu):
|
||||
*/
|
||||
|
||||
event = perf_event_alloc(attr, cpu, NULL, NULL, overflow_handler);
|
||||
event = perf_event_alloc(attr, cpu, task, NULL, NULL, overflow_handler);
|
||||
if (IS_ERR(event)) {
|
||||
err = PTR_ERR(event);
|
||||
goto err;
|
||||
|
@ -5996,6 +6008,7 @@ inherit_event(struct perf_event *parent_event,
|
|||
|
||||
child_event = perf_event_alloc(&parent_event->attr,
|
||||
parent_event->cpu,
|
||||
child,
|
||||
group_leader, parent_event,
|
||||
NULL);
|
||||
if (IS_ERR(child_event))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue