MP Implmentation 3B/4: Remove Xcpuast and Xforward_irq, replacing them
authorMatthew Dillon <dillon@dragonflybsd.org>
Fri, 11 Jul 2003 01:23:24 +0000 (01:23 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Fri, 11 Jul 2003 01:23:24 +0000 (01:23 +0000)
with IPI messaging functions.  Fix user scheduling issues so user processes
are dependably scheduled on available cpus.

21 files changed:
sys/i386/apic/apic_vector.s
sys/i386/i386/mp_machdep.c
sys/i386/i386/trap.c
sys/i386/include/smp.h
sys/i386/isa/apic_vector.s
sys/i386/isa/intr_machdep.c
sys/i386/isa/intr_machdep.h
sys/kern/kern_intr.c
sys/kern/kern_sig.c
sys/kern/kern_switch.c
sys/kern/kern_synch.c
sys/kern/lwkt_thread.c
sys/platform/pc32/apic/apic_vector.s
sys/platform/pc32/i386/mp_machdep.c
sys/platform/pc32/i386/trap.c
sys/platform/pc32/include/smp.h
sys/platform/pc32/isa/apic_vector.s
sys/platform/pc32/isa/intr_machdep.c
sys/platform/pc32/isa/intr_machdep.h
sys/sys/proc.h
sys/sys/thread.h

index ca7208c..660bf65 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     from: vector.s, 386BSD 0.1 unknown origin
  * $FreeBSD: src/sys/i386/isa/apic_vector.s,v 1.47.2.5 2001/09/01 22:33:38 tegge Exp $
- * $DragonFly: src/sys/i386/apic/Attic/apic_vector.s,v 1.9 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/i386/apic/Attic/apic_vector.s,v 1.10 2003/07/11 01:23:23 dillon Exp $
  */
 
 
@@ -421,133 +421,6 @@ Xcpucheckstate:
 #endif /* BETTER_CLOCK */
 #endif
 
-/*
- * Executed by a CPU when it receives an Xcpuast IPI from another CPU,
- *
- *  - Signals its receipt by clearing bit cpuid in checkstate_need_ast.
- *  - MP safe in regards to setting AST_PENDING because doreti is in
- *    a cli mode when it checks.
- */
-
-       .text
-       SUPERALIGN_TEXT
-       .globl Xcpuast
-Xcpuast:
-       PUSH_FRAME
-
-       movl    PCPU(cpuid), %eax
-       lock                            /* checkstate_need_ast &= ~(1<<id) */
-       btrl    %eax, checkstate_need_ast
-       movl    $0, lapic_eoi           /* End Of Interrupt to APIC */
-
-       lock
-       btsl    %eax, checkstate_pending_ast
-       jc      1f
-
-       FAKE_MCOUNT(13*4(%esp))
-
-       movl    PCPU(curthread), %eax
-       pushl   TD_CPL(%eax)            /* cpl restored by doreti */
-
-       orl     $AST_PENDING, PCPU(astpending)  /* XXX */
-       incl    PCPU(intr_nesting_level)
-       sti
-       
-       movl    PCPU(cpuid), %eax
-       lock    
-       btrl    %eax, checkstate_pending_ast
-       lock    
-       btrl    %eax, CNAME(resched_cpus)
-       jnc     2f
-       orl     $AST_PENDING+AST_RESCHED,PCPU(astpending)
-2:             
-       MEXITCOUNT
-       jmp     doreti
-1:
-       /* We are already in the process of delivering an ast for this CPU */
-       POP_FRAME
-       iret                    
-
-
-/*
- *      Executed by a CPU when it receives an XFORWARD_IRQ IPI.
- */
-
-       .text
-       SUPERALIGN_TEXT
-       .globl Xforward_irq
-Xforward_irq:
-       PUSH_FRAME
-
-       movl    $0, lapic_eoi           /* End Of Interrupt to APIC */
-
-       FAKE_MCOUNT(13*4(%esp))
-
-       call    try_mplock
-       testl   %eax,%eax               /* Did we get the lock ? */
-       jz  1f                          /* No */
-
-       incl    PCPU(cnt)+V_FORWARDED_HITS
-       
-       movl    PCPU(curthread), %eax
-       pushl   TD_CPL(%eax)            /* cpl restored by doreti */
-
-       incl    PCPU(intr_nesting_level)
-       sti
-       
-       MEXITCOUNT
-       jmp     doreti                  /* Handle forwarded interrupt */
-1:
-       incl    PCPU(cnt)+V_FORWARDED_MISSES
-       call    forward_irq     /* Oops, we've lost the isr lock */
-       MEXITCOUNT
-       POP_FRAME
-       iret
-3:     
-       call    rel_mplock
-       MEXITCOUNT
-       POP_FRAME
-       iret
-
-/*
- * 
- */
-forward_irq:
-       MCOUNT
-       cmpl    $0,invltlb_ok
-       jz      4f
-
-       cmpl    $0, CNAME(forward_irq_enabled)
-       jz      4f
-
-       movl    mp_lock,%eax
-       cmpl    $MP_FREE_LOCK,%eax
-       jne     1f
-       movl    $0, %eax                /* Pick CPU #0 if noone has lock */
-1:
-       shrl    $24,%eax
-       movl    cpu_num_to_apic_id(,%eax,4),%ecx
-       shll    $24,%ecx
-       movl    lapic_icr_hi, %eax
-       andl    $~APIC_ID_MASK, %eax
-       orl     %ecx, %eax
-       movl    %eax, lapic_icr_hi
-
-2:
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_DELSTAT_MASK,%eax
-       jnz     2b
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_RESV2_MASK, %eax
-       orl     $(APIC_DEST_DESTFLD|APIC_DELMODE_FIXED|XFORWARD_IRQ_OFFSET), %eax
-       movl    %eax, lapic_icr_lo
-3:
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_DELSTAT_MASK,%eax
-       jnz     3b
-4:             
-       ret
-
 /*
  * Executed by a CPU when it receives an Xcpustop IPI from another CPU,
  *
@@ -804,15 +677,7 @@ started_cpus:
 checkstate_probed_cpus:
        .long   0       
 #endif /* BETTER_CLOCK */
-       .globl checkstate_need_ast
-checkstate_need_ast:
-       .long   0
-checkstate_pending_ast:
-       .long   0
-       .globl CNAME(resched_cpus)
        .globl CNAME(cpustop_restartfunc)
-CNAME(resched_cpus):
-       .long 0
 CNAME(cpustop_restartfunc):
        .long 0
                
index c4cb9ce..419a8fc 100644 (file)
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $
- * $DragonFly: src/sys/i386/i386/Attic/mp_machdep.c,v 1.11 2003/07/10 04:47:53 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/mp_machdep.c,v 1.12 2003/07/11 01:23:21 dillon Exp $
  */
 
 #include "opt_cpu.h"
@@ -597,6 +597,7 @@ mp_enable(u_int boot_addr)
        setidt(XRENDEZVOUS_OFFSET, Xrendezvous,
               SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
 
+#if 0
        /* install an inter-CPU IPI for forcing an additional software trap */
        setidt(XCPUAST_OFFSET, Xcpuast,
               SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
@@ -604,6 +605,7 @@ mp_enable(u_int boot_addr)
        /* install an inter-CPU IPI for interrupt forwarding */
        setidt(XFORWARD_IRQ_OFFSET, Xforward_irq,
               SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+#endif
 
        /* install an inter-CPU IPI for CPU stop/restart */
        setidt(XCPUSTOP_OFFSET, Xcpustop,
@@ -2661,22 +2663,8 @@ forward_statclock(int pscnt)
                        continue;
                forwarded_statclock(id, pscnt, &map);
        }
-       if (map != 0) {
-               checkstate_need_ast |= map;
-               selected_apic_ipi(map, XCPUAST_OFFSET, APIC_DELMODE_FIXED);
-               i = 0;
-               while ((checkstate_need_ast & map) != 0) {
-                       /* spin */
-                       i++;
-                       if (i > 100000) { 
-#ifdef BETTER_CLOCK_DIAGNOSTIC
-                               printf("forward_statclock: dropped ast 0x%x\n",
-                                      checkstate_need_ast & map);
-#endif
-                               break;
-                       }
-               }
-       }
+       if (map != 0)
+               resched_cpus(map);
 }
 
 void 
@@ -2759,111 +2747,12 @@ forward_hardclock(int pscnt)
                }
 #endif
        }
-       if (map != 0) {
-               checkstate_need_ast |= map;
-               selected_apic_ipi(map, XCPUAST_OFFSET, APIC_DELMODE_FIXED);
-               i = 0;
-               while ((checkstate_need_ast & map) != 0) {
-                       /* spin */
-                       i++;
-                       if (i > 100000) { 
-#ifdef BETTER_CLOCK_DIAGNOSTIC
-                               printf("forward_hardclock: dropped ast 0x%x\n",
-                                      checkstate_need_ast & map);
-#endif
-                               break;
-                       }
-               }
-       }
+       if (map != 0) 
+               resched_cpus(map);
 }
 
 #endif /* BETTER_CLOCK */
 
-void 
-forward_signal(struct proc *p)
-{
-       /* YYY forward_signal */
-#if 0
-       int map;
-       int id;
-       int i;
-
-       /* Kludge. We don't yet have separate locks for the interrupts
-        * and the kernel. This means that we cannot let the other processors
-        * handle complex interrupts while inhibiting them from entering
-        * the kernel in a non-interrupt context.
-        *
-        * What we can do, without changing the locking mechanisms yet,
-        * is letting the other processors handle a very simple interrupt
-        * (wich determines the processor states), and do the main
-        * work ourself.
-        */
-
-       if (!smp_started || !invltlb_ok || cold || panicstr)
-               return;
-       if (!forward_signal_enabled)
-               return;
-       while (1) {
-               if (p->p_stat != SRUN)
-                       return;
-               id = p->p_oncpu;
-               if (id == 0xff)
-                       return;
-               map = (1<<id);
-               checkstate_need_ast |= map;
-               selected_apic_ipi(map, XCPUAST_OFFSET, APIC_DELMODE_FIXED);
-               i = 0;
-               while ((checkstate_need_ast & map) != 0) {
-                       /* spin */
-                       i++;
-                       if (i > 100000) { 
-#if 0
-                               printf("forward_signal: dropped ast 0x%x\n",
-                                      checkstate_need_ast & map);
-#endif
-                               break;
-                       }
-               }
-               if (id == p->p_oncpu)
-                       return;
-       }
-#endif
-}
-
-void
-forward_roundrobin(void)
-{
-       /* YYY forward_roundrobin */
-#if 0
-       u_int map;
-       int i;
-
-       if (!smp_started || !invltlb_ok || cold || panicstr)
-               return;
-       if (!forward_roundrobin_enabled)
-               return;
-       resched_cpus |= mycpu->gd_other_cpus;
-       map = mycpu->gd_other_cpus & ~stopped_cpus ;
-#if 1
-       selected_apic_ipi(map, XCPUAST_OFFSET, APIC_DELMODE_FIXED);
-#else
-       (void) all_but_self_ipi(XCPUAST_OFFSET);
-#endif
-       i = 0;
-       while ((checkstate_need_ast & map) != 0) {
-               /* spin */
-               i++;
-               if (i > 100000) {
-#if 0
-                       printf("forward_roundrobin: dropped ast 0x%x\n",
-                              checkstate_need_ast & map);
-#endif
-                       break;
-               }
-       }
-#endif
-}
-
 #ifdef APIC_INTR_REORDER
 /*
  *     Maintain mapping from softintr vector to isr bit in local apic.
index 9542d9a..b6bcd4a 100644 (file)
@@ -36,7 +36,7 @@
  *
  *     from: @(#)trap.c        7.4 (Berkeley) 5/13/91
  * $FreeBSD: src/sys/i386/i386/trap.c,v 1.147.2.11 2003/02/27 19:09:59 luoqi Exp $
- * $DragonFly: src/sys/i386/i386/Attic/trap.c,v 1.20 2003/07/10 04:47:53 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/trap.c,v 1.21 2003/07/11 01:23:21 dillon Exp $
  */
 
 /*
@@ -200,6 +200,10 @@ userexit(struct proc *p)
         * If we did not have to release we should already be P_CURPROC.  If
         * we did have to release we must acquire P_CURPROC again and then
         * restore our priority for user return.
+        *
+        * Lowering our priority may make other higher priority threads
+        * runnable. lwkt_setpri_self() does not switch away, so call
+        * lwkt_maybe_switch() to deal with it.
         */
        if (td->td_release) {
                td->td_release = NULL;
@@ -218,6 +222,7 @@ userexit(struct proc *p)
                        lwkt_setpri_self(TDPRI_USER_NORM);
                        break;
                }
+               lwkt_maybe_switch();
        }
 }
 
@@ -235,18 +240,17 @@ userret(struct proc *p, struct trapframe *frame, u_quad_t oticks)
        }
 
        /*
-        * If a reschedule has been requested we lwkt_switch().  The
-        * lwkt_switch() will ensure that our current process is released
-        * (see the use of td_release) as well as ensure that any pending
-        * LWKTs get run before we get cpu back.
-        *
-        * YYY though of doreti detects that we were in a user context
-        * it should really just call lwkt_switch()!  and are re-acquisition 
-        * of the current process below will handle userland scheduling
-        * priorities.
+        * If a reschedule has been requested then the easiest solution
+        * is to run our passive release function which will shift our
+        * P_CURPROC designation to another user process.  We don't actually
+        * switch here because that would be a waste of cycles (the newly 
+        * scheduled user process would just switch back to us since we are
+        * running at a kernel priority).  Instead we fall through and will
+        * switch away when we attempt to reacquire our P_CURPROC designation.
         */
        if (resched_wanted()) {
-               lwkt_switch();
+               if (curthread->td_release)
+                       passive_release(curthread);
        }
 
        /*
index b422a04..efd23bc 100644 (file)
@@ -7,7 +7,7 @@
  * ----------------------------------------------------------------------------
  *
  * $FreeBSD: src/sys/i386/include/smp.h,v 1.50.2.5 2001/02/13 22:32:45 tegge Exp $
- * $DragonFly: src/sys/i386/include/Attic/smp.h,v 1.4 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/i386/include/Attic/smp.h,v 1.5 2003/07/11 01:23:23 dillon Exp $
  *
  */
 
@@ -52,8 +52,6 @@ extern volatile u_int         stopped_cpus;
 extern volatile u_int          started_cpus;
 
 extern volatile u_int          checkstate_probed_cpus;
-extern volatile u_int          checkstate_need_ast;
-extern volatile u_int          resched_cpus;
 extern void (*cpustop_restartfunc) __P((void));
 
 /* functions in apic_ipl.s */
index 3ad2634..0a8d36f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     from: vector.s, 386BSD 0.1 unknown origin
  * $FreeBSD: src/sys/i386/isa/apic_vector.s,v 1.47.2.5 2001/09/01 22:33:38 tegge Exp $
- * $DragonFly: src/sys/i386/isa/Attic/apic_vector.s,v 1.9 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/i386/isa/Attic/apic_vector.s,v 1.10 2003/07/11 01:23:23 dillon Exp $
  */
 
 
@@ -421,133 +421,6 @@ Xcpucheckstate:
 #endif /* BETTER_CLOCK */
 #endif
 
-/*
- * Executed by a CPU when it receives an Xcpuast IPI from another CPU,
- *
- *  - Signals its receipt by clearing bit cpuid in checkstate_need_ast.
- *  - MP safe in regards to setting AST_PENDING because doreti is in
- *    a cli mode when it checks.
- */
-
-       .text
-       SUPERALIGN_TEXT
-       .globl Xcpuast
-Xcpuast:
-       PUSH_FRAME
-
-       movl    PCPU(cpuid), %eax
-       lock                            /* checkstate_need_ast &= ~(1<<id) */
-       btrl    %eax, checkstate_need_ast
-       movl    $0, lapic_eoi           /* End Of Interrupt to APIC */
-
-       lock
-       btsl    %eax, checkstate_pending_ast
-       jc      1f
-
-       FAKE_MCOUNT(13*4(%esp))
-
-       movl    PCPU(curthread), %eax
-       pushl   TD_CPL(%eax)            /* cpl restored by doreti */
-
-       orl     $AST_PENDING, PCPU(astpending)  /* XXX */
-       incl    PCPU(intr_nesting_level)
-       sti
-       
-       movl    PCPU(cpuid), %eax
-       lock    
-       btrl    %eax, checkstate_pending_ast
-       lock    
-       btrl    %eax, CNAME(resched_cpus)
-       jnc     2f
-       orl     $AST_PENDING+AST_RESCHED,PCPU(astpending)
-2:             
-       MEXITCOUNT
-       jmp     doreti
-1:
-       /* We are already in the process of delivering an ast for this CPU */
-       POP_FRAME
-       iret                    
-
-
-/*
- *      Executed by a CPU when it receives an XFORWARD_IRQ IPI.
- */
-
-       .text
-       SUPERALIGN_TEXT
-       .globl Xforward_irq
-Xforward_irq:
-       PUSH_FRAME
-
-       movl    $0, lapic_eoi           /* End Of Interrupt to APIC */
-
-       FAKE_MCOUNT(13*4(%esp))
-
-       call    try_mplock
-       testl   %eax,%eax               /* Did we get the lock ? */
-       jz  1f                          /* No */
-
-       incl    PCPU(cnt)+V_FORWARDED_HITS
-       
-       movl    PCPU(curthread), %eax
-       pushl   TD_CPL(%eax)            /* cpl restored by doreti */
-
-       incl    PCPU(intr_nesting_level)
-       sti
-       
-       MEXITCOUNT
-       jmp     doreti                  /* Handle forwarded interrupt */
-1:
-       incl    PCPU(cnt)+V_FORWARDED_MISSES
-       call    forward_irq     /* Oops, we've lost the isr lock */
-       MEXITCOUNT
-       POP_FRAME
-       iret
-3:     
-       call    rel_mplock
-       MEXITCOUNT
-       POP_FRAME
-       iret
-
-/*
- * 
- */
-forward_irq:
-       MCOUNT
-       cmpl    $0,invltlb_ok
-       jz      4f
-
-       cmpl    $0, CNAME(forward_irq_enabled)
-       jz      4f
-
-       movl    mp_lock,%eax
-       cmpl    $MP_FREE_LOCK,%eax
-       jne     1f
-       movl    $0, %eax                /* Pick CPU #0 if noone has lock */
-1:
-       shrl    $24,%eax
-       movl    cpu_num_to_apic_id(,%eax,4),%ecx
-       shll    $24,%ecx
-       movl    lapic_icr_hi, %eax
-       andl    $~APIC_ID_MASK, %eax
-       orl     %ecx, %eax
-       movl    %eax, lapic_icr_hi
-
-2:
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_DELSTAT_MASK,%eax
-       jnz     2b
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_RESV2_MASK, %eax
-       orl     $(APIC_DEST_DESTFLD|APIC_DELMODE_FIXED|XFORWARD_IRQ_OFFSET), %eax
-       movl    %eax, lapic_icr_lo
-3:
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_DELSTAT_MASK,%eax
-       jnz     3b
-4:             
-       ret
-
 /*
  * Executed by a CPU when it receives an Xcpustop IPI from another CPU,
  *
@@ -804,15 +677,7 @@ started_cpus:
 checkstate_probed_cpus:
        .long   0       
 #endif /* BETTER_CLOCK */
-       .globl checkstate_need_ast
-checkstate_need_ast:
-       .long   0
-checkstate_pending_ast:
-       .long   0
-       .globl CNAME(resched_cpus)
        .globl CNAME(cpustop_restartfunc)
-CNAME(resched_cpus):
-       .long 0
 CNAME(cpustop_restartfunc):
        .long 0
                
index 95cab68..be914fd 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     from: @(#)isa.c 7.2 (Berkeley) 5/13/91
  * $FreeBSD: src/sys/i386/isa/intr_machdep.c,v 1.29.2.5 2001/10/14 06:54:27 luigi Exp $
- * $DragonFly: src/sys/i386/isa/Attic/intr_machdep.c,v 1.7 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/i386/isa/Attic/intr_machdep.c,v 1.8 2003/07/11 01:23:23 dillon Exp $
  */
 /*
  * This file contains an aggregated module marked:
@@ -86,6 +86,7 @@
 #ifdef APIC_IO
 #include <machine/clock.h>
 #endif
+#include <machine/cpu.h>
 
 #include "mca.h"
 #if NMCA > 0
@@ -712,6 +713,9 @@ update_masks(intrmask_t *maskptr, int irq)
  * check relative thread priorities for us as long as we properly pass through
  * critpri.
  *
+ * The interrupt thread has already been put on the run queue, so if we cannot
+ * preempt we should force a reschedule.
+ *
  * YYY needs work.  At the moment the handler is run inside a critical
  * section so only the preemption cpl check is used.
  */
@@ -722,6 +726,8 @@ cpu_intr_preempt(struct thread *td, int critpri)
 
        if ((curthread->td_cpl & (1 << info->irq)) == 0)
                lwkt_preempt(td, critpri);
+       else
+               need_resched();
 }
 
 static int
index 172e234..de6a650 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/isa/intr_machdep.h,v 1.19.2.2 2001/10/14 20:05:50 luigi Exp $
- * $DragonFly: src/sys/i386/isa/Attic/intr_machdep.h,v 1.5 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/i386/isa/Attic/intr_machdep.h,v 1.6 2003/07/11 01:23:23 dillon Exp $
  */
 
 #ifndef _I386_ISA_INTR_MACHDEP_H_
 /* IPIQ rendezvous */
 #define XIPIQ_OFFSET           (ICU_OFFSET + 115)
 
-/* IPI to generate an additional software trap at the target CPU */
-#define XCPUAST_OFFSET         (ICU_OFFSET +  48)
-
-/* IPI to signal the CPU holding the ISR lock that another IRQ has appeared */
-#define XFORWARD_IRQ_OFFSET    (ICU_OFFSET +  49)
-
 /* IPI to signal CPUs to stop and wait for another CPU to restart them */
 #define XCPUSTOP_OFFSET                (ICU_OFFSET + 128)
 
index aa11f82..c1d5705 100644 (file)
@@ -24,7 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_intr.c,v 1.24.2.1 2001/10/14 20:05:50 luigi Exp $
- * $DragonFly: src/sys/kern/kern_intr.c,v 1.8 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_intr.c,v 1.9 2003/07/11 01:23:24 dillon Exp $
  *
  */
 
@@ -205,9 +205,7 @@ sched_ithd(int intr)
                irunning[intr] = 1;
                lwkt_schedule(td);      /* preemption handled internally */
            } else {
-               crit_enter();
                lwkt_send_ipiq(td->td_cpu, sched_ithd_remote, (void *)intr);
-               crit_exit();
            }
        }
     } else {
index d1244f6..38f3e79 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_sig.c  8.7 (Berkeley) 4/18/94
  * $FreeBSD: src/sys/kern/kern_sig.c,v 1.72.2.17 2003/05/16 16:34:34 obrien Exp $
- * $DragonFly: src/sys/kern/kern_sig.c,v 1.8 2003/06/30 19:50:31 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_sig.c,v 1.9 2003/07/11 01:23:24 dillon Exp $
  */
 
 #include "opt_compat.h"
@@ -83,6 +83,9 @@ static int killpg1    __P((int sig, int pgid, int all));
 static int sig_ffs     __P((sigset_t *set));
 static int sigprop     __P((int sig));
 static void stop       __P((struct proc *));
+#ifdef SMP
+static void signotify_remote(void *arg);
+#endif
 
 static int     filt_sigattach(struct knote *kn);
 static void    filt_sigdetach(struct knote *kn);
@@ -969,13 +972,14 @@ trapsignal(p, sig, code)
  *
  * Other ignored signals are discarded immediately.
  */
+
 void
 psignal(p, sig)
        register struct proc *p;
        register int sig;
 {
-       register int s, prop;
-       register sig_t action;
+       int s, prop;
+       sig_t action;
 
        if (sig > _SIG_MAXSIG || sig <= 0) {
                printf("psignal: signal %d\n", sig);
@@ -1152,12 +1156,22 @@ psignal(p, sig)
                 * SRUN, SIDL, SZOMB do nothing with the signal,
                 * other than kicking ourselves if we are running.
                 * It will either never be noticed, or noticed very soon.
+                *
+                * For SMP we may have to forward the request to another cpu.
+                * YYY the MP lock prevents the target process from moving
+                * to another cpu, see kern/kern_switch.c
                 */
-               if (p == curproc)
-                       signotify(p);
 #ifdef SMP
-               else if (p->p_stat == SRUN)
-                       forward_signal(p);
+               if (p == lwkt_preempted_proc()) {
+                       signotify(p);
+               } else {
+                       int cpuid = p->p_thread->td_cpu;
+                       if (cpuid != mycpu->gd_cpuid)
+                               lwkt_send_ipiq(cpuid, signotify_remote, p);
+               }
+#else
+               if (p == lwkt_preempted_proc())
+                       signotify(p);
 #endif
                goto out;
        }
@@ -1168,6 +1182,23 @@ out:
        splx(s);
 }
 
+#ifdef SMP
+
+/*
+ * This function is called via an IPI.  We will be in a critical section but
+ * the MP lock will NOT be held.  Also note that by the time the ipi message
+ * gets to us the process 'p' (arg) may no longer be scheduled or even valid.
+ */
+static void
+signotify_remote(void *arg)
+{
+       struct proc *p = arg;
+       if (p == lwkt_preempted_proc())
+               signotify(p);
+}
+
+#endif
+
 /*
  * If the current process has received a signal (should be caught or cause
  * termination, should interrupt current syscall), return the signal number.
index 36535a8..5a66081 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_switch.c,v 1.3.2.1 2000/05/16 06:58:12 dillon Exp $
- * $DragonFly: src/sys/kern/Attic/kern_switch.c,v 1.6 2003/07/10 18:23:24 dillon Exp $
+ * $DragonFly: src/sys/kern/Attic/kern_switch.c,v 1.7 2003/07/11 01:23:24 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -36,6 +36,7 @@
 #include <sys/rtprio.h>
 #include <sys/thread2.h>
 #include <sys/uio.h>
+#include <sys/sysctl.h>
 #include <machine/ipl.h>
 #include <machine/cpu.h>
 
@@ -63,10 +64,12 @@ static struct rq idqueues[NQS];
 static u_int32_t queuebits;
 static u_int32_t rtqueuebits;
 static u_int32_t idqueuebits;
-static u_int32_t curprocmask = -1;
-static u_int32_t rdyprocmask = 0;
+static u_int32_t curprocmask = -1;     /* currently running a user process */
+static u_int32_t rdyprocmask;          /* ready to accept a user process */
 static int      runqcount;
 
+SYSCTL_INT(_debug, OID_AUTO, runqcount, CTLFLAG_RD, &runqcount, 0, "");
+
 /*
  * Initialize the run queues at boot time.
  */
@@ -135,6 +138,7 @@ chooseproc(void)
        p = TAILQ_FIRST(q);
        KASSERT(p, ("chooseproc: no proc on busy queue"));
        TAILQ_REMOVE(q, p, p_procq);
+       --runqcount;
        if (TAILQ_EMPTY(q))
                *which &= ~(1 << pri);
        KASSERT((p->p_flag & P_ONRUNQ) != 0, ("not on runq6!"));
@@ -186,6 +190,20 @@ setrunqueue(struct proc *p)
                return;
        }
 
+       /*
+        * If our cpu is available to run a user process we short cut and
+        * just do it.
+        */
+       cpuid = mycpu->gd_cpuid;
+       if ((curprocmask & (1 << cpuid)) == 0) {
+               curprocmask |= 1 << cpuid;
+               p->p_flag |= P_CURPROC;
+               lwkt_acquire(p->p_thread);
+               lwkt_schedule(p->p_thread);
+               crit_exit();
+               return;
+       }
+
        /*
         * Otherwise place this process on the userland scheduler's run
         * queue for action.
@@ -216,9 +234,14 @@ setrunqueue(struct proc *p)
         * Wakeup other cpus to schedule the newly available thread.
         * XXX doesn't really have to be in a critical section.
         * We own giant after all.
+        *
+        * We use rdyprocmask to avoid unnecessarily waking up the scheduler
+        * thread when it is already running.
         */
        if ((mask = ~curprocmask & rdyprocmask & mycpu->gd_other_cpus) != 0) {
                int count = runqcount;
+               if (!mask)
+                       printf("PROC %d nocpu to schedule it on\n", p->p_pid);
                while (mask && count) {
                        cpuid = bsfl(mask);
                        KKASSERT((curprocmask & (1 << cpuid)) == 0);
@@ -315,6 +338,7 @@ release_curproc(struct proc *p)
                        }
                        rel_mplock();
                } else {
+                       KKASSERT(0);
                        curprocmask &= ~(1 << cpuid);
                        if (rdyprocmask & (1 << cpuid))
                                lwkt_schedule(&globaldata_find(cpuid)->gd_schedthread);
@@ -442,8 +466,8 @@ sched_thread(void *dummy)
     for (;;) {
        struct proc *np;
 
-       rdyprocmask |= cpumask;
        lwkt_deschedule_self();         /* interlock */
+       rdyprocmask |= cpumask;
        crit_enter();
        if ((curprocmask & cpumask) == 0 && (np = chooseproc()) != NULL) {
            curprocmask |= cpumask;
index d3ac9f9..b55adad 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_synch.c        8.9 (Berkeley) 5/19/95
  * $FreeBSD: src/sys/kern/kern_synch.c,v 1.87.2.6 2002/10/13 07:29:53 kbyanc Exp $
- * $DragonFly: src/sys/kern/kern_synch.c,v 1.16 2003/07/10 04:47:54 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_synch.c,v 1.17 2003/07/11 01:23:24 dillon Exp $
  */
 
 #include "opt_ktrace.h"
@@ -151,23 +151,36 @@ roundrobin_interval(void)
 /*
  * Force switch among equal priority processes every 100ms.
  */
-/* ARGSUSED */
+#ifdef SMP
+
 static void
-roundrobin(arg)
-       void *arg;
+roundrobin_remote(void *arg)
 {
        struct proc *p = lwkt_preempted_proc();
-#ifdef SMP
        if (p == NULL || RTP_PRIO_NEED_RR(p->p_rtprio.type))
                need_resched();
-       forward_roundrobin();
-#else 
+}
+
+#endif
+
+static void
+roundrobin(void *arg)
+{
+       struct proc *p = lwkt_preempted_proc();
        if (p == NULL || RTP_PRIO_NEED_RR(p->p_rtprio.type))
-               need_resched();
+               need_resched();
+#ifdef SMP
+       lwkt_send_ipiq_mask(mycpu->gd_other_cpus, roundrobin_remote, NULL);
 #endif
        timeout(roundrobin, NULL, sched_quantum);
 }
 
+void
+resched_cpus(u_int32_t mask)
+{
+       lwkt_send_ipiq_mask(mask, roundrobin_remote, NULL);
+}
+
 /*
  * Constants for digital decay and forget:
  *     90% of (p_estcpu) usage in 5 * loadav time
index 761c40f..de55930 100644 (file)
@@ -28,7 +28,7 @@
  *     to use a critical section to avoid problems.  Foreign thread 
  *     scheduling is queued via (async) IPIs.
  *
- * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.19 2003/07/10 18:23:24 dillon Exp $
+ * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.20 2003/07/11 01:23:24 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -309,6 +309,18 @@ lwkt_switch(void)
        panic("lwkt_switch: cannot switch from within an interrupt, yet\n");
     }
 
+    /*
+     * Passive release (used to transition from user to kernel mode
+     * when we block or switch rather then when we enter the kernel).
+     * This function is NOT called if we are switching into a preemption
+     * or returning from a preemption.  Typically this causes us to lose
+     * our P_CURPROC designation (if we have one) and become a true LWKT
+     * thread, and may also hand P_CURPROC to another process and schedule
+     * its thread.
+     */
+    if (td->td_release)
+           td->td_release(td);
+
     crit_enter();
     ++switch_count;
 
@@ -404,15 +416,6 @@ again:
     KASSERT(ntd->td_pri >= TDPRI_CRIT,
        ("priority problem in lwkt_switch %d %d", td->td_pri, ntd->td_pri));
 
-    /*
-     * Passive release (used to transition from user to kernel mode
-     * when we block or switch rather then when we enter the kernel).
-     * This function is NOT called if we are switching into a preemption
-     * or returning from a preemption.
-     */
-    if (td->td_release)
-           td->td_release(td);
-
     /*
      * Do the actual switch.  If the new target does not need the MP lock
      * and we are holding it, release the MP lock.  If the new target requires
@@ -433,6 +436,21 @@ again:
     crit_exit();
 }
 
+/*
+ * Switch if another thread has a higher priority.  Do not switch to other
+ * threads at the same priority.
+ */
+void
+lwkt_maybe_switch()
+{
+    struct globaldata *gd = mycpu;
+    struct thread *td = gd->gd_curthread;
+
+    if ((td->td_pri & TDPRI_MASK) < bsrl(gd->gd_runqmask)) {
+       lwkt_switch();
+    }
+}
+
 /*
  * Request that the target thread preempt the current thread.  Preemption
  * only works under a specific set of conditions:
@@ -484,13 +502,13 @@ lwkt_preempt(thread_t ntd, int critpri)
      */
     KASSERT(ntd->td_pri >= TDPRI_CRIT, ("BADCRIT0 %d", ntd->td_pri));
 
+    need_resched();
     if (!_lwkt_wantresched(ntd, td)) {
        ++preempt_miss;
        return;
     }
     if ((td->td_pri & ~TDPRI_MASK) > critpri) {
        ++preempt_miss;
-       need_resched();
        return;
     }
 #ifdef SMP
@@ -501,12 +519,10 @@ lwkt_preempt(thread_t ntd, int critpri)
 #endif
     if (td == ntd || ((td->td_flags | ntd->td_flags) & TDF_PREEMPT_LOCK)) {
        ++preempt_weird;
-       need_resched();
        return;
     }
     if (ntd->td_preempted) {
        ++preempt_hit;
-       need_resched();
        return;
     }
 #ifdef SMP
@@ -525,7 +541,6 @@ lwkt_preempt(thread_t ntd, int critpri)
     if (mpheld == 0 && ntd->td_mpcount && !cpu_try_mplock()) {
        ntd->td_mpcount -= td->td_mpcount;
        ++preempt_miss;
-       need_resched();
        return;
     }
 #endif
@@ -724,10 +739,12 @@ void
 lwkt_acquire(thread_t td)
 {
     struct globaldata *gd;
+    int ocpu;
 
     gd = td->td_gd;
     KKASSERT((td->td_flags & TDF_RUNQ) == 0);
     if (gd != mycpu) {
+       ocpu = td->td_cpu;
        crit_enter();
        TAILQ_REMOVE(&gd->gd_tdallq, td, td_allq);      /* protected by BGL */
        gd = mycpu;
@@ -1061,10 +1078,12 @@ lwkt_regettoken(lwkt_token_t tok)
            req.tok = tok;
            dcpu = (volatile int)tok->t_cpu;
            KKASSERT(dcpu >= 0 && dcpu < ncpus);
-           printf("REQT%d ", dcpu);
+           if (token_debug)
+               printf("REQT%d ", dcpu);
            seq = lwkt_send_ipiq(dcpu, lwkt_gettoken_remote, &req);
            lwkt_wait_ipiq(dcpu, seq);
-           printf("REQR%d ", tok->t_cpu);
+           if (token_debug)
+               printf("REQR%d ", tok->t_cpu);
        }
 #endif
        ++tok->t_gen;
@@ -1223,6 +1242,7 @@ lwkt_send_ipiq(int dcpu, ipifunc_t func, void *arg)
        func(arg);
        return(0);
     } 
+    crit_enter();
     ++gd->gd_intr_nesting_level;
 #ifdef INVARIANTS
     if (gd->gd_intr_nesting_level > 20)
@@ -1232,29 +1252,49 @@ lwkt_send_ipiq(int dcpu, ipifunc_t func, void *arg)
     KKASSERT(dcpu >= 0 && dcpu < ncpus);
     ++ipiq_count;
     ip = &gd->gd_ipiq[dcpu];
+
+    /*
+     * We always drain before the FIFO becomes full so it should never
+     * become full.  We need to leave enough entries to deal with 
+     * reentrancy.
+     */
+    KKASSERT(ip->ip_windex - ip->ip_rindex != MAXCPUFIFO);
+    windex = ip->ip_windex & MAXCPUFIFO_MASK;
+    ip->ip_func[windex] = func;
+    ip->ip_arg[windex] = arg;
+    /* YYY memory barrier */
+    ++ip->ip_windex;
     if (ip->ip_windex - ip->ip_rindex > MAXCPUFIFO / 2) {
        unsigned int eflags = read_eflags();
-       printf("SEND_IPIQ FIFO FULL\n");
        cpu_enable_intr();
        ++ipiq_fifofull;
-       while (ip->ip_windex - ip->ip_rindex > MAXCPUFIFO / 2) {
+       while (ip->ip_windex - ip->ip_rindex > MAXCPUFIFO / 4) {
            KKASSERT(ip->ip_windex - ip->ip_rindex != MAXCPUFIFO - 1);
            lwkt_process_ipiq();
        }
-       printf("SEND_IPIQ FIFO GOOD\n");
        write_eflags(eflags);
     }
-    KKASSERT(ip->ip_windex - ip->ip_rindex != MAXCPUFIFO - 1);
-    windex = ip->ip_windex & MAXCPUFIFO_MASK;
-    ip->ip_func[windex] = func;
-    ip->ip_arg[windex] = arg;
-    /* YYY memory barrier */
-    ++ip->ip_windex;
     --gd->gd_intr_nesting_level;
     cpu_send_ipiq(dcpu);       /* issues memory barrier if appropriate */
+    crit_exit();
     return(ip->ip_windex);
 }
 
+/*
+ * Send a message to several target cpus.  Typically used for scheduling.
+ */
+void
+lwkt_send_ipiq_mask(u_int32_t mask, ipifunc_t func, void *arg)
+{
+    int cpuid;
+
+    while (mask) {
+           cpuid = bsfl(mask);
+           lwkt_send_ipiq(cpuid, func, arg);
+           mask &= ~(1 << cpuid);
+    }
+}
+
 /*
  * Wait for the remote cpu to finish processing a function.
  *
@@ -1275,16 +1315,13 @@ lwkt_wait_ipiq(int dcpu, int seq)
     if (dcpu != mycpu->gd_cpuid) {
        KKASSERT(dcpu >= 0 && dcpu < ncpus);
        ip = &mycpu->gd_ipiq[dcpu];
-       if ((int)(ip->ip_rindex - seq) < 0) {
+       if ((int)(ip->ip_xindex - seq) < 0) {
            unsigned int eflags = read_eflags();
            cpu_enable_intr();
-           while ((int)(ip->ip_rindex - seq) < 0) {
+           while ((int)(ip->ip_xindex - seq) < 0) {
                lwkt_process_ipiq();
-#if 0
-               lwkt_switch();  /* YYY fixme */
-#endif
                if (--maxc == 0)
-                       printf("LWKT_WAIT_IPIQ WARNING! %d wait %d (%d)\n", mycpu->gd_cpuid, dcpu, ip->ip_rindex - seq);
+                       printf("LWKT_WAIT_IPIQ WARNING! %d wait %d (%d)\n", mycpu->gd_cpuid, dcpu, ip->ip_xindex - seq);
                if (maxc < -1000000)
                        panic("LWKT_WAIT_IPIQ");
            }
@@ -1296,7 +1333,8 @@ lwkt_wait_ipiq(int dcpu, int seq)
 /*
  * Called from IPI interrupt (like a fast interrupt), which has placed
  * us in a critical section.  The MP lock may or may not be held.
- * May also be called from doreti or splz.
+ * May also be called from doreti or splz, or be reentrantly called
+ * indirectly through the ip_func[] we run.
  */
 void
 lwkt_process_ipiq(void)
@@ -1314,10 +1352,18 @@ lwkt_process_ipiq(void)
        if (ip == NULL)
            continue;
        ip = &ip[cpuid];
+
+       /*
+        * Note: xindex is only updated after we are sure the function has
+        * finished execution.  Beware lwkt_process_ipiq() reentrancy!  The
+        * function may send an IPI which may block/drain.
+        */
        while (ip->ip_rindex != ip->ip_windex) {
            ri = ip->ip_rindex & MAXCPUFIFO_MASK;
-           ip->ip_func[ri](ip->ip_arg[ri]);
            ++ip->ip_rindex;
+           ip->ip_func[ri](ip->ip_arg[ri]);
+           /* YYY memory barrier */
+           ip->ip_xindex = ip->ip_rindex;
        }
     }
 }
index aede11d..17a2751 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     from: vector.s, 386BSD 0.1 unknown origin
  * $FreeBSD: src/sys/i386/isa/apic_vector.s,v 1.47.2.5 2001/09/01 22:33:38 tegge Exp $
- * $DragonFly: src/sys/platform/pc32/apic/apic_vector.s,v 1.9 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/apic/apic_vector.s,v 1.10 2003/07/11 01:23:23 dillon Exp $
  */
 
 
@@ -421,133 +421,6 @@ Xcpucheckstate:
 #endif /* BETTER_CLOCK */
 #endif
 
-/*
- * Executed by a CPU when it receives an Xcpuast IPI from another CPU,
- *
- *  - Signals its receipt by clearing bit cpuid in checkstate_need_ast.
- *  - MP safe in regards to setting AST_PENDING because doreti is in
- *    a cli mode when it checks.
- */
-
-       .text
-       SUPERALIGN_TEXT
-       .globl Xcpuast
-Xcpuast:
-       PUSH_FRAME
-
-       movl    PCPU(cpuid), %eax
-       lock                            /* checkstate_need_ast &= ~(1<<id) */
-       btrl    %eax, checkstate_need_ast
-       movl    $0, lapic_eoi           /* End Of Interrupt to APIC */
-
-       lock
-       btsl    %eax, checkstate_pending_ast
-       jc      1f
-
-       FAKE_MCOUNT(13*4(%esp))
-
-       movl    PCPU(curthread), %eax
-       pushl   TD_CPL(%eax)            /* cpl restored by doreti */
-
-       orl     $AST_PENDING, PCPU(astpending)  /* XXX */
-       incl    PCPU(intr_nesting_level)
-       sti
-       
-       movl    PCPU(cpuid), %eax
-       lock    
-       btrl    %eax, checkstate_pending_ast
-       lock    
-       btrl    %eax, CNAME(resched_cpus)
-       jnc     2f
-       orl     $AST_PENDING+AST_RESCHED,PCPU(astpending)
-2:             
-       MEXITCOUNT
-       jmp     doreti
-1:
-       /* We are already in the process of delivering an ast for this CPU */
-       POP_FRAME
-       iret                    
-
-
-/*
- *      Executed by a CPU when it receives an XFORWARD_IRQ IPI.
- */
-
-       .text
-       SUPERALIGN_TEXT
-       .globl Xforward_irq
-Xforward_irq:
-       PUSH_FRAME
-
-       movl    $0, lapic_eoi           /* End Of Interrupt to APIC */
-
-       FAKE_MCOUNT(13*4(%esp))
-
-       call    try_mplock
-       testl   %eax,%eax               /* Did we get the lock ? */
-       jz  1f                          /* No */
-
-       incl    PCPU(cnt)+V_FORWARDED_HITS
-       
-       movl    PCPU(curthread), %eax
-       pushl   TD_CPL(%eax)            /* cpl restored by doreti */
-
-       incl    PCPU(intr_nesting_level)
-       sti
-       
-       MEXITCOUNT
-       jmp     doreti                  /* Handle forwarded interrupt */
-1:
-       incl    PCPU(cnt)+V_FORWARDED_MISSES
-       call    forward_irq     /* Oops, we've lost the isr lock */
-       MEXITCOUNT
-       POP_FRAME
-       iret
-3:     
-       call    rel_mplock
-       MEXITCOUNT
-       POP_FRAME
-       iret
-
-/*
- * 
- */
-forward_irq:
-       MCOUNT
-       cmpl    $0,invltlb_ok
-       jz      4f
-
-       cmpl    $0, CNAME(forward_irq_enabled)
-       jz      4f
-
-       movl    mp_lock,%eax
-       cmpl    $MP_FREE_LOCK,%eax
-       jne     1f
-       movl    $0, %eax                /* Pick CPU #0 if noone has lock */
-1:
-       shrl    $24,%eax
-       movl    cpu_num_to_apic_id(,%eax,4),%ecx
-       shll    $24,%ecx
-       movl    lapic_icr_hi, %eax
-       andl    $~APIC_ID_MASK, %eax
-       orl     %ecx, %eax
-       movl    %eax, lapic_icr_hi
-
-2:
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_DELSTAT_MASK,%eax
-       jnz     2b
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_RESV2_MASK, %eax
-       orl     $(APIC_DEST_DESTFLD|APIC_DELMODE_FIXED|XFORWARD_IRQ_OFFSET), %eax
-       movl    %eax, lapic_icr_lo
-3:
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_DELSTAT_MASK,%eax
-       jnz     3b
-4:             
-       ret
-
 /*
  * Executed by a CPU when it receives an Xcpustop IPI from another CPU,
  *
@@ -804,15 +677,7 @@ started_cpus:
 checkstate_probed_cpus:
        .long   0       
 #endif /* BETTER_CLOCK */
-       .globl checkstate_need_ast
-checkstate_need_ast:
-       .long   0
-checkstate_pending_ast:
-       .long   0
-       .globl CNAME(resched_cpus)
        .globl CNAME(cpustop_restartfunc)
-CNAME(resched_cpus):
-       .long 0
 CNAME(cpustop_restartfunc):
        .long 0
                
index bee55f9..9b3a387 100644 (file)
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $
- * $DragonFly: src/sys/platform/pc32/i386/mp_machdep.c,v 1.11 2003/07/10 04:47:53 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/mp_machdep.c,v 1.12 2003/07/11 01:23:21 dillon Exp $
  */
 
 #include "opt_cpu.h"
@@ -597,6 +597,7 @@ mp_enable(u_int boot_addr)
        setidt(XRENDEZVOUS_OFFSET, Xrendezvous,
               SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
 
+#if 0
        /* install an inter-CPU IPI for forcing an additional software trap */
        setidt(XCPUAST_OFFSET, Xcpuast,
               SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
@@ -604,6 +605,7 @@ mp_enable(u_int boot_addr)
        /* install an inter-CPU IPI for interrupt forwarding */
        setidt(XFORWARD_IRQ_OFFSET, Xforward_irq,
               SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+#endif
 
        /* install an inter-CPU IPI for CPU stop/restart */
        setidt(XCPUSTOP_OFFSET, Xcpustop,
@@ -2661,22 +2663,8 @@ forward_statclock(int pscnt)
                        continue;
                forwarded_statclock(id, pscnt, &map);
        }
-       if (map != 0) {
-               checkstate_need_ast |= map;
-               selected_apic_ipi(map, XCPUAST_OFFSET, APIC_DELMODE_FIXED);
-               i = 0;
-               while ((checkstate_need_ast & map) != 0) {
-                       /* spin */
-                       i++;
-                       if (i > 100000) { 
-#ifdef BETTER_CLOCK_DIAGNOSTIC
-                               printf("forward_statclock: dropped ast 0x%x\n",
-                                      checkstate_need_ast & map);
-#endif
-                               break;
-                       }
-               }
-       }
+       if (map != 0)
+               resched_cpus(map);
 }
 
 void 
@@ -2759,111 +2747,12 @@ forward_hardclock(int pscnt)
                }
 #endif
        }
-       if (map != 0) {
-               checkstate_need_ast |= map;
-               selected_apic_ipi(map, XCPUAST_OFFSET, APIC_DELMODE_FIXED);
-               i = 0;
-               while ((checkstate_need_ast & map) != 0) {
-                       /* spin */
-                       i++;
-                       if (i > 100000) { 
-#ifdef BETTER_CLOCK_DIAGNOSTIC
-                               printf("forward_hardclock: dropped ast 0x%x\n",
-                                      checkstate_need_ast & map);
-#endif
-                               break;
-                       }
-               }
-       }
+       if (map != 0) 
+               resched_cpus(map);
 }
 
 #endif /* BETTER_CLOCK */
 
-void 
-forward_signal(struct proc *p)
-{
-       /* YYY forward_signal */
-#if 0
-       int map;
-       int id;
-       int i;
-
-       /* Kludge. We don't yet have separate locks for the interrupts
-        * and the kernel. This means that we cannot let the other processors
-        * handle complex interrupts while inhibiting them from entering
-        * the kernel in a non-interrupt context.
-        *
-        * What we can do, without changing the locking mechanisms yet,
-        * is letting the other processors handle a very simple interrupt
-        * (wich determines the processor states), and do the main
-        * work ourself.
-        */
-
-       if (!smp_started || !invltlb_ok || cold || panicstr)
-               return;
-       if (!forward_signal_enabled)
-               return;
-       while (1) {
-               if (p->p_stat != SRUN)
-                       return;
-               id = p->p_oncpu;
-               if (id == 0xff)
-                       return;
-               map = (1<<id);
-               checkstate_need_ast |= map;
-               selected_apic_ipi(map, XCPUAST_OFFSET, APIC_DELMODE_FIXED);
-               i = 0;
-               while ((checkstate_need_ast & map) != 0) {
-                       /* spin */
-                       i++;
-                       if (i > 100000) { 
-#if 0
-                               printf("forward_signal: dropped ast 0x%x\n",
-                                      checkstate_need_ast & map);
-#endif
-                               break;
-                       }
-               }
-               if (id == p->p_oncpu)
-                       return;
-       }
-#endif
-}
-
-void
-forward_roundrobin(void)
-{
-       /* YYY forward_roundrobin */
-#if 0
-       u_int map;
-       int i;
-
-       if (!smp_started || !invltlb_ok || cold || panicstr)
-               return;
-       if (!forward_roundrobin_enabled)
-               return;
-       resched_cpus |= mycpu->gd_other_cpus;
-       map = mycpu->gd_other_cpus & ~stopped_cpus ;
-#if 1
-       selected_apic_ipi(map, XCPUAST_OFFSET, APIC_DELMODE_FIXED);
-#else
-       (void) all_but_self_ipi(XCPUAST_OFFSET);
-#endif
-       i = 0;
-       while ((checkstate_need_ast & map) != 0) {
-               /* spin */
-               i++;
-               if (i > 100000) {
-#if 0
-                       printf("forward_roundrobin: dropped ast 0x%x\n",
-                              checkstate_need_ast & map);
-#endif
-                       break;
-               }
-       }
-#endif
-}
-
 #ifdef APIC_INTR_REORDER
 /*
  *     Maintain mapping from softintr vector to isr bit in local apic.
index 41d012b..5be0776 100644 (file)
@@ -36,7 +36,7 @@
  *
  *     from: @(#)trap.c        7.4 (Berkeley) 5/13/91
  * $FreeBSD: src/sys/i386/i386/trap.c,v 1.147.2.11 2003/02/27 19:09:59 luoqi Exp $
- * $DragonFly: src/sys/platform/pc32/i386/trap.c,v 1.20 2003/07/10 04:47:53 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/trap.c,v 1.21 2003/07/11 01:23:21 dillon Exp $
  */
 
 /*
@@ -200,6 +200,10 @@ userexit(struct proc *p)
         * If we did not have to release we should already be P_CURPROC.  If
         * we did have to release we must acquire P_CURPROC again and then
         * restore our priority for user return.
+        *
+        * Lowering our priority may make other higher priority threads
+        * runnable. lwkt_setpri_self() does not switch away, so call
+        * lwkt_maybe_switch() to deal with it.
         */
        if (td->td_release) {
                td->td_release = NULL;
@@ -218,6 +222,7 @@ userexit(struct proc *p)
                        lwkt_setpri_self(TDPRI_USER_NORM);
                        break;
                }
+               lwkt_maybe_switch();
        }
 }
 
@@ -235,18 +240,17 @@ userret(struct proc *p, struct trapframe *frame, u_quad_t oticks)
        }
 
        /*
-        * If a reschedule has been requested we lwkt_switch().  The
-        * lwkt_switch() will ensure that our current process is released
-        * (see the use of td_release) as well as ensure that any pending
-        * LWKTs get run before we get cpu back.
-        *
-        * YYY though of doreti detects that we were in a user context
-        * it should really just call lwkt_switch()!  and are re-acquisition 
-        * of the current process below will handle userland scheduling
-        * priorities.
+        * If a reschedule has been requested then the easiest solution
+        * is to run our passive release function which will shift our
+        * P_CURPROC designation to another user process.  We don't actually
+        * switch here because that would be a waste of cycles (the newly 
+        * scheduled user process would just switch back to us since we are
+        * running at a kernel priority).  Instead we fall through and will
+        * switch away when we attempt to reacquire our P_CURPROC designation.
         */
        if (resched_wanted()) {
-               lwkt_switch();
+               if (curthread->td_release)
+                       passive_release(curthread);
        }
 
        /*
index f21735b..5a4af7a 100644 (file)
@@ -7,7 +7,7 @@
  * ----------------------------------------------------------------------------
  *
  * $FreeBSD: src/sys/i386/include/smp.h,v 1.50.2.5 2001/02/13 22:32:45 tegge Exp $
- * $DragonFly: src/sys/platform/pc32/include/smp.h,v 1.4 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/include/smp.h,v 1.5 2003/07/11 01:23:23 dillon Exp $
  *
  */
 
@@ -52,8 +52,6 @@ extern volatile u_int         stopped_cpus;
 extern volatile u_int          started_cpus;
 
 extern volatile u_int          checkstate_probed_cpus;
-extern volatile u_int          checkstate_need_ast;
-extern volatile u_int          resched_cpus;
 extern void (*cpustop_restartfunc) __P((void));
 
 /* functions in apic_ipl.s */
index f966475..9e68d1d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     from: vector.s, 386BSD 0.1 unknown origin
  * $FreeBSD: src/sys/i386/isa/apic_vector.s,v 1.47.2.5 2001/09/01 22:33:38 tegge Exp $
- * $DragonFly: src/sys/platform/pc32/isa/Attic/apic_vector.s,v 1.9 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/isa/Attic/apic_vector.s,v 1.10 2003/07/11 01:23:23 dillon Exp $
  */
 
 
@@ -421,133 +421,6 @@ Xcpucheckstate:
 #endif /* BETTER_CLOCK */
 #endif
 
-/*
- * Executed by a CPU when it receives an Xcpuast IPI from another CPU,
- *
- *  - Signals its receipt by clearing bit cpuid in checkstate_need_ast.
- *  - MP safe in regards to setting AST_PENDING because doreti is in
- *    a cli mode when it checks.
- */
-
-       .text
-       SUPERALIGN_TEXT
-       .globl Xcpuast
-Xcpuast:
-       PUSH_FRAME
-
-       movl    PCPU(cpuid), %eax
-       lock                            /* checkstate_need_ast &= ~(1<<id) */
-       btrl    %eax, checkstate_need_ast
-       movl    $0, lapic_eoi           /* End Of Interrupt to APIC */
-
-       lock
-       btsl    %eax, checkstate_pending_ast
-       jc      1f
-
-       FAKE_MCOUNT(13*4(%esp))
-
-       movl    PCPU(curthread), %eax
-       pushl   TD_CPL(%eax)            /* cpl restored by doreti */
-
-       orl     $AST_PENDING, PCPU(astpending)  /* XXX */
-       incl    PCPU(intr_nesting_level)
-       sti
-       
-       movl    PCPU(cpuid), %eax
-       lock    
-       btrl    %eax, checkstate_pending_ast
-       lock    
-       btrl    %eax, CNAME(resched_cpus)
-       jnc     2f
-       orl     $AST_PENDING+AST_RESCHED,PCPU(astpending)
-2:             
-       MEXITCOUNT
-       jmp     doreti
-1:
-       /* We are already in the process of delivering an ast for this CPU */
-       POP_FRAME
-       iret                    
-
-
-/*
- *      Executed by a CPU when it receives an XFORWARD_IRQ IPI.
- */
-
-       .text
-       SUPERALIGN_TEXT
-       .globl Xforward_irq
-Xforward_irq:
-       PUSH_FRAME
-
-       movl    $0, lapic_eoi           /* End Of Interrupt to APIC */
-
-       FAKE_MCOUNT(13*4(%esp))
-
-       call    try_mplock
-       testl   %eax,%eax               /* Did we get the lock ? */
-       jz  1f                          /* No */
-
-       incl    PCPU(cnt)+V_FORWARDED_HITS
-       
-       movl    PCPU(curthread), %eax
-       pushl   TD_CPL(%eax)            /* cpl restored by doreti */
-
-       incl    PCPU(intr_nesting_level)
-       sti
-       
-       MEXITCOUNT
-       jmp     doreti                  /* Handle forwarded interrupt */
-1:
-       incl    PCPU(cnt)+V_FORWARDED_MISSES
-       call    forward_irq     /* Oops, we've lost the isr lock */
-       MEXITCOUNT
-       POP_FRAME
-       iret
-3:     
-       call    rel_mplock
-       MEXITCOUNT
-       POP_FRAME
-       iret
-
-/*
- * 
- */
-forward_irq:
-       MCOUNT
-       cmpl    $0,invltlb_ok
-       jz      4f
-
-       cmpl    $0, CNAME(forward_irq_enabled)
-       jz      4f
-
-       movl    mp_lock,%eax
-       cmpl    $MP_FREE_LOCK,%eax
-       jne     1f
-       movl    $0, %eax                /* Pick CPU #0 if noone has lock */
-1:
-       shrl    $24,%eax
-       movl    cpu_num_to_apic_id(,%eax,4),%ecx
-       shll    $24,%ecx
-       movl    lapic_icr_hi, %eax
-       andl    $~APIC_ID_MASK, %eax
-       orl     %ecx, %eax
-       movl    %eax, lapic_icr_hi
-
-2:
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_DELSTAT_MASK,%eax
-       jnz     2b
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_RESV2_MASK, %eax
-       orl     $(APIC_DEST_DESTFLD|APIC_DELMODE_FIXED|XFORWARD_IRQ_OFFSET), %eax
-       movl    %eax, lapic_icr_lo
-3:
-       movl    lapic_icr_lo, %eax
-       andl    $APIC_DELSTAT_MASK,%eax
-       jnz     3b
-4:             
-       ret
-
 /*
  * Executed by a CPU when it receives an Xcpustop IPI from another CPU,
  *
@@ -804,15 +677,7 @@ started_cpus:
 checkstate_probed_cpus:
        .long   0       
 #endif /* BETTER_CLOCK */
-       .globl checkstate_need_ast
-checkstate_need_ast:
-       .long   0
-checkstate_pending_ast:
-       .long   0
-       .globl CNAME(resched_cpus)
        .globl CNAME(cpustop_restartfunc)
-CNAME(resched_cpus):
-       .long 0
 CNAME(cpustop_restartfunc):
        .long 0
                
index 114c6de..75e163b 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     from: @(#)isa.c 7.2 (Berkeley) 5/13/91
  * $FreeBSD: src/sys/i386/isa/intr_machdep.c,v 1.29.2.5 2001/10/14 06:54:27 luigi Exp $
- * $DragonFly: src/sys/platform/pc32/isa/intr_machdep.c,v 1.7 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/isa/intr_machdep.c,v 1.8 2003/07/11 01:23:23 dillon Exp $
  */
 /*
  * This file contains an aggregated module marked:
@@ -86,6 +86,7 @@
 #ifdef APIC_IO
 #include <machine/clock.h>
 #endif
+#include <machine/cpu.h>
 
 #include "mca.h"
 #if NMCA > 0
@@ -712,6 +713,9 @@ update_masks(intrmask_t *maskptr, int irq)
  * check relative thread priorities for us as long as we properly pass through
  * critpri.
  *
+ * The interrupt thread has already been put on the run queue, so if we cannot
+ * preempt we should force a reschedule.
+ *
  * YYY needs work.  At the moment the handler is run inside a critical
  * section so only the preemption cpl check is used.
  */
@@ -722,6 +726,8 @@ cpu_intr_preempt(struct thread *td, int critpri)
 
        if ((curthread->td_cpl & (1 << info->irq)) == 0)
                lwkt_preempt(td, critpri);
+       else
+               need_resched();
 }
 
 static int
index d4ca6fc..ab7d59b 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/isa/intr_machdep.h,v 1.19.2.2 2001/10/14 20:05:50 luigi Exp $
- * $DragonFly: src/sys/platform/pc32/isa/intr_machdep.h,v 1.5 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/isa/intr_machdep.h,v 1.6 2003/07/11 01:23:23 dillon Exp $
  */
 
 #ifndef _I386_ISA_INTR_MACHDEP_H_
 /* IPIQ rendezvous */
 #define XIPIQ_OFFSET           (ICU_OFFSET + 115)
 
-/* IPI to generate an additional software trap at the target CPU */
-#define XCPUAST_OFFSET         (ICU_OFFSET +  48)
-
-/* IPI to signal the CPU holding the ISR lock that another IRQ has appeared */
-#define XFORWARD_IRQ_OFFSET    (ICU_OFFSET +  49)
-
 /* IPI to signal CPUs to stop and wait for another CPU to restart them */
 #define XCPUSTOP_OFFSET                (ICU_OFFSET + 128)
 
index 35642c6..47f8178 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)proc.h      8.15 (Berkeley) 5/19/95
  * $FreeBSD: src/sys/sys/proc.h,v 1.99.2.9 2003/06/06 20:21:32 tegge Exp $
- * $DragonFly: src/sys/sys/proc.h,v 1.23 2003/07/10 04:47:55 dillon Exp $
+ * $DragonFly: src/sys/sys/proc.h,v 1.24 2003/07/11 01:23:24 dillon Exp $
  */
 
 #ifndef _SYS_PROC_H_
@@ -402,6 +402,7 @@ void        relscurproc(struct proc *curp);
 int    p_trespass __P((struct ucred *cr1, struct ucred *cr2));
 void   resetpriority __P((struct proc *));
 int    roundrobin_interval __P((void));
+void   resched_cpus(u_int32_t mask);
 void   schedclock __P((struct proc *));
 void   setrunnable __P((struct proc *));
 void   clrrunnable __P((struct proc *, int stat));
index 3a1468e..45f6426 100644 (file)
@@ -4,7 +4,7 @@
  *     Implements the architecture independant portion of the LWKT 
  *     subsystem.
  * 
- * $DragonFly: src/sys/sys/thread.h,v 1.21 2003/07/10 04:47:55 dillon Exp $
+ * $DragonFly: src/sys/sys/thread.h,v 1.22 2003/07/11 01:23:24 dillon Exp $
  */
 
 #ifndef _SYS_THREAD_H_
@@ -101,6 +101,7 @@ typedef void (*ipifunc_t)(void *arg);
 
 typedef struct lwkt_ipiq {
     int                ip_rindex;      /* only written by target cpu */
+    int                ip_xindex;      /* writte by target, indicates completion */
     int                ip_windex;      /* only written by source cpu */
     ipifunc_t  ip_func[MAXCPUFIFO];
     void       *ip_arg[MAXCPUFIFO];
@@ -248,6 +249,7 @@ extern void lwkt_free_thread(struct thread *td);
 extern void lwkt_init_wait(struct lwkt_wait *w);
 extern void lwkt_gdinit(struct globaldata *gd);
 extern void lwkt_switch(void);
+extern void lwkt_maybe_switch(void);
 extern void lwkt_preempt(thread_t ntd, int critpri);
 extern void lwkt_schedule(thread_t td);
 extern void lwkt_schedule_self(void);
@@ -275,6 +277,7 @@ extern void lwkt_shunlock(lwkt_rwlock_t lock);
 extern void lwkt_setpri(thread_t td, int pri);
 extern void lwkt_setpri_self(int pri);
 extern int  lwkt_send_ipiq(int dcpu, ipifunc_t func, void *arg);
+extern void lwkt_send_ipiq_mask(u_int32_t mask, ipifunc_t func, void *arg);
 extern void lwkt_wait_ipiq(int dcpu, int seq);
 extern void lwkt_process_ipiq(void);
 extern void crit_panic(void);