Hi Keir,
diff -r 44e3ace9a1f1 drivers/xen/core/reboot.c
--- a/drivers/xen/core/reboot.c Thu Jul 31 09:46:58 2008 +0100
+++ b/drivers/xen/core/reboot.c Fri Aug 01 04:14:43 2008 +0530
@@ -108,6 +116,31 @@ static int xen_suspend(void *__unused)
return 0;
}
+static void switch_shutdown_state(int new_state)
+{
+ int prev_state, old_state = SHUTDOWN_INVALID;
+
+ /* We only drive shutdown_state into an active state. */
+ if (new_state == SHUTDOWN_INVALID)
+ return;
+
+ do {
+ /* We drop this transition if already in an active state. */
+ if ((old_state != SHUTDOWN_INVALID) &&
+ (old_state != SHUTDOWN_RESUMING))
+ return;
+ /* Attempt to transition. */
+ prev_state = old_state;
+ old_state = cmpxchg(&shutting_down, old_state, new_state);
+ } while (old_state != prev_state);
+
+ /* Either we kick off the work, or we leave it to xen_suspend(). */
+ if (old_state == SHUTDOWN_INVALID)
+ schedule_work(&shutdown_work);
+ else
+ BUG_ON(old_state != SHUTDOWN_RESUMING);
+}
+
static void __shutdown_handler(void *unused)
{
int err;
It is doing a busy-wait loop till suspend-resume cycle completes, if
any. I found that it may go more than 25 msec sometimes.
@@ -220,26 +247,24 @@ static struct xenbus_watch sysrq_watch =
static irqreturn_t suspend_int(int irq, void* dev_id, struct pt_regs
*ptregs)
{
- shutting_down = SHUTDOWN_SUSPEND;
- schedule_work(&shutdown_work);
-
+ switch_shutdown_state(SHUTDOWN_SUSPEND);
return IRQ_HANDLED;
}
And you are calling the above busy-wait loop from within an irq handler.
AFAIK it runs in interrupt-context and might cause dead-lock on
uniprocessor setups (especially if underlying process context belongs to
suspend thread itself).
regards,
--
bvk-chaitanya
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|