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