Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/alpha Eliminate race conditions in the FP-switch co...



details:   https://anonhg.NetBSD.org/src/rev/b39a57116201
branches:  trunk
changeset: 508793:b39a57116201
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Fri Apr 20 00:10:17 2001 +0000

description:
Eliminate race conditions in the FP-switch code.  MP kernels get
much further on the way to multi-user now.

diffstat:

 sys/arch/alpha/alpha/ipifuncs.c   |   8 +++-
 sys/arch/alpha/alpha/machdep.c    |  73 ++++++++++++++++++++++++++++----------
 sys/arch/alpha/alpha/trap.c       |  23 +++--------
 sys/arch/alpha/alpha/vm_machdep.c |   5 +-
 sys/arch/alpha/include/cpu.h      |   3 +-
 sys/arch/alpha/include/pcb.h      |  25 ++++++++++++-
 6 files changed, 96 insertions(+), 41 deletions(-)

diffs (truncated from 323 to 300 lines):

diff -r dea4b683afaf -r b39a57116201 sys/arch/alpha/alpha/ipifuncs.c
--- a/sys/arch/alpha/alpha/ipifuncs.c   Thu Apr 19 23:37:21 2001 +0000
+++ b/sys/arch/alpha/alpha/ipifuncs.c   Fri Apr 20 00:10:17 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ipifuncs.c,v 1.24 2001/01/19 18:51:17 thorpej Exp $ */
+/* $NetBSD: ipifuncs.c,v 1.25 2001/04/20 00:10:17 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
 
 #include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.24 2001/01/19 18:51:17 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.25 2001/04/20 00:10:17 thorpej Exp $");
 
 /*
  * Interprocessor interrupt handlers.
@@ -293,6 +293,8 @@
 alpha_ipi_synch_fpu(struct cpu_info *ci, struct trapframe *framep)
 {
 
+       if (ci->ci_flags & CPUF_FPUSAVE)
+               return;
        fpusave_cpu(ci, 1);
 }
 
@@ -300,6 +302,8 @@
 alpha_ipi_discard_fpu(struct cpu_info *ci, struct trapframe *framep)
 {
 
+       if (ci->ci_flags & CPUF_FPUSAVE)
+               return;
        fpusave_cpu(ci, 0);
 }
 
diff -r dea4b683afaf -r b39a57116201 sys/arch/alpha/alpha/machdep.c
--- a/sys/arch/alpha/alpha/machdep.c    Thu Apr 19 23:37:21 2001 +0000
+++ b/sys/arch/alpha/alpha/machdep.c    Fri Apr 20 00:10:17 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.234 2001/04/19 17:48:46 thorpej Exp $ */
+/* $NetBSD: machdep.c,v 1.235 2001/04/20 00:10:17 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
@@ -73,7 +73,7 @@
 
 #include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.234 2001/04/19 17:48:46 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.235 2001/04/20 00:10:17 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -663,6 +663,7 @@
            (u_int64_t)proc0paddr + USPACE - sizeof(struct trapframe);
        proc0.p_md.md_tf =
            (struct trapframe *)proc0paddr->u_pcb.pcb_hw.apcb_ksp;
+       simple_lock_init(&proc0paddr->u_pcb.pcb_fpcpu_slock);
 
        /*
         * Initialize the primary CPU's idle PCB to proc0's.  In a
@@ -1794,9 +1795,13 @@
 
        KDASSERT(ci == curcpu());
 
+#if defined(MULTIPROCESSOR)
+       atomic_setbits_ulong(&ci->ci_flags, CPUF_FPUSAVE);
+#endif
+
        p = ci->ci_fpcurproc;
        if (p == NULL)
-               return;
+               goto out;
 
        if (save) {
                alpha_pal_wrfen(1);
@@ -1805,15 +1810,18 @@
 
        alpha_pal_wrfen(0);
 
-#if defined(MULTIPROCESSOR)
-       s = splhigh();
-#endif
+       FPCPU_LOCK(&p->p_addr->u_pcb, s);
+
        p->p_addr->u_pcb.pcb_fpcpu = NULL;
        ci->ci_fpcurproc = NULL;
+
+       FPCPU_UNLOCK(&p->p_addr->u_pcb, s);
+
+ out:
 #if defined(MULTIPROCESSOR)
-       splx(s);
-       alpha_mb();
+       atomic_clearbits_ulong(&ci->ci_flags, CPUF_FPUSAVE);
 #endif
+       return;
 }
 
 /*
@@ -1824,32 +1832,59 @@
 {
        struct cpu_info *ci = curcpu();
        struct cpu_info *oci;
+#if defined(MULTIPROCESSOR)
+       u_long ipi = save ? ALPHA_IPI_SYNCH_FPU : ALPHA_IPI_DISCARD_FPU;
+       int s, spincount, hold_count;
+#endif
 
        KDASSERT(p->p_addr != NULL);
        KDASSERT(p->p_flag & P_INMEM);
 
+       FPCPU_LOCK(&p->p_addr->u_pcb, s);
+
        oci = p->p_addr->u_pcb.pcb_fpcpu;
-       if (oci == NULL)
+       if (oci == NULL) {
+               FPCPU_UNLOCK(&p->p_addr->u_pcb, s);
                return;
+       }
 
 #if defined(MULTIPROCESSOR)
        if (oci == ci) {
-               int s;
                KASSERT(ci->ci_fpcurproc == p);
-               s = splhigh();
+               FPCPU_UNLOCK(&p->p_addr->u_pcb, s);
                fpusave_cpu(ci, save);
-               splx(s);
-       } else {
-               u_long ipi = save ? ALPHA_IPI_SYNCH_FPU :
-                                   ALPHA_IPI_DISCARD_FPU;
+               return;
+       }
+
+       KASSERT(oci->ci_fpcurproc == p);
+       alpha_send_ipi(oci->ci_cpuid, ipi);
+       FPCPU_UNLOCK(&p->p_addr->u_pcb, s);
 
-               KASSERT(oci->ci_fpcurproc == p);
-               do {
-                       alpha_send_ipi(oci->ci_cpuid, ipi);
-               } while (p->p_addr->u_pcb.pcb_fpcpu != NULL);
+       /*
+        * If we're holding the kernel lock, release it before
+        * spinning.
+        *
+        * XXX Why do we have to do this?!  We shouldn't need to!
+        */
+       if (p->p_flag & P_BIGLOCK)
+               hold_count = spinlock_release_all(&kernel_lock);
+
+       spincount = 0;
+       while (p->p_addr->u_pcb.pcb_fpcpu != NULL) {
+               spincount++;
+               delay(1000);    /* XXX */
+               if (spincount > 10000)
+                       panic("fpsave ipi didn't");
        }
+
+       /*
+        * ...and reacquire it.
+        */
+       if (p->p_flag & P_BIGLOCK)
+               spinlock_acquire_count(&kernel_lock, hold_count);
 #else
        KASSERT(ci->ci_fpcurproc == p);
+       FPCPU_UNLOCK(&p->p_addr->u_pcb, s);
        fpusave_cpu(ci, save);
 #endif /* MULTIPROCESSOR */
 }
diff -r dea4b683afaf -r b39a57116201 sys/arch/alpha/alpha/trap.c
--- a/sys/arch/alpha/alpha/trap.c       Thu Apr 19 23:37:21 2001 +0000
+++ b/sys/arch/alpha/alpha/trap.c       Fri Apr 20 00:10:17 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.67 2001/03/15 06:10:33 chs Exp $ */
+/* $NetBSD: trap.c,v 1.68 2001/04/20 00:10:18 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
 
 #include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.67 2001/03/15 06:10:33 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.68 2001/04/20 00:10:18 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -335,10 +335,6 @@
                        int s;
 #endif
 
-#if defined(MULTIPROCESSOR)
-                       /* Block IPIs while we clean house. */
-                       s = splhigh();
-#endif
                        /*
                         * on exit from the kernel, if proc == fpcurproc,
                         * FP is enabled.
@@ -351,9 +347,7 @@
        
                        if (ci->ci_fpcurproc != NULL)
                                fpusave_cpu(ci, 1);
-#if defined(MULTIPROCESSOR)
-                       splx(s);
-#endif
+
                        KDASSERT(ci->ci_fpcurproc == NULL);
 
 #if defined(MULTIPROCESSOR)
@@ -363,15 +357,12 @@
                        KDASSERT(p->p_addr->u_pcb.pcb_fpcpu == NULL);
 #endif
 
-#if defined(MULTIPROCESSOR)
-                       s = splhigh();
-#endif
+                       FPCPU_LOCK(&p->p_addr->u_pcb, s);
+
                        p->p_addr->u_pcb.pcb_fpcpu = ci;
                        ci->ci_fpcurproc = p;
-#if defined(MULTIPROCESSOR)
-                       splx(s);
-                       alpha_mb();
-#endif
+
+                       FPCPU_UNLOCK(&p->p_addr->u_pcb, s);
 
                        alpha_pal_wrfen(1);
                        restorefpstate(&p->p_addr->u_pcb.pcb_fp);
diff -r dea4b683afaf -r b39a57116201 sys/arch/alpha/alpha/vm_machdep.c
--- a/sys/arch/alpha/alpha/vm_machdep.c Thu Apr 19 23:37:21 2001 +0000
+++ b/sys/arch/alpha/alpha/vm_machdep.c Fri Apr 20 00:10:17 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vm_machdep.c,v 1.65 2001/04/10 00:27:00 sommerfeld Exp $ */
+/* $NetBSD: vm_machdep.c,v 1.66 2001/04/20 00:10:18 thorpej Exp $ */
 
 /*
  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -29,7 +29,7 @@
 
 #include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.65 2001/04/10 00:27:00 sommerfeld Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.66 2001/04/20 00:10:18 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -163,6 +163,7 @@
         */
        p2->p_addr->u_pcb = p1->p_addr->u_pcb;
        p2->p_addr->u_pcb.pcb_hw.apcb_usp = alpha_pal_rdusp();
+       simple_lock_init(&p2->p_addr->u_pcb.pcb_fpcpu_slock);
 
        /*
         * Arrange for a non-local goto when the new process
diff -r dea4b683afaf -r b39a57116201 sys/arch/alpha/include/cpu.h
--- a/sys/arch/alpha/include/cpu.h      Thu Apr 19 23:37:21 2001 +0000
+++ b/sys/arch/alpha/include/cpu.h      Fri Apr 20 00:10:17 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.52 2001/02/27 22:00:19 mjacob Exp $ */
+/* $NetBSD: cpu.h,v 1.53 2001/04/20 00:10:18 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
@@ -139,6 +139,7 @@
 #define        CPUF_PRESENT    0x02            /* CPU is present */
 #define        CPUF_RUNNING    0x04            /* CPU is running */
 #define        CPUF_PAUSED     0x08            /* CPU is paused */
+#define        CPUF_FPUSAVE    0x10            /* CPU is currently in fpusave_cpu() */
 
 #if defined(MULTIPROCESSOR)
 extern __volatile u_long cpus_running;
diff -r dea4b683afaf -r b39a57116201 sys/arch/alpha/include/pcb.h
--- a/sys/arch/alpha/include/pcb.h      Thu Apr 19 23:37:21 2001 +0000
+++ b/sys/arch/alpha/include/pcb.h      Fri Apr 20 00:10:17 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pcb.h,v 1.7 2000/08/15 22:16:19 thorpej Exp $ */
+/* $NetBSD: pcb.h,v 1.8 2001/04/20 00:10:18 thorpej Exp $ */
 
 /*
  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -27,6 +27,8 @@
  * rights to redistribute these changes.
  */
 
+#include <sys/lock.h>
+
 #include <machine/frame.h>
 #include <machine/reg.h>
 
@@ -52,8 +54,29 @@
        unsigned long   pcb_onfault;            /* for copy faults      [SW] */
        unsigned long   pcb_accessaddr;         /* for [fs]uswintr      [SW] */
        struct cpu_info * __volatile pcb_fpcpu; /* CPU with our FP state[SW] */
+       struct simplelock pcb_fpcpu_slock;      /* simple lock on fpcpu [SW] */
 };
 



Home | Main Index | Thread Index | Old Index