Source-Changes-HG archive

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

[src/trunk]: src pcu(9):



details:   https://anonhg.NetBSD.org/src/rev/8c8d223020d3
branches:  trunk
changeset: 329238:8c8d223020d3
user:      rmind <rmind%NetBSD.org@localhost>
date:      Fri May 16 00:48:41 2014 +0000

description:
pcu(9):
- Remove PCU_KERNEL (hi matt!) and significantly simplify the code.
  This experimental feature was tried on ARM did not meet the expectations.
  It may be revived one day, but it should be done in a much simpler way.
- Add a message structure for xcall function, pass the LWP ower and thus
  optimise a race condition: if LWP is discarding its state on a remote CPU,
  but another LWP already did it - do not cause an unecessary re-faulting.
- Reduce the variety of flags for PCU operations (only PCU_VALID and
  PCU_REENABLE are used now), pass them only to the pcu_state_load().
- Rename pcu_used_p() to pcu_valid_p(); hopefully it is less confusing.
- pcu_save_all_on_cpu: SPL ought to be used here.
- Update and improve the pcu(9) man page; it needs wizd(8) though.

diffstat:

 share/man/man9/pcu.9               |   65 +++----
 sys/arch/alpha/alpha/fp_complete.c |   10 +-
 sys/arch/alpha/include/alpha.h     |    6 +-
 sys/arch/amd64/amd64/locore.S      |    7 +-
 sys/arch/arm/vfp/vfp_init.c        |  156 ++++-------------
 sys/arch/mips/mips/mips_dsp.c      |   17 +-
 sys/arch/mips/mips/mips_fpu.c      |   17 +-
 sys/arch/powerpc/booke/spe.c       |   16 +-
 sys/arch/powerpc/oea/altivec.c     |   16 +-
 sys/arch/powerpc/powerpc/fpu.c     |   18 +-
 sys/kern/subr_pcu.c                |  305 ++++++++++++++----------------------
 sys/sys/pcu.h                      |   38 ++--
 12 files changed, 257 insertions(+), 414 deletions(-)

diffs (truncated from 1365 to 300 lines):

diff -r 73a5735b26cf -r 8c8d223020d3 share/man/man9/pcu.9
--- a/share/man/man9/pcu.9      Fri May 16 00:19:00 2014 +0000
+++ b/share/man/man9/pcu.9      Fri May 16 00:48:41 2014 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: pcu.9,v 1.6 2014/05/15 23:59:05 wiz Exp $
+.\"    $NetBSD: pcu.9,v 1.7 2014/05/16 00:48:41 rmind Exp $
 .\"
 .\" Copyright (c) 2012-2014 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd May 12, 2014
+.Dd May 15, 2014
 .Dt PCU 9
 .Os
 .Sh NAME
@@ -42,14 +42,14 @@
 .Ft void
 .Fn pcu_save_all "lwp_t *l"
 .Ft void
-.Fn pcu_discard "const pcu_ops_t *pcu"
+.Fn pcu_discard "const pcu_ops_t *pcu" "bool valid"
 .Ft bool
-.Fn pcu_used_p "const pcu_ops_t *pcu"
+.Fn pcu_valid_p "const pcu_ops_t *pcu"
 .\" -----
 .Sh DESCRIPTION
 Per CPU Unit (PCU) is an interface to manage synchronization of any
 per-CPU context (unit) tied to an LWP context.
-Typical use of PCU is for "lazy-switch" synchronisation of FPU state.
+Typical use of PCU is for "lazy-switch" synchronization of the FPU state.
 Each PCU has its operations defined by a
 .Vt pcu_ops_t
 structure.
@@ -58,62 +58,55 @@
 are
 .Bd -literal
         u_int  pcu_id;
-        void   (*pcu_state_save)(lwp_t *l, u_int flags);
+        void   (*pcu_state_save)(lwp_t *l);
         void   (*pcu_state_load)(lwp_t *l, u_int flags);
-        void   (*pcu_state_release)(lwp_t *l, u_int flags);
+        void   (*pcu_state_release)(lwp_t *l);
 .Ed
 .Pp
-The PCU operations take a
-.Ar flags
-parameter which is a bitmask that always can have one of the general
-bits set:
-.Bl -tag -width PCU_KERNELXXX
-.It Dv PCU_USER
-PCU state is for the user
-.It Dv PCU_KERNEL
-PCU state is for the kernel
-.El
-.Pp
-.Bl -tag -width pcu_state_saveXXX
 .It Fn pcu_state_save
-save the current CPU's state into the given LWP's MD storage.
+indicate to MD code that the PCU state on the current CPU should be
+saved into the given LWP's MD storage.
 .It Fn pcu_state_load
 load PCU state from the given LWP's MD storage to the current CPU.
 The
 .Ar flags
-is a combination of the above general flags and one or more of
-the following:
-.Bl -tag -width PCU_LOADEDXXX
-.It Dv PCU_RELOAD
-Load registers into the PCU
-.It Dv PCU_ENABLE
-Enable the PCU
-.It Dv PCU_LOADED
-the current LWP has used this PCU before
+is a combination of one or more of the following:
+.Bl -tag -width PCU_VALIDXXX
+.It Dv PCU_VALID
+Indicates that the PCU state is considered valid and need not be initialized
+This is a case if the PCU state was already used (and thus loaded) by the LWP
+and has not been discarded since.
+.It Dv PCU_REENABLE
+Indicates that a fault reoccurred while the PCU state is loaded,
+therefore PCU should be re-enabled.
+This is applicable only in some cases, e.g. ARM NEON extensions.
 .El
 .It Fn pcu_state_release
 indicate to MD code that the PCU ownership by the LWP was released,
 therefore the next use of PCU on the LWP shall be detected and
 .Fn pcu_load
-be called to reacquire ownership.
-For example, this would often be the changing of a bit for a CPU to
+be called to reacquire the ownership.
+For example, this would normally be the changing of a bit for a CPU to
 trap on the execution of one of the PCU's instructions.
 .El
 .Sh FUNCTIONS
 .Bl -tag -width pcu_save_allXXX
 .It Fn pcu_load
-Load (initialize) the PCU state of the current LWP on the current CPU.
+Load or initialize the PCU state of the current LWP on the current CPU.
 .It Fn pcu_save
 Save the specified PCU state to the given LWP.
 .It Fn pcu_discard
 Discard the specified PCU state of the current LWP.
-.It Fn pcu_used_p
-Return true if PCU was used (i.e.,
+The PCU state will be considered invalid,
+unless the "valid" parameter is set to true.
+.It Fn pcu_valid_p
+Return true if PCU state is considered valid.
+Generally, it always becomes "valid" when
 .Fn pcu_load
-was called) by the LWP.
+is called by the LWP.
 Otherwise, return false.
 .It Fn pcu_save_all
-Save all PCU state of the given LWP, so that it could be used later.
+Save all PCU states of the given LWP, so that they could be used later.
 .El
 .\" -----
 .Sh CODE REFERENCES
diff -r 73a5735b26cf -r 8c8d223020d3 sys/arch/alpha/alpha/fp_complete.c
--- a/sys/arch/alpha/alpha/fp_complete.c        Fri May 16 00:19:00 2014 +0000
+++ b/sys/arch/alpha/alpha/fp_complete.c        Fri May 16 00:48:41 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fp_complete.c,v 1.15 2012/12/26 19:13:19 matt Exp $ */
+/* $NetBSD: fp_complete.c,v 1.16 2014/05/16 00:48:41 rmind Exp $ */
 
 /*-
  * Copyright (c) 2001 Ross Harvey
@@ -35,7 +35,7 @@
 
 #include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.15 2012/12/26 19:13:19 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fp_complete.c,v 1.16 2014/05/16 00:48:41 rmind Exp $");
 
 #include "opt_compat_osf1.h"
 
@@ -731,7 +731,7 @@
         * If a process has used FP, count a "used FP, and took
         * a trap to use it again" event.
         */
-       if (!fpu_used_p(l)) {
+       if ((flags & PCU_VALID) == 0) {
                atomic_inc_ulong(&fpevent_use.ev_count);
                fpu_mark_used(l);
        } else
@@ -749,7 +749,7 @@
  */
 
 void
-fpu_state_save(struct lwp *l, u_int flags)
+fpu_state_save(struct lwp *l)
 {
        struct pcb * const pcb = lwp_getpcb(l);
 
@@ -762,7 +762,7 @@
  * Release the FPU.
  */
 void
-fpu_state_release(struct lwp *l, u_int flags)
+fpu_state_release(struct lwp *l)
 {
        l->l_md.md_flags &= ~MDLWP_FPACTIVE;
 }
diff -r 73a5735b26cf -r 8c8d223020d3 sys/arch/alpha/include/alpha.h
--- a/sys/arch/alpha/include/alpha.h    Fri May 16 00:19:00 2014 +0000
+++ b/sys/arch/alpha/include/alpha.h    Fri May 16 00:48:41 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: alpha.h,v 1.32 2013/08/22 19:50:54 drochner Exp $ */
+/* $NetBSD: alpha.h,v 1.33 2014/05/16 00:48:41 rmind Exp $ */
 
 /*
  * Copyright (c) 1988 University of Utah.
@@ -110,8 +110,8 @@
 extern const pcu_ops_t fpu_ops;
 
 void    fpu_state_load(struct lwp *, u_int);
-void    fpu_state_save(struct lwp *, u_int);
-void    fpu_state_release(struct lwp *, u_int);
+void    fpu_state_save(struct lwp *);
+void    fpu_state_release(struct lwp *);
 
 static inline void
 fpu_load(void)
diff -r 73a5735b26cf -r 8c8d223020d3 sys/arch/amd64/amd64/locore.S
--- a/sys/arch/amd64/amd64/locore.S     Fri May 16 00:19:00 2014 +0000
+++ b/sys/arch/amd64/amd64/locore.S     Fri May 16 00:48:41 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.75 2013/12/01 01:05:16 christos Exp $     */
+/*     $NetBSD: locore.S,v 1.76 2014/05/16 00:48:41 rmind Exp $        */
 
 /*
  * Copyright-o-rama!
@@ -1017,9 +1017,8 @@
        jne     5f
 
        /*
-        * Restore cr0 (including FPU state).  Raise the IPL to IPL_HIGH.
-        * FPU IPIs can alter the LWP's saved cr0.  Dropping the priority
-        * is deferred until mi_switch(), when cpu_switchto() returns.
+        * Restore cr0 including FPU state (may have CR0_TS set).  Note that
+        * IPL_SCHED prevents from FPU interrupt altering the LWP's saved cr0.
         */
 2:
 #ifndef XEN
diff -r 73a5735b26cf -r 8c8d223020d3 sys/arch/arm/vfp/vfp_init.c
--- a/sys/arch/arm/vfp/vfp_init.c       Fri May 16 00:19:00 2014 +0000
+++ b/sys/arch/arm/vfp/vfp_init.c       Fri May 16 00:48:41 2014 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: vfp_init.c,v 1.38 2014/04/06 00:54:52 matt Exp $ */
+/*      $NetBSD: vfp_init.c,v 1.39 2014/05/16 00:48:41 rmind Exp $ */
 
 /*
  * Copyright (c) 2008 ARM Ltd
@@ -131,8 +131,8 @@
 #endif
 
 static void vfp_state_load(lwp_t *, u_int);
-static void vfp_state_save(lwp_t *, u_int);
-static void vfp_state_release(lwp_t *, u_int);
+static void vfp_state_save(lwp_t *);
+static void vfp_state_release(lwp_t *);
 
 const pcu_ops_t arm_vfp_ops = {
        .pcu_id = PCU_FPU,
@@ -475,24 +475,6 @@
 vfp_state_load(lwp_t *l, u_int flags)
 {
        struct pcb * const pcb = lwp_getpcb(l);
-
-       KASSERT(flags & PCU_ENABLE);
-
-       if (flags & PCU_KERNEL) {
-               if ((flags & PCU_LOADED) == 0) {
-                       pcb->pcb_kernel_vfp.vfp_fpexc = pcb->pcb_vfp.vfp_fpexc;
-               }
-               pcb->pcb_vfp.vfp_fpexc = VFP_FPEXC_EN;
-               armreg_fpexc_write(pcb->pcb_vfp.vfp_fpexc);
-               /*
-                * Load the kernel registers (just the first 16) if they've
-                * been used..
-                */
-               if (flags & PCU_LOADED) {
-                       load_vfpregs_lo(pcb->pcb_kernel_vfp.vfp_regs);
-               }
-               return;
-       }
        struct vfpreg * const fregs = &pcb->pcb_vfp;
 
        /*
@@ -503,55 +485,53 @@
         * If a process has used the VFP, count a "used VFP, and took
         * a trap to use it again" event.
         */
-       if (__predict_false((flags & PCU_LOADED) == 0)) {
-               KASSERT(flags & PCU_RELOAD);
+       if (__predict_false((flags & PCU_VALID) == 0)) {
                curcpu()->ci_vfp_evs[0].ev_count++;
                pcb->pcb_vfp.vfp_fpscr = vfp_fpscr_default;
        } else {
                curcpu()->ci_vfp_evs[1].ev_count++;
        }
 
-       uint32_t fpexc = armreg_fpexc_read();
-       if (flags & PCU_RELOAD) {
-               bool enabled = fregs->vfp_fpexc & VFP_FPEXC_EN;
+       /*
+        * If the VFP is already enabled we must be bouncing an instruction.
+        */
+       if (flags & PCU_REENABLE) {
+               uint32_t fpexc = armreg_fpexc_read();
+               armreg_fpexc_write(fpexc | VFP_FPEXC_EN);
+               return;
+       }
 
+       /*
+        * Load and Enable the VFP (so that we can write the registers).
+        */
+       bool enabled = fregs->vfp_fpexc & VFP_FPEXC_EN;
+       fregs->vfp_fpexc |= VFP_FPEXC_EN;
+       armreg_fpexc_write(fregs->vfp_fpexc);
+       if (enabled) {
                /*
-                * Load and Enable the VFP (so that we can write the
-                * registers).
+                * If we think the VFP is enabled, it must have be
+                * disabled by vfp_state_release for another LWP so
+                * we can now just return.
                 */
-               fregs->vfp_fpexc |= VFP_FPEXC_EN;
-               armreg_fpexc_write(fregs->vfp_fpexc);
-               if (enabled) {
-                       /*
-                        * If we think the VFP is enabled, it must have be
-                        * disabled by vfp_state_release for another LWP so
-                        * we can now just return.



Home | Main Index | Thread Index | Old Index