hi folks,

while investigating the powerpc ieeefp.h problems that I recently fixed,
I discovered that using ptrace() to access the floating-point state
of a thread can hit the assertion in process_read_fpregs() about
the FPU state being loaded on a different CPU.  we need to change
all of these PCU accessors to handle this case rather than asserting that
it can't happen.

in the case of PT_GETFPREGS or PT_SETFPREGS, the target thread will be
stopped, but for PT_DUMPCORE the target thread supposedly may be running.
it appears to me that the PCU save/discard code does the right thing even for
a running thread, though the thread may change its PCU state again immediately.
this is ok for PT_DUMPCORE, since PT_DUMPCORE is documented as possibly
producing an inconsistent image.  ... actually, I looked at the code some more
and PT_DUMPCORE does require that the target be stopped.

I've verified that the attached patch makes gdb and gcore work for FPU-using
programs on an MP macppc.  could people please test this on other MP systems
that use PCU?

I'll commit this in a few days if there are no objections.

-Chuck
Index: src/share/man/man9/pcu.9
===================================================================
RCS file: /home/chs/netbsd/cvs/src/share/man/man9/pcu.9,v
retrieving revision 1.10
diff -u -p -r1.10 pcu.9
--- src/share/man/man9/pcu.9    25 May 2014 14:56:23 -0000      1.10
+++ src/share/man/man9/pcu.9    4 Mar 2017 01:37:08 -0000
@@ -38,11 +38,11 @@
 .Ft void
 .Fn pcu_load "const pcu_ops_t *pcu"
 .Ft void
-.Fn pcu_save "const pcu_ops_t *pcu"
+.Fn pcu_save "const pcu_ops_t *pcu" "lwp_t *l"
 .Ft void
 .Fn pcu_save_all "lwp_t *l"
 .Ft void
-.Fn pcu_discard "const pcu_ops_t *pcu" "bool valid"
+.Fn pcu_discard "const pcu_ops_t *pcu" "lwp_t *l" "bool valid"
 .Ft void
 .Fn pcu_discard_all "lwp_t *l"
 .Ft bool
Index: src/sys/arch/aarch64/include/locore.h
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/aarch64/include/locore.h,v
retrieving revision 1.1
diff -u -p -r1.1 locore.h
--- src/sys/arch/aarch64/include/locore.h       10 Aug 2014 05:47:38 -0000      
1.1
+++ src/sys/arch/aarch64/include/locore.h       4 Mar 2017 01:46:25 -0000
@@ -69,22 +69,19 @@ extern const pcu_ops_t pcu_fpu_ops;
 static inline bool
 fpu_used_p(lwp_t *l)
 {
-       KASSERT(l == curlwp);
-       return pcu_valid_p(&pcu_fpu_ops);
+       return pcu_valid_p(&pcu_fpu_ops, l);
 }
 
 static inline void
 fpu_discard(lwp_t *l, bool usesw)
 {
-       KASSERT(l == curlwp);
-       pcu_discard(&pcu_fpu_ops, usesw);
+       pcu_discard(&pcu_fpu_ops, l, usesw);
 }
 
 static inline void
 fpu_save(lwp_t *l)
 {
-       KASSERT(l == curlwp);
-       pcu_save(&pcu_fpu_ops);
+       pcu_save(&pcu_fpu_ops, l);
 }
 
 static inline void cpsie(register_t psw) __attribute__((__unused__));
Index: src/sys/arch/alpha/alpha/compat_13_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/alpha/alpha/compat_13_machdep.c,v
retrieving revision 1.21
diff -u -p -r1.21 compat_13_machdep.c
--- src/sys/arch/alpha/alpha/compat_13_machdep.c        16 May 2014 19:18:21 
-0000      1.21
+++ src/sys/arch/alpha/alpha/compat_13_machdep.c        3 Mar 2017 22:05:18 
-0000
@@ -94,7 +94,7 @@ compat_13_sys_sigreturn(struct lwp *l, c
 
        /* XXX ksc.sc_ownedfp ? */
        pcb = lwp_getpcb(l);
-       fpu_discard(true);
+       fpu_discard(l, true);
        memcpy(&pcb->pcb_fp, (struct fpreg *)ksc.sc_fpregs,
            sizeof(struct fpreg));
        /* XXX ksc.sc_fp_control ? */
Index: src/sys/arch/alpha/alpha/compat_16_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/alpha/alpha/compat_16_machdep.c,v
retrieving revision 1.20
diff -u -p -r1.20 compat_16_machdep.c
--- src/sys/arch/alpha/alpha/compat_16_machdep.c        19 Mar 2016 20:57:48 
-0000      1.20
+++ src/sys/arch/alpha/alpha/compat_16_machdep.c        3 Mar 2017 22:05:59 
-0000
@@ -132,7 +132,7 @@ sendsig_sigcontext(const ksiginfo_t *ksi
        frame.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp();
 
        /* save the floating-point state, if necessary, then copy it. */
-       fpu_save();
+       fpu_save(l);
        frame.sf_sc.sc_ownedfp = fpu_valid_p(l);
        memcpy((struct fpreg *)frame.sf_sc.sc_fpregs, &pcb->pcb_fp,
            sizeof(struct fpreg));
@@ -281,7 +281,7 @@ compat_16_sys___sigreturn14(struct lwp *
        alpha_pal_wrusp(ksc.sc_regs[R_SP]);
 
        pcb = lwp_getpcb(l);
-       fpu_discard(true);
+       fpu_discard(l, true);
        memcpy(&pcb->pcb_fp, (struct fpreg *)ksc.sc_fpregs,
            sizeof(struct fpreg));
        pcb->pcb_fp.fpr_cr = ksc.sc_fpcr;
Index: src/sys/arch/alpha/alpha/machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/alpha/alpha/machdep.c,v
retrieving revision 1.349
diff -u -p -r1.349 machdep.c
--- src/sys/arch/alpha/alpha/machdep.c  23 Dec 2016 07:15:27 -0000      1.349
+++ src/sys/arch/alpha/alpha/machdep.c  3 Mar 2017 22:06:41 -0000
@@ -1796,7 +1796,7 @@ cpu_getmcontext(struct lwp *l, mcontext_
 
        /* Save floating point register context, if any, and copy it. */
        if (fpu_valid_p(l)) {
-               fpu_save();
+               fpu_save(l);
                (void)memcpy(&mcp->__fpregs, &pcb->pcb_fp,
                    sizeof (mcp->__fpregs));
                mcp->__fpregs.__fp_fpcr = alpha_read_fp_c(l);
@@ -1844,7 +1844,7 @@ cpu_setmcontext(struct lwp *l, const mco
        /* Restore floating point register context, if any. */
        if (flags & _UC_FPU) {
                /* If we have an FP register context, get rid of it. */
-               fpu_discard(true);
+               fpu_discard(l, true);
                (void)memcpy(&pcb->pcb_fp, &mcp->__fpregs,
                    sizeof (pcb->pcb_fp));
                l->l_md.md_flags = mcp->__fpregs.__fp_fpcr & MDLWP_FP_C;
Index: src/sys/arch/alpha/alpha/process_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/alpha/alpha/process_machdep.c,v
retrieving revision 1.29
diff -u -p -r1.29 process_machdep.c
--- src/sys/arch/alpha/alpha/process_machdep.c  16 May 2014 19:18:21 -0000      
1.29
+++ src/sys/arch/alpha/alpha/process_machdep.c  3 Mar 2017 22:07:36 -0000
@@ -116,7 +116,7 @@ process_read_fpregs(struct lwp *l, struc
 {
        struct pcb *pcb = lwp_getpcb(l);
 
-       fpu_save();
+       fpu_save(l);
 
        memcpy(regs, &pcb->pcb_fp, sizeof(struct fpreg));
        return (0);
@@ -127,7 +127,7 @@ process_write_fpregs(struct lwp *l, cons
 {
        struct pcb *pcb = lwp_getpcb(l);
 
-       fpu_discard(true);
+       fpu_discard(l, true);
 
        memcpy(&pcb->pcb_fp, regs, sizeof(struct fpreg));
        return (0);
Index: src/sys/arch/alpha/alpha/trap.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/alpha/alpha/trap.c,v
retrieving revision 1.132
diff -u -p -r1.132 trap.c
--- src/sys/arch/alpha/alpha/trap.c     2 Mar 2015 11:07:16 -0000       1.132
+++ src/sys/arch/alpha/alpha/trap.c     3 Mar 2017 22:08:09 -0000
@@ -641,13 +641,13 @@ static const int reg_to_framereg[32] = {
 
 #define        unaligned_load_floating(storage, mod) do {                      
\
        struct pcb * const pcb = lwp_getpcb(l);                         \
-       fpu_save();                                                     \
+       fpu_save(l);                                                    \
        unaligned_load(storage, frp, mod)                               \
 } while (/*CONSTCOND*/0)
 
 #define        unaligned_store_floating(storage, mod) do {                     
\
        struct pcb * const pcb = lwp_getpcb(l);                         \
-       fpu_save();                                                     \
+       fpu_save(l);                                                    \
        unaligned_store(storage, frp, mod)                              \
 } while (/*CONSTCOND*/0)
 
Index: src/sys/arch/alpha/include/alpha.h
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/alpha/include/alpha.h,v
retrieving revision 1.34
diff -u -p -r1.34 alpha.h
--- src/sys/arch/alpha/include/alpha.h  16 May 2014 19:18:21 -0000      1.34
+++ src/sys/arch/alpha/include/alpha.h  4 Mar 2017 01:45:43 -0000
@@ -116,8 +116,7 @@ void    fpu_state_release(struct lwp *);
 static inline bool
 fpu_valid_p(struct lwp *l)
 {
-       KASSERT(l == curlwp);
-       return pcu_valid_p(&fpu_ops);
+       return pcu_valid_p(&fpu_ops, l);
 }
 
 static inline void
@@ -127,15 +126,15 @@ fpu_load(void)
 }
 
 static inline void
-fpu_save(void)
+fpu_save(lwp_t *l)
 {
-       pcu_save(&fpu_ops);
+       pcu_save(&fpu_ops, l);
 }
 
 static inline void
-fpu_discard(bool valid_p)
+fpu_discard(lwp_t *l, bool valid_p)
 {
-       pcu_discard(&fpu_ops, valid_p);
+       pcu_discard(&fpu_ops, l, valid_p);
 }
 
 void   alpha_patch(bool);
Index: src/sys/arch/arm/arm/arm_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/arm/arm/arm_machdep.c,v
retrieving revision 1.49
diff -u -p -r1.49 arm_machdep.c
--- src/sys/arch/arm/arm/arm_machdep.c  2 May 2015 16:20:41 -0000       1.49
+++ src/sys/arch/arm/arm/arm_machdep.c  3 Mar 2017 22:18:49 -0000
@@ -201,7 +201,7 @@ setregs(struct lwp *l, struct exec_packa
                l->l_md.md_flags |= MDLWP_NOALIGNFLT;
 #endif
 #ifdef FPU_VFP
-       vfp_discardcontext(false);
+       vfp_discardcontext(l, false);
 #endif
 }
 
Index: src/sys/arch/arm/arm/process_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/arm/arm/process_machdep.c,v
retrieving revision 1.31
diff -u -p -r1.31 process_machdep.c
--- src/sys/arch/arm/arm/process_machdep.c      21 Feb 2017 07:40:28 -0000      
1.31
+++ src/sys/arch/arm/arm/process_machdep.c      3 Mar 2017 22:19:39 -0000
@@ -177,7 +177,7 @@ process_read_fpregs(struct lwp *l, struc
                return 0;
        }
        const struct pcb * const pcb = lwp_getpcb(l);
-       vfp_savecontext();
+       vfp_savecontext(l);
        regs->fpr_vfp = pcb->pcb_vfp;
        regs->fpr_vfp.vfp_fpexc &= ~VFP_FPEXC_EN;
 #endif
@@ -220,7 +220,7 @@ process_write_fpregs(struct lwp *l, cons
                return EINVAL;
        }
        struct pcb * const pcb = lwp_getpcb(l);
-       vfp_discardcontext(true);
+       vfp_discardcontext(l, true);
        pcb->pcb_vfp = regs->fpr_vfp;
        pcb->pcb_vfp.vfp_fpexc &= ~VFP_FPEXC_EN;
 #endif
Index: src/sys/arch/arm/arm32/sys_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/arm/arm32/sys_machdep.c,v
retrieving revision 1.22
diff -u -p -r1.22 sys_machdep.c
--- src/sys/arch/arm/arm32/sys_machdep.c        2 Jul 2015 08:33:31 -0000       
1.22
+++ src/sys/arch/arm/arm32/sys_machdep.c        3 Mar 2017 22:19:56 -0000
@@ -101,7 +101,7 @@ arm32_vfp_fpscr(struct lwp *l, const voi
         * Save the current VFP state (to make sure the FPSCR copy is
         * up to date).
         */
-       vfp_savecontext();
+       vfp_savecontext(l);
 #endif
 
        retval[0] = pcb->pcb_vfp.vfp_fpscr;
@@ -125,7 +125,7 @@ arm32_fpu_used(struct lwp *l, const void
 {
        /* No args */
 #ifdef FPU_VFP
-       retval[0] = vfp_used_p();
+       retval[0] = vfp_used_p(l);
 #else
        retval[0] = false;
 #endif
Index: src/sys/arch/arm/include/locore.h
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/arm/include/locore.h,v
retrieving revision 1.26
diff -u -p -r1.26 locore.h
--- src/sys/arch/arm/include/locore.h   9 Jun 2015 08:13:17 -0000       1.26
+++ src/sys/arch/arm/include/locore.h   3 Mar 2017 22:19:01 -0000
@@ -310,11 +310,11 @@ void      ucas_ras_check(trapframe_t *);
 
 /* vfp_init.c */
 void   vfp_attach(struct cpu_info *);
-void   vfp_discardcontext(bool);
-void   vfp_savecontext(void);
+void   vfp_discardcontext(lwp_t *, bool);
+void   vfp_savecontext(lwp_t *);
 void   vfp_kernel_acquire(void);
 void   vfp_kernel_release(void);
-bool   vfp_used_p(void);
+bool   vfp_used_p(const lwp_t *);
 extern const pcu_ops_t arm_vfp_ops;
 
 #endif /* !_LOCORE */
Index: src/sys/arch/arm/vfp/vfp_init.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/arm/vfp/vfp_init.c,v
retrieving revision 1.50
diff -u -p -r1.50 vfp_init.c
--- src/sys/arch/arm/vfp/vfp_init.c     3 Mar 2016 17:01:31 -0000       1.50
+++ src/sys/arch/arm/vfp/vfp_init.c     3 Mar 2017 22:20:52 -0000
@@ -196,7 +196,7 @@ vfp_fpscr_handler(u_int address, u_int i
        if (pcb->pcb_vfp.vfp_fpexc & VFP_FPEXC_EN)
                return 1;
 
-       if (__predict_false(!vfp_used_p())) {
+       if (__predict_false(!vfp_used_p(l))) {
                pcb->pcb_vfp.vfp_fpscr = vfp_fpscr_default;
        }
 #endif
@@ -434,7 +434,7 @@ vfp_handler(u_int address, u_int insn, t
                 */
                armreg_fpexc_write(fpexc & ~(VFP_FPEXC_EX|VFP_FPEXC_FSUM));
 
-               pcu_save(&arm_vfp_ops);
+               pcu_save(&arm_vfp_ops, curlwp);
 
                /*
                 * XXX Need to emulate bounce instructions here to get correct
@@ -603,29 +603,30 @@ vfp_state_release(lwp_t *l)
 }
 
 void
-vfp_savecontext(void)
+vfp_savecontext(lwp_t *l)
 {
-       pcu_save(&arm_vfp_ops);
+       pcu_save(&arm_vfp_ops, l);
 }
 
 void
-vfp_discardcontext(bool used_p)
+vfp_discardcontext(lwp_t *l, bool used_p)
 {
-       pcu_discard(&arm_vfp_ops, used_p);
+       pcu_discard(&arm_vfp_ops, l, used_p);
 }
 
 bool
-vfp_used_p(void)
+vfp_used_p(const lwp_t *l)
 {
-       return pcu_valid_p(&arm_vfp_ops);
+       return pcu_valid_p(&arm_vfp_ops, l);
 }
 
 void
 vfp_getcontext(struct lwp *l, mcontext_t *mcp, int *flagsp)
 {
-       if (vfp_used_p()) {
+       if (vfp_used_p(l)) {
                const struct pcb * const pcb = lwp_getpcb(l);
-               pcu_save(&arm_vfp_ops);
+
+               pcu_save(&arm_vfp_ops, l);
                mcp->__fpu.__vfpregs.__vfp_fpscr = pcb->pcb_vfp.vfp_fpscr;
                memcpy(mcp->__fpu.__vfpregs.__vfp_fstmx, pcb->pcb_vfp.vfp_regs,
                    sizeof(mcp->__fpu.__vfpregs.__vfp_fstmx));
@@ -636,8 +637,9 @@ vfp_getcontext(struct lwp *l, mcontext_t
 void
 vfp_setcontext(struct lwp *l, const mcontext_t *mcp)
 {
-       pcu_discard(&arm_vfp_ops, true);
        struct pcb * const pcb = lwp_getpcb(l);
+
+       pcu_discard(&arm_vfp_ops, l, true);
        pcb->pcb_vfp.vfp_fpscr = mcp->__fpu.__vfpregs.__vfp_fpscr;
        memcpy(pcb->pcb_vfp.vfp_regs, mcp->__fpu.__vfpregs.__vfp_fstmx,
            sizeof(mcp->__fpu.__vfpregs.__vfp_fstmx));
Index: src/sys/arch/mips/include/locore.h
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/mips/include/locore.h,v
retrieving revision 1.101
diff -u -p -r1.101 locore.h
--- src/sys/arch/mips/include/locore.h  13 Oct 2016 18:52:30 -0000      1.101
+++ src/sys/arch/mips/include/locore.h  3 Mar 2017 23:37:06 -0000
@@ -727,18 +727,18 @@ int       kdbpeek(vaddr_t);
 
 /* mips_dsp.c */
 void   dsp_init(void);
-void   dsp_discard(void);
+void   dsp_discard(lwp_t *);
 void   dsp_load(void);
-void   dsp_save(void);
-bool   dsp_used_p(void);
+void   dsp_save(lwp_t *);
+bool   dsp_used_p(const lwp_t *);
 extern const pcu_ops_t mips_dsp_ops;
 
 /* mips_fpu.c */
 void   fpu_init(void);
-void   fpu_discard(void);
+void   fpu_discard(lwp_t *);
 void   fpu_load(void);
-void   fpu_save(void);
-bool   fpu_used_p(void);
+void   fpu_save(lwp_t *);
+bool   fpu_used_p(const lwp_t *);
 extern const pcu_ops_t mips_fpu_ops;
 
 /* mips_machdep.c */
Index: src/sys/arch/mips/mips/compat_16_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/mips/mips/compat_16_machdep.c,v
retrieving revision 1.21
diff -u -p -r1.21 compat_16_machdep.c
--- src/sys/arch/mips/mips/compat_16_machdep.c  6 Dec 2013 13:52:05 -0000       
1.21
+++ src/sys/arch/mips/mips/compat_16_machdep.c  3 Mar 2017 22:22:23 -0000
@@ -131,11 +131,11 @@ sendsig_sigcontext(const ksiginfo_t *ksi
 #endif
 
        /* Save the FP state, if necessary, then copy it. */
-       ksc.sc_fpused = fpu_used_p();
+       ksc.sc_fpused = fpu_used_p(l);
 #if !defined(NOFPU)
        if (ksc.sc_fpused) {
                /* if FPU has current state, save it first */
-               fpu_save();
+               fpu_save(l);
        }
 #endif
        *(struct fpreg *)ksc.sc_fpregs = *(struct fpreg *)&pcb->pcb_fpregs;
@@ -275,7 +275,7 @@ compat_16_sys___sigreturn14(struct lwp *
 #endif
 #if !defined(NOFPU)
        if (scp->sc_fpused) {
-               fpu_discard();
+               fpu_discard(l);
        }
 #endif
        *(struct fpreg *)&pcb->pcb_fpregs = *(struct fpreg *)scp->sc_fpregs;
Index: src/sys/arch/mips/mips/cpu_subr.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/mips/mips/cpu_subr.c,v
retrieving revision 1.30
diff -u -p -r1.30 cpu_subr.c
--- src/sys/arch/mips/mips/cpu_subr.c   31 Oct 2016 12:49:04 -0000      1.30
+++ src/sys/arch/mips/mips/cpu_subr.c   3 Mar 2017 22:22:40 -0000
@@ -371,13 +371,13 @@ cpu_getmcontext(struct lwp *l, mcontext_
 
        /* Save floating point register context, if any. */
        KASSERT(l == curlwp);
-       if (fpu_used_p()) {
+       if (fpu_used_p(l)) {
                size_t fplen;
                /*
                 * If this process is the current FP owner, dump its
                 * context to the PCB first.
                 */
-               fpu_save();
+               fpu_save(l);
 
                /*
                 * The PCB FP regs struct includes the FP CSR, so use the
@@ -451,7 +451,7 @@ cpu_setmcontext(struct lwp *l, const mco
                size_t fplen;
 
                /* Disable the FPU contents. */
-               fpu_discard();
+               fpu_discard(l);
 
 #if !defined(__mips_o32)
                if (_MIPS_SIM_NEWABI_P(l->l_proc->p_md.md_abi)) {
Index: src/sys/arch/mips/mips/mips_dsp.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/mips/mips/mips_dsp.c,v
retrieving revision 1.4
diff -u -p -r1.4 mips_dsp.c
--- src/sys/arch/mips/mips/mips_dsp.c   16 May 2014 00:48:41 -0000      1.4
+++ src/sys/arch/mips/mips/mips_dsp.c   3 Mar 2017 23:37:09 -0000
@@ -58,9 +58,9 @@ const pcu_ops_t mips_dsp_ops = {
 };
 
 void
-dsp_discard(void)
+dsp_discard(lwp_t *l)
 {
-       pcu_discard(&mips_dsp_ops, false);
+       pcu_discard(&mips_dsp_ops, l, false);
 }
 
 void
@@ -70,15 +70,15 @@ dsp_load(void)
 }
 
 void
-dsp_save(void)
+dsp_save(lwp_t *l)
 {
-       pcu_save(&mips_dsp_ops);
+       pcu_save(&mips_dsp_ops, l);
 }
 
 bool
-dsp_used_p(void)
+dsp_used_p(const lwp_t *l)
 {
-       return pcu_valid_p(&mips_dsp_ops);
+       return pcu_valid_p(&mips_dsp_ops, l);
 }
 
 void
Index: src/sys/arch/mips/mips/mips_fpu.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/mips/mips/mips_fpu.c,v
retrieving revision 1.13
diff -u -p -r1.13 mips_fpu.c
--- src/sys/arch/mips/mips/mips_fpu.c   26 Mar 2016 17:40:02 -0000      1.13
+++ src/sys/arch/mips/mips/mips_fpu.c   3 Mar 2017 22:23:23 -0000
@@ -58,9 +58,9 @@ const pcu_ops_t mips_fpu_ops = {
 };
 
 void
-fpu_discard(void)
+fpu_discard(lwp_t *l)
 {
-       pcu_discard(&mips_fpu_ops, false);
+       pcu_discard(&mips_fpu_ops, l, false);
 }
 
 void
@@ -70,15 +70,15 @@ fpu_load(void)
 }
 
 void
-fpu_save(void)
+fpu_save(lwp_t *l)
 {
-       pcu_save(&mips_fpu_ops);
+       pcu_save(&mips_fpu_ops, l);
 }
 
 bool
-fpu_used_p(void)
+fpu_used_p(const lwp_t *l)
 {
-       return pcu_valid_p(&mips_fpu_ops);
+       return pcu_valid_p(&mips_fpu_ops, l);
 }
 
 void
Index: src/sys/arch/mips/mips/netbsd32_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/mips/mips/netbsd32_machdep.c,v
retrieving revision 1.13
diff -u -p -r1.13 netbsd32_machdep.c
--- src/sys/arch/mips/mips/netbsd32_machdep.c   26 Nov 2015 13:15:34 -0000      
1.13
+++ src/sys/arch/mips/mips/netbsd32_machdep.c   3 Mar 2017 22:11:50 -0000
@@ -324,8 +324,7 @@ cpu_coredump32(struct lwp *l, struct cor
                return 0;
        }
 
-       KASSERT(l == curlwp);
-       fpu_save();
+       fpu_save(l);
 
        struct pcb * const pcb = lwp_getpcb(l);
        cpustate.frame = *l->l_md.md_utf;
Index: src/sys/arch/mips/mips/process_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/mips/mips/process_machdep.c,v
retrieving revision 1.37
diff -u -p -r1.37 process_machdep.c
--- src/sys/arch/mips/mips/process_machdep.c    4 Jan 2014 00:10:03 -0000       
1.37
+++ src/sys/arch/mips/mips/process_machdep.c    3 Mar 2017 22:23:39 -0000
@@ -144,7 +144,7 @@ process_read_fpregs(struct lwp *l, struc
                *regslen_p = sizeof(struct fpreg_oabi);
 #endif
 
-       fpu_save();
+       fpu_save(l);
        memcpy(regs, &pcb->pcb_fpregs, sizeof(*regs));
        return 0;
 }
@@ -156,7 +156,7 @@ process_write_fpregs(struct lwp *l, cons
 
 #ifndef NOFPU
        /* to load FPA contents next time when FP insn is executed */
-       fpu_discard();
+       fpu_discard(l);
 #endif /* !NOFPU */
 
 #if defined(__mips_n32) || defined(__mips_n64)
Index: src/sys/arch/powerpc/booke/spe.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/powerpc/booke/spe.c,v
retrieving revision 1.8
diff -u -p -r1.8 spe.c
--- src/sys/arch/powerpc/booke/spe.c    16 May 2014 00:48:41 -0000      1.8
+++ src/sys/arch/powerpc/booke/spe.c    3 Mar 2017 19:40:18 -0000
@@ -63,13 +63,13 @@ const pcu_ops_t vec_ops = {
 bool
 vec_used_p(lwp_t *l)
 {
-       return pcu_valid_p(&vec_ops);
+       return pcu_valid_p(&vec_ops, l);
 }
 
 void
 vec_mark_used(lwp_t *l)
 {
-       pcu_discard(&vec_ops, true);
+       pcu_discard(&vec_ops, l, true);
 }
 
 void
Index: src/sys/arch/powerpc/include/altivec.h
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/powerpc/include/altivec.h,v
retrieving revision 1.16
diff -u -p -r1.16 altivec.h
--- src/sys/arch/powerpc/include/altivec.h      22 Aug 2013 19:50:54 -0000      
1.16
+++ src/sys/arch/powerpc/include/altivec.h      3 Mar 2017 19:00:18 -0000
@@ -60,15 +60,15 @@ vec_load(void)
 }
 
 static inline void
-vec_save(void)
+vec_save(lwp_t *l)
 {
-       pcu_save(&vec_ops);
+       pcu_save(&vec_ops, l);
 }
 
 static inline void
-vec_discard(void)
+vec_discard(lwp_t *l)
 {
-       pcu_discard(&vec_ops, false);
+       pcu_discard(&vec_ops, l, false);
 }
 
 void   vec_load_from_vreg(const struct vreg *);
Index: src/sys/arch/powerpc/include/fpu.h
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/powerpc/include/fpu.h,v
retrieving revision 1.20
diff -u -p -r1.20 fpu.h
--- src/sys/arch/powerpc/include/fpu.h  22 Aug 2013 19:50:54 -0000      1.20
+++ src/sys/arch/powerpc/include/fpu.h  3 Mar 2017 19:00:29 -0000
@@ -98,15 +98,15 @@ fpu_load(void)
 }
 
 static inline void
-fpu_save(void)
+fpu_save(lwp_t *l)
 {
-       pcu_save(&fpu_ops);
+       pcu_save(&fpu_ops, l);
 }
 
 static inline void
-fpu_discard(void)
+fpu_discard(lwp_t *l)
 {
-       pcu_discard(&fpu_ops, false);
+       pcu_discard(&fpu_ops, l, false);
 }
 
 void   fpu_load_from_fpreg(const struct fpreg *);
Index: src/sys/arch/powerpc/oea/altivec.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/powerpc/oea/altivec.c,v
retrieving revision 1.30
diff -u -p -r1.30 altivec.c
--- src/sys/arch/powerpc/oea/altivec.c  6 Jul 2015 02:43:26 -0000       1.30
+++ src/sys/arch/powerpc/oea/altivec.c  3 Mar 2017 19:40:24 -0000
@@ -63,13 +63,13 @@ const pcu_ops_t vec_ops = {
 bool
 vec_used_p(lwp_t *l)
 {
-       return pcu_valid_p(&vec_ops);
+       return pcu_valid_p(&vec_ops, l);
 }
 
 void
 vec_mark_used(lwp_t *l)
 {
-       return pcu_discard(&vec_ops, true);
+       return pcu_discard(&vec_ops, l, true);
 }
 
 void
@@ -166,7 +166,8 @@ vec_restore_from_mcontext(struct lwp *l,
        KASSERT(l == curlwp);
 
        /* we don't need to save the state, just drop it */
-       pcu_discard(&vec_ops, true);
+       pcu_discard(&vec_ops, l, true);
+
        memcpy(pcb->pcb_vr.vreg, &mcp->__vrf.__vrs, sizeof (pcb->pcb_vr.vreg));
        pcb->pcb_vr.vscr = mcp->__vrf.__vscr;
        pcb->pcb_vr.vrsave = mcp->__vrf.__vrsave;
@@ -187,7 +188,7 @@ vec_save_to_mcontext(struct lwp *l, mcon
        /*
         * If we're the AltiVec owner, dump its context to the PCB first.
         */
-       pcu_save(&vec_ops);
+       pcu_save(&vec_ops, l);
 
        mcp->__gregs[_REG_MSR] |= PSL_VEC;
        mcp->__vrf.__vscr = pcb->pcb_vr.vscr;
Index: src/sys/arch/powerpc/powerpc/fpu.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/powerpc/powerpc/fpu.c,v
retrieving revision 1.36
diff -u -p -r1.36 fpu.c
--- src/sys/arch/powerpc/powerpc/fpu.c  6 Jul 2015 01:55:50 -0000       1.36
+++ src/sys/arch/powerpc/powerpc/fpu.c  3 Mar 2017 21:59:05 -0000
@@ -65,13 +65,13 @@ const pcu_ops_t fpu_ops = {
 bool
 fpu_used_p(lwp_t *l)
 {
-       return pcu_valid_p(&fpu_ops);
+       return pcu_valid_p(&fpu_ops, l);
 }
 
 void
 fpu_mark_used(lwp_t *l)
 {
-       pcu_discard(&fpu_ops, true);
+       pcu_discard(&fpu_ops, l, true);
 }
 
 #ifdef PPC_HAVE_FPU
@@ -175,7 +175,7 @@ fpu_get_fault_code(void)
                 * We got preempted to a different CPU so we need to save
                 * our FPU state.
                 */
-               fpu_save();
+               fpu_save(l);
                fpscr64 = *(uint64_t *)&pcb->pcb_fpu.fpscr;
                ((uint32_t *)&pcb->pcb_fpu.fpscr)[_QUAD_LOWWORD] &= ~MASKBITS;
        }
@@ -213,14 +213,14 @@ fpu_save_to_mcontext(lwp_t *l, mcontext_
 {
        KASSERT(l == curlwp);
 
-       if (!pcu_valid_p(&fpu_ops))
+       if (!pcu_valid_p(&fpu_ops, l))
                return false;
 
        struct pcb * const pcb = lwp_getpcb(l);
 
 #ifdef PPC_HAVE_FPU
        /* If we're the FPU owner, dump its context to the PCB first. */
-       pcu_save(&fpu_ops);
+       pcu_save(&fpu_ops, l);
 #endif
        (void)memcpy(mcp->__fpregs.__fpu_regs, pcb->pcb_fpu.fpreg,
            sizeof (mcp->__fpregs.__fpu_regs));
@@ -241,8 +241,7 @@ fpu_restore_from_mcontext(lwp_t *l, cons
 
 #ifdef PPC_HAVE_FPU
        /* we don't need to save the state, just drop it */
-       if (l == curlwp)
-               pcu_discard(&fpu_ops, true);
+       pcu_discard(&fpu_ops, l, true);
 #endif
        (void)memcpy(&pcb->pcb_fpu.fpreg, &mcp->__fpregs.__fpu_regs,
            sizeof (pcb->pcb_fpu.fpreg));
Index: src/sys/arch/powerpc/powerpc/process_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/powerpc/powerpc/process_machdep.c,v
retrieving revision 1.37
diff -u -p -r1.37 process_machdep.c
--- src/sys/arch/powerpc/powerpc/process_machdep.c      9 Mar 2014 22:31:25 
-0000       1.37
+++ src/sys/arch/powerpc/powerpc/process_machdep.c      3 Mar 2017 19:07:05 
-0000
@@ -90,12 +90,8 @@ process_read_fpregs(struct lwp *l, struc
        if (!fpu_used_p(l)) {
                memset(fpregs, 0, sizeof (*fpregs));
 #ifdef PPC_HAVE_FPU
-       } else if (l == curlwp) {
-               fpu_save();
        } else {
-               KASSERTMSG(l->l_pcu_cpu[PCU_FPU] == NULL,
-                   "%s: FPU of l (%p) active on cpu%u",
-                    __func__, l, cpu_index(l->l_pcu_cpu[PCU_FPU]));
+               fpu_save(l);
 #endif
        }
        *fpregs = pcb->pcb_fpu;
@@ -110,8 +106,7 @@ process_write_fpregs(struct lwp *l, cons
        struct pcb * const pcb = lwp_getpcb(l);
 
 #ifdef PPC_HAVE_FPU
-       KASSERT(l == curlwp);
-       fpu_discard();
+       fpu_discard(l);
 #endif
        pcb->pcb_fpu = *fpregs;
        fpu_mark_used(l);               /* pcb_fpu is initialized now. */
@@ -154,7 +149,6 @@ process_machdep_read_vecregs(struct lwp 
 {
        struct pcb * const pcb = lwp_getpcb(l);
 
-       KASSERT(l == curlwp);
 #ifdef ALTIVEC
        if (cpu_altivec == 0)
                return EINVAL;
@@ -163,13 +157,9 @@ process_machdep_read_vecregs(struct lwp 
        /* Is the process using AltiVEC? */
        if (!vec_used_p(l)) {
                memset(vregs, 0, sizeof (*vregs));
-       } else if (l == curlwp) {
-               vec_save();
-               *vregs = pcb->pcb_vr;
        } else {
-               KASSERTMSG(l->l_pcu_cpu[PCU_VEC] == NULL,
-                   "%s: VEC of l (%p) active on cpu%u",
-                    __func__, l, cpu_index(l->l_pcu_cpu[PCU_FPU]));
+               vec_save(l);
+               *vregs = pcb->pcb_vr;
        }
        vec_mark_used(l);
 
@@ -181,15 +171,13 @@ process_machdep_write_vecregs(struct lwp
 {
        struct pcb * const pcb = lwp_getpcb(l);
 
-       KASSERT(l == curlwp);
-
 #ifdef ALTIVEC
        if (cpu_altivec == 0)
                return (EINVAL);
 #endif
 
 #if defined(ALTIVEC) || defined(PPC_HAVE_SPE)
-       vec_discard();
+       vec_discard(l);
 #endif
        pcb->pcb_vr = *vregs;           /* pcb_vr is initialized now. */
        vec_mark_used(l);
Index: src/sys/arch/powerpc/powerpc/trap.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/powerpc/powerpc/trap.c,v
retrieving revision 1.151
diff -u -p -r1.151 trap.c
--- src/sys/arch/powerpc/powerpc/trap.c 27 Feb 2017 06:54:00 -0000      1.151
+++ src/sys/arch/powerpc/powerpc/trap.c 3 Mar 2017 22:04:03 -0000
@@ -750,12 +750,12 @@ fix_unaligned(struct lwp *l, struct trap
                                memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu));
                                fpu_mark_used(l);
                        } else {
-                               fpu_save();
+                               fpu_save(l);
                        }
 
-                               if (copyin((void *)tf->tf_dar, fpreg,
-                                   sizeof(double)) != 0)
-                                       return -1;
+                       if (copyin((void *)tf->tf_dar, fpreg,
+                                  sizeof(double)) != 0)
+                               return -1;
 
                        if (dsi->flags & DSI_OP_INDEXED) {
                            /* do nothing */
@@ -796,12 +796,12 @@ fix_unaligned(struct lwp *l, struct trap
                                memset(&pcb->pcb_fpu, 0, sizeof(pcb->pcb_fpu));
                                fpu_mark_used(l);
                        } else {
-                               fpu_save();
+                               fpu_save(l);
                        }
 
-                               if (copyout(fpreg, (void *)tf->tf_dar,
+                       if (copyout(fpreg, (void *)tf->tf_dar,
                                    sizeof(double)) != 0)
-                                       return -1;
+                               return -1;
 
                        if (dsi->flags & DSI_OP_INDEXED) {
                            /* do nothing */
Index: src/sys/arch/riscv/include/locore.h
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/riscv/include/locore.h,v
retrieving revision 1.2
diff -u -p -r1.2 locore.h
--- src/sys/arch/riscv/include/locore.h 28 Mar 2015 16:13:56 -0000      1.2
+++ src/sys/arch/riscv/include/locore.h 3 Mar 2017 19:40:42 -0000
@@ -138,27 +138,27 @@ fpu_load(void)
 }
 
 static inline void
-fpu_save(void)
+fpu_save(lwp_t *l)
 {
-       pcu_save(&pcu_fpu_ops);
+       pcu_save(&pcu_fpu_ops, l);
 }
 
 static inline void
-fpu_discard(void)
+fpu_discard(lwp_t *l)
 {
-       pcu_discard(&pcu_fpu_ops, false);
+       pcu_discard(&pcu_fpu_ops, l, false);
 }
 
 static inline void
-fpu_replace(void)
+fpu_replace(lwp_t *l)
 {
-       pcu_discard(&pcu_fpu_ops, true);
+       pcu_discard(&pcu_fpu_ops, l, true);
 }
 
 static inline bool
-fpu_valid_p(void)
+fpu_valid_p(lwp_t *l)
 {
-       return pcu_valid_p(&pcu_fpu_ops);
+       return pcu_valid_p(&pcu_fpu_ops, l);
 }
 
 void   __syncicache(const void *, size_t);
Index: src/sys/arch/riscv/riscv/netbsd32_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/riscv/riscv/netbsd32_machdep.c,v
retrieving revision 1.2
diff -u -p -r1.2 netbsd32_machdep.c
--- src/sys/arch/riscv/riscv/netbsd32_machdep.c 26 Nov 2015 13:15:34 -0000      
1.2
+++ src/sys/arch/riscv/riscv/netbsd32_machdep.c 4 Mar 2017 00:30:31 -0000
@@ -92,12 +92,12 @@ cpu_getmcontext32(struct lwp *l, mcontex
 
        /* Save floating point register context, if any. */
        KASSERT(l == curlwp);
-       if (fpu_valid_p()) {
+       if (fpu_valid_p(l)) {
                /*
                 * If this process is the current FP owner, dump its
                 * context to the PCB first.
                 */
-               fpu_save();
+               fpu_save(l);
 
                struct pcb * const pcb = lwp_getpcb(l);
                *(struct fpreg *)mcp->__fregs = pcb->pcb_fpregs;
@@ -149,7 +149,7 @@ cpu_setmcontext32(struct lwp *l, const m
        if (flags & _UC_FPU) {
                KASSERT(l == curlwp);
                /* Tell PCU we are replacing the FPU contents. */
-               fpu_replace();
+               fpu_replace(l);
 
                /*
                 * The PCB FP regs struct includes the FP CSR, so use the
@@ -185,4 +185,3 @@ netbsd32_vm_default_addr(struct proc *p,
        else
                return VM_DEFAULT_ADDRESS32_BOTTOMUP(base, size);
 }
-
Index: src/sys/arch/riscv/riscv/process_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/riscv/riscv/process_machdep.c,v
retrieving revision 1.1
diff -u -p -r1.1 process_machdep.c
--- src/sys/arch/riscv/riscv/process_machdep.c  28 Mar 2015 16:13:56 -0000      
1.1
+++ src/sys/arch/riscv/riscv/process_machdep.c  4 Mar 2017 00:30:46 -0000
@@ -63,19 +63,14 @@ process_read_fpregs(struct lwp *l, struc
 {
        struct pcb * const pcb = lwp_getpcb(l);
 
-       if (l == curlwp) {
-               /* Is the process using the fpu? */
-               if (!fpu_valid_p()) {
-                       memset(fpregs, 0, sizeof (*fpregs));
-                       return 0;
-               }
-               fpu_save();
-       } else {
-               KASSERTMSG(l->l_pcu_cpu[PCU_FPU] == NULL,
-                   "%s: FPU of l (%p) active on %s",
-                    __func__, l, l->l_pcu_cpu[PCU_FPU]->ci_cpuname);
+       /* Is the process using the fpu? */
+       if (!fpu_valid_p(l)) {
+               memset(fpregs, 0, sizeof (*fpregs));
+               return 0;
        }
+       fpu_save(l);
        *fpregs = pcb->pcb_fpregs;
+
        return 0;
 }
 
@@ -84,9 +79,7 @@ process_write_fpregs(struct lwp *l, cons
 {
        struct pcb * const pcb = lwp_getpcb(l);
 
-       KASSERT(l == curlwp);
-       fpu_replace();
-
+       fpu_replace(l);
        pcb->pcb_fpregs = *fpregs;
 
        return 0;
Index: src/sys/arch/riscv/riscv/riscv_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/riscv/riscv/riscv_machdep.c,v
retrieving revision 1.1
diff -u -p -r1.1 riscv_machdep.c
--- src/sys/arch/riscv/riscv/riscv_machdep.c    28 Mar 2015 16:13:56 -0000      
1.1
+++ src/sys/arch/riscv/riscv/riscv_machdep.c    4 Mar 2017 00:30:11 -0000
@@ -170,12 +170,12 @@ cpu_getmcontext(struct lwp *l, mcontext_
 
        /* Save floating point register context, if any. */
        KASSERT(l == curlwp);
-       if (fpu_valid_p()) {
+       if (fpu_valid_p(l)) {
                /*
                 * If this process is the current FP owner, dump its
                 * context to the PCB first.
                 */
-               fpu_save();
+               fpu_save(l);
 
                struct pcb * const pcb = lwp_getpcb(l);
                *(struct fpreg *)mcp->__fregs = pcb->pcb_fpregs;
@@ -224,7 +224,7 @@ cpu_setmcontext(struct lwp *l, const mco
        if (flags & _UC_FPU) {
                KASSERT(l == curlwp);
                /* Tell PCU we are replacing the FPU contents. */
-               fpu_replace();
+               fpu_replace(l);
 
                /*
                 * The PCB FP regs struct includes the FP CSR, so use the
Index: src/sys/compat/linux/arch/powerpc/linux_machdep.c
===================================================================
RCS file: 
/home/chs/netbsd/cvs/src/sys/compat/linux/arch/powerpc/linux_machdep.c,v
retrieving revision 1.48
diff -u -p -r1.48 linux_machdep.c
--- src/sys/compat/linux/arch/powerpc/linux_machdep.c   9 Nov 2014 17:48:08 
-0000       1.48
+++ src/sys/compat/linux/arch/powerpc/linux_machdep.c   3 Mar 2017 22:12:46 
-0000
@@ -181,7 +181,7 @@ linux_sendsig(const ksiginfo_t *ksi, con
        memcpy(&frame.lgp_regs, &linux_regs, sizeof(linux_regs));
 
 #ifdef PPC_HAVE_FPU
-       fpu_save();
+       fpu_save(l);
 #endif
        memcpy(&frame.lfp_regs, curpcb->pcb_fpu.fpreg, sizeof(frame.lfp_regs));
 
Index: src/sys/kern/subr_pcu.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/kern/subr_pcu.c,v
retrieving revision 1.19
diff -u -p -r1.19 subr_pcu.c
--- src/sys/kern/subr_pcu.c     25 May 2014 14:53:55 -0000      1.19
+++ src/sys/kern/subr_pcu.c     4 Mar 2017 01:50:31 -0000
@@ -313,7 +313,7 @@ pcu_load(const pcu_ops_t *pcu)
                 * some architectures.
                 */
                KASSERT(curci->ci_pcu_curlwp[id] == l);
-               KASSERT(pcu_valid_p(pcu));
+               KASSERT(pcu_valid_p(pcu, l));
                pcu->pcu_state_load(l, PCU_VALID | PCU_REENABLE);
                splx(s);
                return;
@@ -356,14 +356,13 @@ pcu_load(const pcu_ops_t *pcu)
 }
 
 /*
- * pcu_discard: discard the PCU state of current LWP.  If "valid"
+ * pcu_discard: discard the PCU state of the given LWP.  If "valid"
  * parameter is true, then keep considering the PCU state as valid.
  */
 void
-pcu_discard(const pcu_ops_t *pcu, bool valid)
+pcu_discard(const pcu_ops_t *pcu, lwp_t *l, bool valid)
 {
        const u_int id = pcu->pcu_id;
-       lwp_t * const l = curlwp;
 
        KASSERT(!cpu_intr_p() && !cpu_softintr_p());
 
@@ -382,10 +381,9 @@ pcu_discard(const pcu_ops_t *pcu, bool v
  * pcu_save_lwp: save PCU state to the given LWP.
  */
 void
-pcu_save(const pcu_ops_t *pcu)
+pcu_save(const pcu_ops_t *pcu, lwp_t *l)
 {
        const u_int id = pcu->pcu_id;
-       lwp_t * const l = curlwp;
 
        KASSERT(!cpu_intr_p() && !cpu_softintr_p());
 
@@ -420,10 +418,9 @@ pcu_save_all_on_cpu(void)
  * it always becomes "valid" when pcu_load() is called.
  */
 bool
-pcu_valid_p(const pcu_ops_t *pcu)
+pcu_valid_p(const pcu_ops_t *pcu, const lwp_t *l)
 {
        const u_int id = pcu->pcu_id;
-       lwp_t * const l = curlwp;
 
        return (l->l_pcu_valid & (1U << id)) != 0;
 }
Index: src/sys/sys/pcu.h
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/sys/pcu.h,v
retrieving revision 1.12
diff -u -p -r1.12 pcu.h
--- src/sys/sys/pcu.h   16 May 2014 00:48:41 -0000      1.12
+++ src/sys/sys/pcu.h   3 Mar 2017 22:00:10 -0000
@@ -81,10 +81,10 @@ void        pcu_discard_all(lwp_t *);
 void   pcu_save_all(lwp_t *);
 
 void   pcu_load(const pcu_ops_t *);
-void   pcu_save(const pcu_ops_t *);
+void   pcu_save(const pcu_ops_t *, lwp_t *);
 void   pcu_save_all_on_cpu(void);
-void   pcu_discard(const pcu_ops_t *, bool);
-bool   pcu_valid_p(const pcu_ops_t *);
+void   pcu_discard(const pcu_ops_t *, lwp_t *, bool);
+bool   pcu_valid_p(const pcu_ops_t *, const lwp_t *);
 
 #else
 #define        pcu_switchpoint(l)

Reply via email to