• Frederic Weisbecker's avatar
    hw_breakpoints: Fix per task breakpoint tracking · 45a73372
    Frederic Weisbecker authored
    Freeing a perf event can happen in several ways. A task
    calls perf_event_exit_task() right before exiting. This helper
    will detach all the events from the task context and queue their
    removal through free_event() if they are child tasks. The task
    also loses its context reference there.
    
    Releasing the breakpoint slot from the constraint table is made
    from free_event() that calls release_bp_slot(). We count the number
    of breakpoints this task is running by looking at the task's
    perf_event_ctxp and iterating through its attached events.
    But at this time, the reference to this context has been cleaned up
    already.
    
    So looking at the event->ctx instead of task->perf_event_ctxp
    to count the remaining breakpoints should solve the problem.
    At least it would for child breakpoints, but not for parent ones.
    If the parent exits before the child, it will remove all its
    events from the context but free_event() will be called later,
    on fd release time. And checking the number of breakpoints the
    task has attached to its context at this time is unreliable as all
    events have been removed from the context.
    
    To solve this, we keep track of the list of per task breakpoints.
    On top of it, we maintain our array of numbers of breakpoints used
    by the tasks. We use the context address as a task id.
    
    So, instead of looking at the number of events attached to a context,
    we walk through our list of per task breakpoints and count the number
    of breakpoints that use the same ctx than the one to be reserved or
    released from the constraint table, and update the count on top of this
    result.
    
    In the meantime it solves a bad refcounting, it also solves a warning,
    reported by Paul.
    
    Badness at /home/paulus/kernel/perf/kernel/hw_breakpoint.c:114
    NIP: c0000000000cb470 LR: c0000000000cb46c CTR: c00000000032d9b8
    REGS: c000000118e7b570 TRAP: 0700   Not tainted  (2.6.35-rc3-perf-00008-g76b0f133
    )
    MSR: 9000000000029032 <EE,ME,CE,IR,DR>  CR: 44004424  XER: 000fffff
    TASK = c0000001187dcad0[3143] 'perf' THREAD: c000000118e78000 CPU: 1
    GPR00: c0000000000cb46c c000000118e7b7f0 c0000000009866a0 0000000000000020
    GPR04: 0000000000000000 000000000000001d 0000000000000000 0000000000000001
    GPR08: c0000000009bed68 c00000000086dff8 c000000000a5bf10 0000000000000001
    GPR12: 0000000024004422 c00000000ffff200 0000000000000000 0000000000000000
    GPR16: 0000000000000000 0000000000000000 0000000000000018 00000000101150f4
    GPR20: 0000000010206b40 0000000000000000 0000000000000000 00000000101150f4
    GPR24: c0000001199090c0 0000000000000001 0000000000000000 0000000000000001
    GPR28: 0000000000000000 0000000000000000 c0000000008ec290 0000000000000000
    NIP [c0000000000cb470] .task_bp_pinned+0x5c/0x12c
    LR [c0000000000cb46c] .task_bp_pinned+0x58/0x12c
    Call Trace:
    [c000000118e7b7f0] [c0000000000cb46c] .task_bp_pinned+0x58/0x12c (unreliable)
    [c000000118e7b8a0] [c0000000000cb584] .toggle_bp_task_slot+0x44/0xe4
    [c000000118e7b940] [c0000000000cb6c8] .toggle_bp_slot+0xa4/0x164
    [c000000118e7b9f0] [c0000000000cbafc] .release_bp_slot+0x44/0x6c
    [c000000118e7ba80] [c0000000000c4178] .bp_perf_event_destroy+0x10/0x24
    [c000000118e7bb00] [c0000000000c4aec] .free_event+0x180/0x1bc
    [c000000118e7bbc0] [c0000000000c54c4] .perf_event_release_kernel+0x14c/0x170
    Reported-by: default avatarPaul Mackerras <paulus@samba.org>
    Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
    Cc: Ingo Molnar <mingo@elte.hu>
    Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
    Cc: Prasad <prasad@linux.vnet.ibm.com>
    Cc: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
    Cc: Will Deacon <will.deacon@arm.com>
    Cc: Jason Wessel <jason.wessel@windriver.com>
    45a73372
hw_breakpoint.c 14.1 KB