Commit 40bb3406 authored by Stéphane Eranian's avatar Stéphane Eranian Committed by Tony Luck

[IA64] perfmon: enable interrupts around semaphore call

fix a problem in pfm_handle_work() where a task may
go to sleep in down_interruptible() with interrupts
disabled. This may happen only for a monitored thread
for which the PFM_FL_NOTIFY_BLOCK flag is set. The fix
re-enables interrupts around the semaphore call. It is safe
to do so because pfm_handle_work() is called from
do_notify_user() which is called only when the task is about
to leave the kernel, i.e., no risk of stack overflow because
of interrupt nesting.

fix a debug printk warning in pfm_write_pmcs()
signed-off-by: default avatarStephane Eranian <eranian@hpl.hp.com>
ack-by: default avatarDavid Mosberger <davidm@hpl.hp.com>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent 69b3a5ac
...@@ -3057,7 +3057,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) ...@@ -3057,7 +3057,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
#endif #endif
} }
DPRINT(("pmc[%u]=0x%lx ld=%d apmu=%d flags=0x%lx all_pmcs=0x%lx used_pmds=0x%lx eventid=%ld smpl_pmds=0x%lx reset_pmds=0x%lx reloads_pmcs=0x%lx used_monitors=0x%lx ovfl_regs=0x%lx\n", DPRINT(("pmc[%u]=0x%lx ld=%d apmu=%d flags=0x%x all_pmcs=0x%lx used_pmds=0x%lx eventid=%ld smpl_pmds=0x%lx reset_pmds=0x%lx reloads_pmcs=0x%lx used_monitors=0x%lx ovfl_regs=0x%lx\n",
cnum, cnum,
value, value,
is_loaded, is_loaded,
...@@ -5057,6 +5057,18 @@ pfm_handle_work(void) ...@@ -5057,6 +5057,18 @@ pfm_handle_work(void)
UNPROTECT_CTX(ctx, flags); UNPROTECT_CTX(ctx, flags);
/*
* pfm_handle_work() is currently called with interrupts disabled.
* The down_interruptible call may sleep, therefore we
* must re-enable interrupts to avoid deadlocks. It is
* safe to do so because this function is called ONLY
* when returning to user level (PUStk=1), in which case
* there is no risk of kernel stack overflow due to deep
* interrupt nesting.
*/ */
BUG_ON(flags & IA64_PSR_I);
local_irq_enable();
DPRINT(("before block sleeping\n")); DPRINT(("before block sleeping\n"));
/* /*
...@@ -5067,6 +5079,12 @@ pfm_handle_work(void) ...@@ -5067,6 +5079,12 @@ pfm_handle_work(void)
DPRINT(("after block sleeping ret=%d\n", ret)); DPRINT(("after block sleeping ret=%d\n", ret));
/*
* disable interrupts to restore state we had upon entering
* this function
*/
local_irq_disable();
PROTECT_CTX(ctx, flags); PROTECT_CTX(ctx, flags);
/* /*
......
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