vkernel/intr: Pin vkernel "hardware interrupts" to CPU0
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 31 Dec 2011 03:29:32 +0000 (11:29 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 31 Dec 2011 03:37:36 +0000 (11:37 +0800)
Due to the nondeterminsm of CPU to which SIGIO will be delivered,
we can't depend on "hardware interrupts" of vkernel always happen
on the registered CPU.  We now pin the vkernel "hardware interrupts"
to CPU0, so the interrupt scheduling code could always know the
correct ithread to be scheduled.

Reported-by: tuxillo vsrinivas
12 files changed:
sys/kern/kern_intr.c
sys/platform/vkernel/platform/console.c
sys/platform/vkernel/platform/cothread.c
sys/platform/vkernel/platform/kqueue.c
sys/platform/vkernel/platform/machintr.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/machintr.c
sys/platform/vkernel64/platform/shutdown.c
sys/sys/interrupt.h

index 1bbe479..22d06c1 100644 (file)
@@ -575,6 +575,30 @@ sched_ithd_hard(int intr)
        sched_ithd_intern(&intr_info_ary[mycpuid][intr]);
 }
 
+#ifdef _KERNEL_VIRTUAL
+
+void
+sched_ithd_hard_virtual(int intr)
+{
+       KKASSERT(intr >= 0 && intr < MAX_HARDINTS);
+       sched_ithd_intern(&intr_info_ary[0][intr]);
+}
+
+void *
+register_int_virtual(int intr, inthand2_t *handler, void *arg, const char *name,
+    struct lwkt_serialize *serializer, int intr_flags)
+{
+       return register_int(intr, handler, arg, name, serializer, intr_flags, 0);
+}
+
+void
+unregister_int_virtual(void *id)
+{
+       unregister_int(id, 0);
+}
+
+#endif /* _KERN_VIRTUAL */
+
 static void
 report_stray_interrupt(struct intr_info *info, const char *func)
 {
index f21c6c3..8fab22b 100644 (file)
@@ -346,7 +346,8 @@ 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, INTR_MPSAFE, 0);
+       register_int_virtual(3, vconswinch_intr, NULL, "swinch", NULL,
+           INTR_MPSAFE);
        bzero(&sa, sizeof(sa));
        sigemptyset(&sa.sa_mask);
        sa.sa_handler = vconswinchsig;
index 9b304cd..c00b9ce 100644 (file)
@@ -92,8 +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,
-                                    INTR_MPSAFE, 0);
+       cotd->intr_id = register_int_virtual(1, (void *)thr_intr, cotd, name,
+           NULL, INTR_MPSAFE);
 
        /*
         * The vkernel's cpu_disable_intr() masks signals.  We don't want
@@ -117,7 +117,7 @@ cothread_delete(cothread_t *cotdp)
        cothread_t cotd;
 
        if ((cotd = *cotdp) != NULL) {
-               unregister_int(cotd->intr_id, 0);
+               unregister_int_virtual(cotd->intr_id);
                crit_enter();
                pthread_join(cotd->pthr, NULL);
                crit_exit();
index 27dee77..95c72e6 100644 (file)
@@ -114,8 +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,
-                                     INTR_MPSAFE, 0);
+               VIntr1 = register_int_virtual(1, kqueue_intr, NULL, "kqueue",
+                   NULL, INTR_MPSAFE);
        }
 
        info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
@@ -137,8 +137,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, 0);
+               VIntr1 = register_int_virtual(1, kqueue_intr, NULL, "kqueue",
+                   NULL, INTR_MPSAFE);
        }
 
        info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
index bb7a41a..166315e 100644 (file)
@@ -144,7 +144,7 @@ splz(void)
                        while ((irq = ffs(gd->gd_fpending)) != 0) {
                                --irq;
                                atomic_clear_int(&gd->gd_fpending, 1 << irq);
-                               sched_ithd_hard(irq);
+                               sched_ithd_hard_virtual(irq);
                        }
                }
                crit_exit_noyield(td);
@@ -154,8 +154,8 @@ splz(void)
 /*
  * Allows an unprotected signal handler or mailbox to signal an interrupt
  *
- * For sched_ithd_hard() to properly preempt via lwkt_schedule() we cannot
- * enter a critical section here.  We use td_nest_count instead.
+ * For sched_ithd_hard_virtaul() to properly preempt via lwkt_schedule() we
+ * cannot enter a critical section here.  We use td_nest_count instead.
  */
 void
 signalintr(int intr)
@@ -169,7 +169,7 @@ signalintr(int intr)
        } else {
                ++td->td_nest_count;
                atomic_clear_int(&gd->gd_fpending, 1 << intr);
-               sched_ithd_hard(intr);
+               sched_ithd_hard_virtual(intr);
                --td->td_nest_count;
        }
 }
index b1f0c01..13253c6 100644 (file)
@@ -74,7 +74,8 @@ initshutdown(void *arg __unused)
        sa.sa_handler = shutdownsig;
        sigaction(SIGTERM, &sa, NULL);
 
-       register_int(2, shutdown_intr, NULL, "shutdown", NULL, INTR_MPSAFE, 0);
+       register_int_virtual(2, shutdown_intr, NULL, "shutdown", NULL,
+           INTR_MPSAFE);
 }
 
 static
index 163ab74..93f2c7a 100644 (file)
@@ -346,7 +346,8 @@ 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, INTR_MPSAFE, 0);
+       register_int_virtual(3, vconswinch_intr, NULL, "swinch", NULL,
+           INTR_MPSAFE);
        bzero(&sa, sizeof(sa));
        sigemptyset(&sa.sa_mask);
        sa.sa_handler = vconswinchsig;
index 88875b7..b46d7a9 100644 (file)
@@ -92,8 +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,
-                                    INTR_MPSAFE, 0);
+       cotd->intr_id = register_int_virtual(1, (void *)thr_intr, cotd, name,
+           NULL, INTR_MPSAFE);
 
        /*
         * The vkernel's cpu_disable_intr() masks signals.  We don't want
@@ -117,7 +117,7 @@ cothread_delete(cothread_t *cotdp)
        cothread_t cotd;
 
        if ((cotd = *cotdp) != NULL) {
-               unregister_int(cotd->intr_id, 0);
+               unregister_int_virtual(cotd->intr_id);
                crit_enter();
                pthread_join(cotd->pthr, NULL);
                crit_exit();
index f5f03ba..c06d4c5 100644 (file)
@@ -114,8 +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,
-                                     INTR_MPSAFE, 0);
+               VIntr1 = register_int_virtual(1, kqueue_intr, NULL, "kqueue",
+                   NULL, INTR_MPSAFE);
        }
 
        info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
@@ -137,8 +137,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,
-                                     INTR_MPSAFE, 0);
+               VIntr1 = register_int_virtual(1, kqueue_intr, NULL, "kqueue",
+                   NULL, INTR_MPSAFE);
        }
 
        info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
index a0ad5ca..ba83191 100644 (file)
@@ -144,7 +144,7 @@ splz(void)
                        while ((irq = ffs(gd->gd_fpending)) != 0) {
                                --irq;
                                atomic_clear_int(&gd->gd_fpending, 1 << irq);
-                               sched_ithd_hard(irq);
+                               sched_ithd_hard_virtual(irq);
                        }
                }
                crit_exit_noyield(td);
@@ -154,8 +154,8 @@ splz(void)
 /*
  * Allows an unprotected signal handler or mailbox to signal an interrupt
  *
- * For sched_ithd_hard() to properly preempt via lwkt_schedule() we cannot
- * enter a critical section here.  We use td_nest_count instead.
+ * For sched_ithd_hard_virtual() to properly preempt via lwkt_schedule() we
+ * cannot enter a critical section here.  We use td_nest_count instead.
  */
 void
 signalintr(int intr)
@@ -169,7 +169,7 @@ signalintr(int intr)
        } else {
                ++td->td_nest_count;
                atomic_clear_int(&gd->gd_fpending, 1 << intr);
-               sched_ithd_hard(intr);
+               sched_ithd_hard_virtual(intr);
                --td->td_nest_count;
        }
 }
index a4a0588..daefb48 100644 (file)
@@ -74,7 +74,8 @@ initshutdown(void *arg __unused)
        sa.sa_handler = shutdownsig;
        sigaction(SIGTERM, &sa, NULL);
 
-       register_int(2, shutdown_intr, NULL, "shutdown", NULL, INTR_MPSAFE, 0);
+       register_int_virtual(2, shutdown_intr, NULL, "shutdown", NULL,
+           INTR_MPSAFE);
 }
 
 static
index 4c02bf2..49c8407 100644 (file)
@@ -126,6 +126,13 @@ int next_registered_randintr(int intr);
 void sched_ithd_soft(int intr);        /* procedure called from MD */
 void sched_ithd_hard(int intr);        /* procedure called from MD */
 
+#ifdef _KERNEL_VIRTUAL
+void *register_int_virtual(int intr, inthand2_t *handler, void *arg,
+    const char *name, struct lwkt_serialize *serializer, int flags);
+void unregister_int_virtual(void *id);
+void sched_ithd_hard_virtual(int intr);
+#endif
+
 extern char    eintrnames[];   /* end of intrnames[] */
 extern char    intrnames[];    /* string table containing device names */