aboutsummaryrefslogtreecommitdiffstats
path: root/xen/drivers/char/console.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-03-06 14:28:27 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-03-06 14:28:27 +0000
commitb3a3ac0f6b46feb2ff6abf4deba9a7395aed2575 (patch)
treee03d74d7bc6ce6baf1d2935a266b8c4b4343f520 /xen/drivers/char/console.c
parent6976476d8c502fa762076493b56ae1ee7d5106e1 (diff)
downloadxen-b3a3ac0f6b46feb2ff6abf4deba9a7395aed2575.tar.gz
xen-b3a3ac0f6b46feb2ff6abf4deba9a7395aed2575.tar.bz2
xen-b3a3ac0f6b46feb2ff6abf4deba9a7395aed2575.zip
Do not deadlock in scheduler when sending VIRQ_CON_RING.
Instead defer the virq notification to tasklet context. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/drivers/char/console.c')
-rw-r--r--xen/drivers/char/console.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 3096b3ec9d..00a32022dd 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -315,6 +315,12 @@ static void serial_rx(char c, struct cpu_user_regs *regs)
__serial_rx(c, regs);
}
+static void notify_dom0_con_ring(unsigned long unused)
+{
+ send_guest_global_virq(dom0, VIRQ_CON_RING);
+}
+static DECLARE_TASKLET(notify_dom0_con_ring_tasklet, notify_dom0_con_ring, 0);
+
static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count)
{
char kbuf[128], *kptr;
@@ -348,7 +354,7 @@ static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count)
{
for ( kptr = kbuf; *kptr != '\0'; kptr++ )
putchar_console_ring(*kptr);
- send_guest_global_virq(dom0, VIRQ_CON_RING);
+ tasklet_schedule(&notify_dom0_con_ring_tasklet);
}
spin_unlock_irq(&console_lock);
@@ -426,7 +432,7 @@ static void __putstr(const char *str)
while ( (c = *str++) != '\0' )
putchar_console_ring(c);
- send_guest_global_virq(dom0, VIRQ_CON_RING);
+ tasklet_schedule(&notify_dom0_con_ring_tasklet);
}
static int printk_prefix_check(char *p, char **pp)