tech-kern archive

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

[PATCH] _UC_TLSBASE, round 2



Hi

Attached is an updated patch for _UC_TLSBASE, with some documentation. 
I need help to validate the MD parts, especially for PowerPC.

While we are there, it seems we could remove _UC_ARM_VFP (unused), 
and perhaps it would make sense to support _UC_SETSTACK and _UC_CLRSTACK
on ports where it is missing (alpha, powerpc and vax if I missed nothing).

-- 
Emmanuel Dreyfus
manu%netbsd.org@localhost
Index: lib/libc/gen/makecontext.3
===================================================================
RCS file: /cvsroot/src/lib/libc/gen/makecontext.3,v
retrieving revision 1.10
diff -U 4 -r1.10 makecontext.3
--- lib/libc/gen/makecontext.3  4 May 2012 12:28:03 -0000       1.10
+++ lib/libc/gen/makecontext.3  12 Aug 2012 14:19:28 -0000
@@ -94,8 +94,32 @@
 .Xr setcontext 2 ,
 execution will resume as if the corresponding invocation of
 .Fn swapcontext
 had just returned (successfully).
+.Sh BUGS
+Programs linking with
+.Lb pthread
+should be cautious that default
+.Fn swapcontext 
+behavior is to alter the pthread private pointer, as returned by
+.Xr pthread_self 3 .
+Using a context obtained from another thread will therefore wreck the
+threading environmment, with multiple kernel threads sharing the same
+user thread identifier. The pthread private pointer can be preserved, 
+therefore enabling safe
+.Fn swapcontext
+usage with 
+.Lb pthread ,
+by unsetting
+.Dv _UC_TLSBASE
+in 
+.Vt ucontext_t
+member
+.Fa uc_flags :
+.Bd -literal -offset indent -compact
+ucp->uc_flags &= ~_UC_TLSBASE;
+swapcontext(ocup, ucp);
+.Ed
 .Sh RETURN VALUES
 The
 .Fn makecontext
 function returns no value.
Index: share/man/man2/ucontext.2
===================================================================
RCS file: /cvsroot/src/share/man/man2/ucontext.2,v
retrieving revision 1.6
diff -U 4 -r1.6 ucontext.2
--- share/man/man2/ucontext.2   29 Apr 2010 06:07:35 -0000      1.6
+++ share/man/man2/ucontext.2   12 Aug 2012 14:19:28 -0000
@@ -46,15 +46,59 @@
 The
 .Vt ucontext_t
 structure includes the following members:
 .Bd -literal -offset indent
-ucontext_t *uc_link
-sigset_t    uc_sigmask
-stack_t     uc_stack
-mcontext_t  uc_mcontext
+unsigned int uc_flags
+ucontext_t  *uc_link
+sigset_t     uc_sigmask
+stack_t      uc_stack
+mcontext_t   uc_mcontext
 .Ed
 .Pp
 The
+.Fa uc_flags
+member contains implementation-specific flags. Portable code should not
+use it. Availlable flags include:
+.Bl -tag -width _UC_SIGMASK
+.It Dv _UC_SIGMASK
+.Fa uc_sigmask
+contains a valid signal mask.
+.It Dv _UC_STACK
+.Fa uc_stack
+contains a valid stack.
+.It Dv _UC_CPU
+.Fa uc_mcontext
+contains valid CPU registers.
+.It Dv _UC_FPU
+.Fa uc_mcontext
+contains valid FPU registers.
+.It Dv _UC_TLSBASE
+.Fa uc_mcontext
+valid pthread private reference.
+.It Dv _UC_UNIQUE
+Synonym for 
+.Dv _UC_TLSBASE (alpha).
+.It Dv _UC_SETSTACK
+Context uses signal stack (missing on alpha, powerpc and vax).
+.It Dv _UC_CLRSTACK
+Context does not use signal stack (missing on alpha, powerpc and vax).
+.It Dv _UC_POWERPC_VEC
+.Fa uc_mcontext
+contains valid AltiVec context (powerpc).
+.It Dv _UC_POWERPC_SPE
+.Fa uc_mcontext
+contains valid SPE context (powerpc).
+.It Dv _UC_ARM_VFP
+Unused (arm).
+.It Dv _UC_VM
+.Fa uc_mcontext
+contains valid virtual 8086 context (amd64, i386).
+.It Dv _UC_FXSAVE
+.Fa uc_mcontext
+contains FPU context in that is in FXSAVE format in XMM space (amd64, i386).
+.El
+.Pp
+The
 .Fa uc_link
 member points to the context that will be resumed after the function
 specified when modifying a context using
 .Xr makecontext 3
Index: sys/arch/alpha/alpha/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/alpha/alpha/machdep.c,v
retrieving revision 1.340
diff -U 4 -r1.340 machdep.c
--- sys/arch/alpha/alpha/machdep.c      13 Jun 2012 17:13:41 -0000      1.340
+++ sys/arch/alpha/alpha/machdep.c      12 Aug 2012 14:19:28 -0000
@@ -1793,9 +1793,9 @@
        if ((ras_pc = (__greg_t)ras_lookup(l->l_proc,
            (void *) gr[_REG_PC])) != -1)
                gr[_REG_PC] = ras_pc;
 
-       *flags |= _UC_CPU | _UC_UNIQUE;
+       *flags |= _UC_CPU | _UC_TLSBASE;
 
        /* Save floating point register context, if any, and copy it. */
        if (fpu_used_p(l)) {
                fpu_save();
@@ -1840,9 +1840,9 @@
                        pcb->pcb_hw.apcb_usp = gr[_REG_SP];
                frame->tf_regs[FRAME_PC] = gr[_REG_PC];
                frame->tf_regs[FRAME_PS] = gr[_REG_PS];
        }
-       if (flags & _UC_UNIQUE)
+       if (flags & _UC_TLSBASE)
                lwp_setprivate(l, (void *)(uintptr_t)gr[_REG_UNIQUE]);
        /* Restore floating point register context, if any. */
        if (flags & _UC_FPU) {
                /* If we have an FP register context, get rid of it. */
Index: sys/arch/alpha/include/mcontext.h
===================================================================
RCS file: /cvsroot/src/sys/arch/alpha/include/mcontext.h,v
retrieving revision 1.7
diff -U 4 -r1.7 mcontext.h
--- sys/arch/alpha/include/mcontext.h   25 Feb 2011 14:07:12 -0000      1.7
+++ sys/arch/alpha/include/mcontext.h   12 Aug 2012 14:19:28 -0000
@@ -93,8 +93,9 @@
 } mcontext_t;
 
 /* Machine-dependent uc_flags */
 #define _UC_UNIQUE     0x20    /* valid process-unique value in _REG_UNIQUE */
+#define _UC_TLSBASE    0x20    /* synonym of _UC_UNIQUE */
 
 #define _UC_MACHINE_SP(uc)     ((uc)->uc_mcontext.__gregs[_REG_SP])
 #define _UC_MACHINE_PC(uc)     ((uc)->uc_mcontext.__gregs[_REG_PC])
 #define _UC_MACHINE_INTRV(uc)  ((uc)->uc_mcontext.__gregs[_REG_V0])
Index: sys/arch/powerpc/include/mcontext.h
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/include/mcontext.h,v
retrieving revision 1.13
diff -U 4 -r1.13 mcontext.h
--- sys/arch/powerpc/include/mcontext.h 12 Mar 2011 07:38:16 -0000      1.13
+++ sys/arch/powerpc/include/mcontext.h 12 Aug 2012 14:19:31 -0000
@@ -114,8 +114,9 @@
 
 /* Machine-dependent uc_flags */
 #define        _UC_POWERPC_VEC 0x00010000      /* Vector Register File valid */
 #define        _UC_POWERPC_SPE 0x00020000      /* Vector Register File valid */
+#define        _UC_TLSBASE     0x00080000      /* thread context valid */
 
 #define _UC_MACHINE_SP(uc)     ((uc)->uc_mcontext.__gregs[_REG_R1])
 #define _UC_MACHINE_PC(uc)     ((uc)->uc_mcontext.__gregs[_REG_PC])
 #define _UC_MACHINE_INTRV(uc)  ((uc)->uc_mcontext.__gregs[_REG_R3])
Index: sys/arch/powerpc/powerpc/sig_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/powerpc/powerpc/sig_machdep.c,v
retrieving revision 1.42
diff -U 4 -r1.42 sig_machdep.c
--- sys/arch/powerpc/powerpc/sig_machdep.c      21 May 2012 14:15:18 -0000      
1.42
+++ sys/arch/powerpc/powerpc/sig_machdep.c      12 Aug 2012 14:19:31 -0000
@@ -170,9 +170,9 @@
 #else
        gr[_REG_MQ]  = 0;
 #endif
 
-       *flagp |= _UC_CPU;
+       *flagp |= (_UC_CPU|_UC_TLSBASE);
 
 #ifdef PPC_HAVE_FPU
        /* Save FPU context, if any. */
        if (!fpu_save_to_mcontext(l, mcp, flagp))
@@ -196,8 +196,9 @@
 cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
 {
        struct trapframe * const tf = l->l_md.md_utf;
        const __greg_t * const gr = mcp->__gregs;
+       __greg_t saved_r2;
        int error;
 
        /* Restore GPR context, if any. */
        if (flags & _UC_CPU) {
@@ -213,8 +214,9 @@
                pcb->pcb_flags &= ~(PCB_FE0|PCB_FE1);
                pcb->pcb_flags |= gr[_REG_MSR] & (PCB_FE0|PCB_FE1);
 #endif
 
+               saved_r2 = tf->tf_fixreg[_REG_R2];
                (void)memcpy(&tf->tf_fixreg, gr, 32 * sizeof (gr[0]));
                tf->tf_cr   = gr[_REG_CR];
                tf->tf_lr   = gr[_REG_LR];
                tf->tf_srr0 = gr[_REG_PC];
@@ -228,8 +230,11 @@
                tf->tf_xer  = gr[_REG_XER];
 #ifdef PPC_OEA
                tf->tf_mq = gr[_REG_MQ];
 #endif
+
+               if (!(flags & _UC_TLSBASE))
+                       tf->tf_fixreg[_REG_R2] = saved_r2;
        }
 
 #ifdef PPC_HAVE_FPU
        /* Restore FPU context, if any. */
Index: sys/arch/sh3/include/mcontext.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sh3/include/mcontext.h,v
retrieving revision 1.9
diff -U 4 -r1.9 mcontext.h
--- sys/arch/sh3/include/mcontext.h     25 Feb 2011 14:07:13 -0000      1.9
+++ sys/arch/sh3/include/mcontext.h     12 Aug 2012 14:19:32 -0000
@@ -91,8 +91,9 @@
  * Machine dependent uc_flags
  */
 #define        _UC_SETSTACK            0x10000
 #define        _UC_CLRSTACK            0x20000
+#define        _UC_TLSBASE             0x80000
 
 static __inline void *
 __lwp_getprivate_fast(void)
 {
Index: sys/arch/sh3/sh3/sh3_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sh3/sh3/sh3_machdep.c,v
retrieving revision 1.100
diff -U 4 -r1.100 sh3_machdep.c
--- sys/arch/sh3/sh3/sh3_machdep.c      8 Jul 2012 20:14:12 -0000       1.100
+++ sys/arch/sh3/sh3/sh3_machdep.c      12 Aug 2012 14:19:32 -0000
@@ -431,9 +431,9 @@
        if ((ras_pc = (__greg_t)ras_lookup(l->l_proc,
            (void *) gr[_REG_PC])) != -1)
                gr[_REG_PC] = ras_pc;
 
-       *flags |= _UC_CPU;
+       *flags |= (_UC_CPU|_UC_TLSBASE);
 
        /* FPU context is currently not handled by the kernel. */
        memset(&mcp->__fpregs, 0, sizeof (mcp->__fpregs));
 }
@@ -464,9 +464,11 @@
                error = cpu_mcontext_validate(l, mcp);
                if (error)
                        return error;
 
+#if notanymore /* done in lwp_setprivate */
                tf->tf_gbr    = gr[_REG_GBR];
+#endif
                tf->tf_spc    = gr[_REG_PC];
                tf->tf_ssr    = gr[_REG_SR];
                tf->tf_macl   = gr[_REG_MACL];
                tf->tf_mach   = gr[_REG_MACH];
@@ -487,9 +489,10 @@
                tf->tf_r1     = gr[_REG_R1];
                tf->tf_r0     = gr[_REG_R0];
                tf->tf_r15    = gr[_REG_R15];
 
-               lwp_setprivate(l, (void *)(uintptr_t)gr[_REG_GBR]);
+               if (flags & _UC_TLSBASE)
+                       lwp_setprivate(l, (void *)(uintptr_t)gr[_REG_GBR]);
        }
 
 #if 0
        /* XXX: FPU context is currently not handled by the kernel. */
Index: sys/arch/sparc/include/mcontext.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/include/mcontext.h,v
retrieving revision 1.12
diff -U 4 -r1.12 mcontext.h
--- sys/arch/sparc/include/mcontext.h   25 Feb 2011 14:07:13 -0000      1.12
+++ sys/arch/sparc/include/mcontext.h   12 Aug 2012 14:19:32 -0000
@@ -33,8 +33,9 @@
 #define _SPARC_MCONTEXT_H_
 
 #define _UC_SETSTACK   0x00010000
 #define _UC_CLRSTACK   0x00020000
+#define _UC_TLSBASE    0x00080000
 
 /*
  * Layout of mcontext_t according the System V Application Binary Interface,
  * Edition 4.1, SPARC Processor ABI Supplement and updated for SPARC v9.
Index: sys/arch/sparc/sparc/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/sparc/machdep.c,v
retrieving revision 1.319
diff -U 4 -r1.319 machdep.c
--- sys/arch/sparc/sparc/machdep.c      21 May 2012 14:15:18 -0000      1.319
+++ sys/arch/sparc/sparc/machdep.c      12 Aug 2012 14:19:32 -0000
@@ -640,9 +640,9 @@
        r[_REG_O5] = tf->tf_out[5];
        r[_REG_O6] = tf->tf_out[6];
        r[_REG_O7] = tf->tf_out[7];
 
-       *flags |= _UC_CPU;
+       *flags |= (_UC_CPU|_UC_TLSBASE);
 
 #ifdef FPU_CONTEXT
        /*
         * Get the floating point registers
@@ -746,9 +746,11 @@
                tf->tf_global[3] = r[_REG_G3];
                tf->tf_global[4] = r[_REG_G4];
                tf->tf_global[5] = r[_REG_G5];
                tf->tf_global[6] = r[_REG_G6];
+#if notanymore /* done in lwp_setprivate */
                tf->tf_global[7] = r[_REG_G7];
+#endif
 
                tf->tf_out[0] = r[_REG_O0];
                tf->tf_out[1] = r[_REG_O1];
                tf->tf_out[2] = r[_REG_O2];
@@ -757,9 +759,10 @@
                tf->tf_out[5] = r[_REG_O5];
                tf->tf_out[6] = r[_REG_O6];
                tf->tf_out[7] = r[_REG_O7];
 
-               lwp_setprivate(l, (void *)(uintptr_t)r[_REG_G7]);
+               if (flags & _UC_TLSBASE)
+                       lwp_setprivate(l, (void *)(uintptr_t)r[_REG_G7]);
        }
 
 #ifdef FPU_CONTEXT
        if (flags & _UC_FPU) {
Index: sys/arch/sparc64/include/mcontext.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/include/mcontext.h,v
retrieving revision 1.8
diff -U 4 -r1.8 mcontext.h
--- sys/arch/sparc64/include/mcontext.h 16 Mar 2006 16:05:53 -0000      1.8
+++ sys/arch/sparc64/include/mcontext.h 12 Aug 2012 14:19:32 -0000
@@ -73,6 +73,7 @@
 } mcontext32_t;
 
 #define        _UC_SETSTACK    0x00010000
 #define        _UC_CLRSTACK    0x00020000
+#define        _UC_TLSBASE     0x00080000
 
 #endif /* _SPARC64_MCONTEXT_H_ */
Index: sys/arch/sparc64/sparc64/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/machdep.c,v
retrieving revision 1.267
diff -U 4 -r1.267 machdep.c
--- sys/arch/sparc64/sparc64/machdep.c  21 May 2012 14:15:18 -0000      1.267
+++ sys/arch/sparc64/sparc64/machdep.c  12 Aug 2012 14:19:32 -0000
@@ -2499,9 +2499,9 @@
                gr[_REG_PC] = ras_pc;
                gr[_REG_nPC] = ras_pc + 4;
        }
 
-       *flags |= _UC_CPU;
+       *flags |= (_UC_CPU|_UC_TLSBASE);
 
        mcp->__gwins = NULL;
 
 
@@ -2588,9 +2588,11 @@
                tf->tf_global[3] = (uint64_t)gr[_REG_G3];
                tf->tf_global[4] = (uint64_t)gr[_REG_G4];
                tf->tf_global[5] = (uint64_t)gr[_REG_G5];
                tf->tf_global[6] = (uint64_t)gr[_REG_G6];
+#if notanymore /* done in cpu_lwp_setprivate */
                tf->tf_global[7] = (uint64_t)gr[_REG_G7];
+#endif
                tf->tf_out[0]    = (uint64_t)gr[_REG_O0];
                tf->tf_out[1]    = (uint64_t)gr[_REG_O1];
                tf->tf_out[2]    = (uint64_t)gr[_REG_O2];
                tf->tf_out[3]    = (uint64_t)gr[_REG_O3];
@@ -2600,8 +2602,11 @@
                tf->tf_out[7]    = (uint64_t)gr[_REG_O7];
                /* %asi restored above; %fprs not yet supported. */
 
                /* XXX mcp->__gwins */
+
+               if (flags & _UC_TLSBASE)
+                       cpu_lwp_setprivate(l, (void *)(uintptr_t)gr[_REG_G7]);
        }
 
        /* Restore FP register context, if any. */
        if ((flags & _UC_FPU) != 0 && mcp->__fpregs.__fpu_en != 0) {
Index: sys/arch/sparc64/sparc64/netbsd32_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/netbsd32_machdep.c,v
retrieving revision 1.98
diff -U 4 -r1.98 netbsd32_machdep.c
--- sys/arch/sparc64/sparc64/netbsd32_machdep.c 21 May 2012 14:15:18 -0000      
1.98
+++ sys/arch/sparc64/sparc64/netbsd32_machdep.c 12 Aug 2012 14:19:32 -0000
@@ -776,9 +776,9 @@
        gr[_REG_O4]  = tf->tf_out[4];
        gr[_REG_O5]  = tf->tf_out[5];
        gr[_REG_O6]  = tf->tf_out[6];
        gr[_REG_O7]  = tf->tf_out[7];
-       *flags |= _UC_CPU;
+       *flags |= (_UC_CPU|_UC_TLSBASE);
 
        mcp->__gwins = 0;
 
 
@@ -1185,9 +1185,11 @@
                tf->tf_global[3] = (uint64_t)gr[_REG32_G3];
                tf->tf_global[4] = (uint64_t)gr[_REG32_G4];
                tf->tf_global[5] = (uint64_t)gr[_REG32_G5];
                tf->tf_global[6] = (uint64_t)gr[_REG32_G6];
+#if notanymore /* done in cpu_lwp_setprivate */
                tf->tf_global[7] = (uint64_t)gr[_REG32_G7];
+#endif
                tf->tf_out[0]    = (uint64_t)gr[_REG32_O0];
                tf->tf_out[1]    = (uint64_t)gr[_REG32_O1];
                tf->tf_out[2]    = (uint64_t)gr[_REG32_O2];
                tf->tf_out[3]    = (uint64_t)gr[_REG32_O3];
@@ -1196,9 +1198,10 @@
                tf->tf_out[6]    = (uint64_t)gr[_REG32_O6];
                tf->tf_out[7]    = (uint64_t)gr[_REG32_O7];
                /* %asi restored above; %fprs not yet supported. */
 
-               lwp_setprivate(l, (void *)(uintptr_t)gr[_REG_G7]);
+               if (flags & _UC_TLSBASE)
+                       cpu_lwp_setprivate(l, (void *)(uintptr_t)gr[_REG32_G7]);
 
                /* XXX mcp->__gwins */
        }
 
@@ -1280,13 +1283,13 @@
        gr[_REG32_O4]  = tf->tf_out[4];
        gr[_REG32_O5]  = tf->tf_out[5];
        gr[_REG32_O6]  = tf->tf_out[6];
        gr[_REG32_O7]  = tf->tf_out[7];
-       *flags |= _UC_CPU;
+       *flags |= (_UC_CPU|_UC_TLSBASE);
 
        mcp->__gwins = 0;
        mcp->__xrs.__xrs_id = 0;        /* Solaris extension? */
-       *flags |= _UC_CPU;
+       *flags |= (_UC_CPU|_UC_TLSBASE);
 
        /* Save FP register context, if any. */
        if (l->l_md.md_fpstate != NULL) {
 #ifdef notyet


Home | Main Index | Thread Index | Old Index