vkernel - Fix problem where cpu-bound user process cannot be interrupted
authorMatthew Dillon <dillon@apollo.backplane.com>
Tue, 5 Apr 2011 00:04:12 +0000 (17:04 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 5 Apr 2011 00:04:12 +0000 (17:04 -0700)
* Fix an issue where a cpu-bound user process running in a vkernel cannot
  be interrupted from within the vkernel.

  The problem occurs because the timer interrupt was not marked MPSAFE,
  causing the interrupt thread to hold the MP token which then prevented
  the thread preemption code from letting the timer interrupt thread
  preempt the currently running user process.

* Fixed by marking the timer interrupt and other vkernel interrupt
  handlers as being MPSAFE.

* This is a problem for the vkernel and not for normal kernel.  Normal
  kernels have a doreti function which 'catches' pending flags on
  any attempt to return to userland.

  The vkernel does not, instead relying on the preemption mechanic to
  catch pending flags.

Reported-by: Antonio Huete Jimenez <ahuete.devel@gmail.com>
sys/platform/vkernel/platform/console.c
sys/platform/vkernel/platform/cothread.c
sys/platform/vkernel/platform/kqueue.c
sys/platform/vkernel/platform/shutdown.c
sys/platform/vkernel64/platform/console.c
sys/platform/vkernel64/platform/cothread.c
sys/platform/vkernel64/platform/kqueue.c
sys/platform/vkernel64/platform/shutdown.c

index 431e7ff..cfe3ebe 100644 (file)
@@ -45,6 +45,7 @@
 #include <sys/signalvar.h>
 #include <sys/eventhandler.h>
 #include <sys/interrupt.h>
+#include <sys/bus.h>
 #include <machine/md_var.h>
 #include <unistd.h>
 #include <termios.h>
@@ -345,7 +346,7 @@ vconsinit_fini(struct consdev *cp)
         * We have to do this here rather then in early boot to be able
         * to use the interrupt subsystem.
         */
-       register_int(3, vconswinch_intr, NULL, "swinch", NULL, 0);
+       register_int(3, vconswinch_intr, NULL, "swinch", NULL, INTR_MPSAFE);
        bzero(&sa, sizeof(sa));
        sigemptyset(&sa.sa_mask);
        sa.sa_handler = vconswinchsig;
index b74b8ee..6ba425a 100644 (file)
@@ -46,6 +46,7 @@
 #include <sys/memrange.h>
 #include <sys/tls.h>
 #include <sys/types.h>
+#include <sys/bus.h>
 
 #include <vm/vm_extern.h>
 #include <vm/vm_kern.h>
@@ -91,7 +92,8 @@ cothread_create(void (*thr_func)(cothread_t cotd),
 
        cotd->pintr = pthread_self();
 
-       cotd->intr_id = register_int(1, (void *)thr_intr, cotd, name, NULL, 0);
+       cotd->intr_id = register_int(1, (void *)thr_intr, cotd, name, NULL,
+                                    INTR_MPSAFE);
 
        /*
         * The vkernel's cpu_disable_intr() masks signals.  We don't want
index 267c96a..f16be3f 100644 (file)
@@ -114,7 +114,8 @@ kqueue_add(int fd, void (*func)(void *, struct intrframe *), void *data)
        struct kevent kev;
 
        if (VIntr1 == NULL)
-               VIntr1 = register_int(1, kqueue_intr, NULL, "kqueue", NULL, 0);
+               VIntr1 = register_int(1, kqueue_intr, NULL, "kqueue", NULL,
+                                     INTR_MPSAFE);
 
        info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
        info->func = func;
index 5870290..1da160b 100644 (file)
@@ -45,6 +45,7 @@
 #include <sys/kthread.h>
 #include <sys/reboot.h>
 #include <sys/interrupt.h>
+#include <sys/bus.h>
 #include <ddb/ddb.h>
 
 #include <sys/thread2.h>
@@ -73,7 +74,7 @@ initshutdown(void *arg __unused)
        sa.sa_handler = shutdownsig;
        sigaction(SIGTERM, &sa, NULL);
 
-       register_int(2, shutdown_intr, NULL, "shutdown", NULL, 0);
+       register_int(2, shutdown_intr, NULL, "shutdown", NULL, INTR_MPSAFE);
 }
 
 static
index 11f9618..98b12d0 100644 (file)
@@ -45,6 +45,7 @@
 #include <sys/signalvar.h>
 #include <sys/eventhandler.h>
 #include <sys/interrupt.h>
+#include <sys/bus.h>
 #include <machine/md_var.h>
 #include <unistd.h>
 #include <termios.h>
@@ -345,7 +346,7 @@ vconsinit_fini(struct consdev *cp)
         * We have to do this here rather then in early boot to be able
         * to use the interrupt subsystem.
         */
-       register_int(3, vconswinch_intr, NULL, "swinch", NULL, 0);
+       register_int(3, vconswinch_intr, NULL, "swinch", NULL, INTR_MPSAFE);
        bzero(&sa, sizeof(sa));
        sigemptyset(&sa.sa_mask);
        sa.sa_handler = vconswinchsig;
index 58ea26d..dce5a2b 100644 (file)
@@ -46,6 +46,7 @@
 #include <sys/memrange.h>
 #include <sys/tls.h>
 #include <sys/types.h>
+#include <sys/bus.h>
 
 #include <vm/vm_extern.h>
 #include <vm/vm_kern.h>
@@ -91,7 +92,8 @@ cothread_create(void (*thr_func)(cothread_t cotd),
 
        cotd->pintr = pthread_self();
 
-       cotd->intr_id = register_int(1, (void *)thr_intr, cotd, name, NULL, 0);
+       cotd->intr_id = register_int(1, (void *)thr_intr, cotd, name, NULL,
+                                    INTR_MPSAFE);
 
        /*
         * The vkernel's cpu_disable_intr() masks signals.  We don't want
index c40c0d7..1942403 100644 (file)
@@ -114,7 +114,8 @@ kqueue_add(int fd, void (*func)(void *, struct intrframe *), void *data)
        struct kevent kev;
 
        if (VIntr1 == NULL)
-               VIntr1 = register_int(1, kqueue_intr, NULL, "kqueue", NULL, 0);
+               VIntr1 = register_int(1, kqueue_intr, NULL, "kqueue", NULL,
+                                     INTR_MPSAFE);
 
        info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
        info->func = func;
@@ -135,7 +136,8 @@ kqueue_add_timer(void (*func)(void *, struct intrframe *), void *data)
        struct kqueue_info *info;
 
        if (VIntr1 == NULL)
-               VIntr1 = register_int(1, kqueue_intr, NULL, "kqueue", NULL, 0);
+               VIntr1 = register_int(1, kqueue_intr, NULL, "kqueue", NULL,
+                                     INTR_MPSAFE);
 
        info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
        info->func = func;
index 462910d..9d49e9d 100644 (file)
@@ -45,6 +45,7 @@
 #include <sys/kthread.h>
 #include <sys/reboot.h>
 #include <sys/interrupt.h>
+#include <sys/bus.h>
 #include <ddb/ddb.h>
 
 #include <sys/thread2.h>
@@ -73,7 +74,7 @@ initshutdown(void *arg __unused)
        sa.sa_handler = shutdownsig;
        sigaction(SIGTERM, &sa, NULL);
 
-       register_int(2, shutdown_intr, NULL, "shutdown", NULL, 0);
+       register_int(2, shutdown_intr, NULL, "shutdown", NULL, INTR_MPSAFE);
 }
 
 static