]> xenbits.xensource.com Git - people/vhanquez/xen.git/commitdiff
Do not deadlock in scheduler when sending VIRQ_CON_RING.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 17 Mar 2009 14:45:07 +0000 (14:45 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 17 Mar 2009 14:45:07 +0000 (14:45 +0000)
Instead defer the virq notification to tasklet context.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen-unstable changeset:   19275:3fd8f9b349413c5a04d0e3f93e43463f1021c9dc
xen-unstable date:        Fri Mar 06 14:28:27 2009 +0000

Avoid deadlock in tasklet_schedule() after console_force_unlock().

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen-unstable changeset:   19296:f57ac4af36b431b10645ee145270ee658f46d58d
xen-unstable date:        Mon Mar 09 09:56:16 2009 +0000

xen/drivers/char/console.c

index 9d24390d38f8f28dbd870121c09ad5ea07c21b4f..17acdb9238a11d34d4c0c691ae547fe693c7eba1 100644 (file)
@@ -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);
@@ -414,6 +420,8 @@ long do_console_io(int cmd, int count, XEN_GUEST_HANDLE(char) buffer)
  * *****************************************************
  */
 
+static bool_t console_locks_busted;
+
 static void __putstr(const char *str)
 {
     int c;
@@ -423,10 +431,12 @@ static void __putstr(const char *str)
     sercon_puts(str);
     vga_puts(str);
 
-    while ( (c = *str++) != '\0' )
-        putchar_console_ring(c);
-
-    send_guest_global_virq(dom0, VIRQ_CON_RING);
+    if ( !console_locks_busted )
+    {
+        while ( (c = *str++) != '\0' )
+            putchar_console_ring(c);
+        tasklet_schedule(&notify_dom0_con_ring_tasklet);
+    }
 }
 
 static int printk_prefix_check(char *p, char **pp)
@@ -659,6 +669,7 @@ void console_force_unlock(void)
 {
     spin_lock_init(&console_lock);
     serial_force_unlock(sercon_handle);
+    console_locks_busted = 1;
     console_start_sync();
 }