tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[PATCH] swapcontext vs libpthread
Here is an updated patch for sorting out swapcontext with libpthread,
with documentation and test cases.
I would appreciate feedback on LWP_PRESERVETLS flag to _lwp_create().
This tells the kernel that the TLS base register will be used by
libpthread and that setcontext() should leave it untouched.
This is done in kernel because it seems to be the easiest way:
another approach would be to have libpthread overriding setcontext(),
but that seems a bad choice: after unsetting _UC_TLSBASE it needs
to call the real setcontext, which means doing a system call from
libpthread. That looks wrong.
--
Emmanuel Dreyfus
manu%netbsd.org@localhost
Index: distrib/sets/lists/tests/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/tests/mi,v
retrieving revision 1.480
diff -U 4 -r1.480 mi
--- distrib/sets/lists/tests/mi 23 Jul 2012 04:21:39 -0000 1.480
+++ distrib/sets/lists/tests/mi 22 Aug 2012 16:38:36 -0000
@@ -571,8 +571,9 @@
./usr/libdata/debug/usr/tests/lib/libc/sys/t_sigaction.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/sys/t_sigqueue.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/sys/t_socketpair.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/sys/t_stat.debug
tests-lib-debug debug,atf
+./usr/libdata/debug/usr/tests/lib/libc/sys/t_swapcontext.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/sys/t_timer_create.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/sys/t_truncate.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/sys/t_ucontext.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/libc/sys/t_umask.debug
tests-lib-debug debug,atf
@@ -672,8 +673,9 @@
./usr/libdata/debug/usr/tests/lib/libpthread/t_sigsuspend.debug
tests-lib-tests debug,atf
./usr/libdata/debug/usr/tests/lib/libpthread/t_siglongjmp.debug
tests-lib-tests debug,atf
./usr/libdata/debug/usr/tests/lib/libpthread/t_sleep.debug
tests-lib-tests debug,atf
./usr/libdata/debug/usr/tests/lib/libpthread/t_status.debug
tests-obsolete obsolete
+./usr/libdata/debug/usr/tests/lib/libpthread/t_swapcontext.debug
tests-lib-tests debug,atf
./usr/libdata/debug/usr/tests/lib/librt
tests-lib-debug
./usr/libdata/debug/usr/tests/lib/librt/t_sched.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/librt/t_sem.debug
tests-lib-debug debug,atf
./usr/libdata/debug/usr/tests/lib/librumpclient
tests-lib-debug
@@ -2478,8 +2480,9 @@
./usr/tests/lib/libc/sys/t_sigaction tests-lib-tests atf
./usr/tests/lib/libc/sys/t_sigqueue tests-lib-tests atf
./usr/tests/lib/libc/sys/t_socketpair tests-lib-tests atf
./usr/tests/lib/libc/sys/t_stat tests-lib-tests
atf
+./usr/tests/lib/libc/sys/t_swapcontext tests-lib-tests atf
./usr/tests/lib/libc/sys/t_timer_create tests-lib-tests
atf
./usr/tests/lib/libc/sys/t_truncate tests-lib-tests atf
./usr/tests/lib/libc/sys/t_ucontext tests-lib-tests atf
./usr/tests/lib/libc/sys/t_umask tests-lib-tests atf
@@ -2706,8 +2709,9 @@
./usr/tests/lib/libpthread/t_sigsuspend tests-lib-tests
atf
./usr/tests/lib/libpthread/t_siglongjmp tests-lib-tests
atf
./usr/tests/lib/libpthread/t_sleep tests-lib-tests atf
./usr/tests/lib/libpthread/t_status tests-obsolete obsolete
+./usr/tests/lib/libpthread/t_swapcontext tests-lib-tests atf
./usr/tests/lib/librt tests-lib-tests atf
./usr/tests/lib/librt/Atffile tests-lib-tests atf
./usr/tests/lib/librt/t_sched tests-lib-tests atf
./usr/tests/lib/librt/t_sem tests-lib-tests atf
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 22 Aug 2012 16:39:00 -0000
@@ -46,15 +46,21 @@
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.
+.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 22 Aug 2012 16:39:00 -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 22 Aug 2012 16:39:00 -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 22 Aug 2012 16:39:01 -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 22 Aug 2012 16:39:01 -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 22 Aug 2012 16:39:02 -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 22 Aug 2012 16:39:02 -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 22 Aug 2012 16:39:02 -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 22 Aug 2012 16:39:02 -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 22 Aug 2012 16:39:02 -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 22 Aug 2012 16:39:02 -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 22 Aug 2012 16:39:02 -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
Index: sys/kern/sys_lwp.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_lwp.c,v
retrieving revision 1.54
diff -U 4 -r1.54 sys_lwp.c
--- sys/kern/sys_lwp.c 21 May 2012 14:15:19 -0000 1.54
+++ sys/kern/sys_lwp.c 22 Aug 2012 16:39:04 -0000
@@ -118,8 +118,12 @@
l2->l_stat = LSSUSPENDED;
p->p_nrlwps--;
lwp_unlock_to(l2, spc->spc_lwplock);
}
+
+ if (flags & LWP_PRESERVETLS)
+ p->p_flag |= PK_PRESERVETLS;
+
mutex_exit(p->p_lock);
return 0;
}
Index: sys/kern/sys_sig.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_sig.c,v
retrieving revision 1.38
diff -U 4 -r1.38 sys_sig.c
--- sys/kern/sys_sig.c 18 Jul 2012 20:30:07 -0000 1.38
+++ sys/kern/sys_sig.c 22 Aug 2012 16:39:04 -0000
@@ -343,8 +343,10 @@
return error;
if ((uc.uc_flags & _UC_CPU) == 0)
return EINVAL;
mutex_enter(p->p_lock);
+ if (p->p_flag & PK_PRESERVETLS)
+ uc.uc_flags &= ~_UC_TLSBASE;
error = setucontext(l, &uc);
mutex_exit(p->p_lock);
if (error)
return error;
Index: sys/sys/lwp.h
===================================================================
RCS file: /cvsroot/src/sys/sys/lwp.h,v
retrieving revision 1.163
diff -U 4 -r1.163 lwp.h
--- sys/sys/lwp.h 22 Jul 2012 22:40:18 -0000 1.163
+++ sys/sys/lwp.h 22 Aug 2012 16:39:05 -0000
@@ -512,8 +512,9 @@
/* Flags for _lwp_create(), as per Solaris. */
#define LWP_DETACHED 0x00000040
#define LWP_SUSPENDED 0x00000080
+#define LWP_PRESERVETLS 0x00000100
/* Kernel-internal flags for LWP creation. */
#define LWP_PIDLID 0x40000000
#define LWP_VFORK 0x80000000
Index: sys/sys/proc.h
===================================================================
RCS file: /cvsroot/src/sys/sys/proc.h,v
retrieving revision 1.317
diff -U 4 -r1.317 proc.h
--- sys/sys/proc.h 22 Jul 2012 22:40:18 -0000 1.317
+++ sys/sys/proc.h 22 Aug 2012 16:39:05 -0000
@@ -342,8 +342,9 @@
*/
#define PK_ADVLOCK 0x00000001 /* Process may hold a POSIX advisory
lock */
#define PK_SYSTEM 0x00000002 /* System process (kthread) */
#define PK_SYSVSEM 0x00000004 /* Used SysV semaphores */
+#define PK_PRESERVETLS 0x00000008 /* TLS base untouched by setcontext */
#define PK_SUGID 0x00000100 /* Had set id privileges since last
exec */
#define PK_EXEC 0x00004000 /* Process called exec */
#define PK_NOCLDWAIT 0x00020000 /* No zombies if child dies */
#define PK_32 0x00040000 /* 32-bit process (used on 64-bit
kernels) */
Index: sys/sys/ucontext.h
===================================================================
RCS file: /cvsroot/src/sys/sys/ucontext.h,v
retrieving revision 1.16
diff -U 4 -r1.16 ucontext.h
--- sys/sys/ucontext.h 21 May 2012 14:15:19 -0000 1.16
+++ sys/sys/ucontext.h 22 Aug 2012 16:39:05 -0000
@@ -56,15 +56,20 @@
#define _UC_SIGMASK 0x01 /* valid uc_sigmask */
#define _UC_STACK 0x02 /* valid uc_stack */
#define _UC_CPU 0x04 /* valid GPR context in
uc_mcontext */
#define _UC_FPU 0x08 /* valid FPU context in
uc_mcontext */
-#define _UC_MD 0x40070020 /* MD bits. see below */
+#define _UC_MD 0x400f0020 /* MD bits. see below */
/*
* _UC_MD includes:
+ * _UC_TLSBASE 0x00080000 (all ports except hppa, mips, alpha)
+ * 0x00040000 (hppa, mips)
+ * 0x00000020 (alpha)
+ * _UC_UNIQUE 0x00000020 synonym of _UC_TLSBASE on alpha
* _UC_SETSTACK 0x00010000 (many ports) and 0x00020000 (arm)
* _UC_CLRSTACK 0x00020000 (many ports) and 0x00040000 (arm)
* _UC_POWERPC_VEC 0x00010000 (powerpc)
+ * _UC_POWERPC_SPE 0x00020000 (powerpc)
* _UC_M68K_UC_USER 0x40000000 (m68k)
* _UC_UNIQUE 0x00000020 (alpha)
* _UC_ARM_VFP 0x00010000 (arm)
* _UC_VM 0x00040000 (i386)
Index: tests/lib/libc/sys/Makefile
===================================================================
RCS file: /cvsroot/src/tests/lib/libc/sys/Makefile,v
retrieving revision 1.26
diff -U 4 -r1.26 Makefile
--- tests/lib/libc/sys/Makefile 22 Jun 2012 18:45:23 -0000 1.26
+++ tests/lib/libc/sys/Makefile 22 Aug 2012 16:44:40 -0000
@@ -54,8 +54,9 @@
TESTS_C+= t_setuid
TESTS_C+= t_sigaction
TESTS_C+= t_sigqueue
TESTS_C+= t_socketpair
+TESTS_C+= t_swapcontext
TESTS_C+= t_stat
TESTS_C+= t_timer_create
TESTS_C+= t_truncate
TESTS_C+= t_ucontext
Index: tests/lib/libpthread/Makefile
===================================================================
RCS file: /cvsroot/src/tests/lib/libpthread/Makefile,v
retrieving revision 1.7
diff -U 4 -r1.7 Makefile
--- tests/lib/libpthread/Makefile 6 Apr 2011 16:04:16 -0000 1.7
+++ tests/lib/libpthread/Makefile 22 Aug 2012 16:39:05 -0000
@@ -34,8 +35,9 @@
TESTS_C+= t_sigmask
TESTS_C+= t_sigsuspend
TESTS_C+= t_siglongjmp
TESTS_C+= t_sleep
+TESTS_C+= t_swapcontext
LDADD.t_sem+= -lrt
BINDIR= ${TESTSDIR}
--- tests/lib/libc/sys/t_swapcontext.c.orig 1970-01-01 01:00:00.000000000
+0100
+++ tests/lib/libc/sys/t_swapcontext.c 2012-08-22 10:56:34.000000000 +0200
@@ -0,0 +1,133 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 2012 Emmanuel Dreyfus. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD");
+
+#include <ucontext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <lwp.h>
+
+#include <atf-c.h>
+
+#define STACKSIZE 65536
+
+char stack[STACKSIZE];
+ucontext_t nctx;
+ucontext_t octx;
+void *otls;
+void *ntls;
+int val1, val2;
+int alter_tlsbase;
+
+/* ARGSUSED0 */
+static void
+swapfunc(void *arg)
+{
+ ntls = _lwp_getprivate();
+ printf("after swapcontext TLS pointer = %p\n", ntls);
+
+ if (alter_tlsbase) {
+ ATF_REQUIRE_EQ(ntls, &val1);
+ printf("TLS pointer modified by swapcontext()\n");
+ } else {
+ ATF_REQUIRE_EQ(ntls, &val2);
+ printf("TLS pointer left untouched by swapcontext()\n");
+ }
+
+ /* Go back in main */
+ ATF_REQUIRE(swapcontext(&nctx, &octx));
+
+ /* NOTREACHED */
+ return;
+}
+
+static void
+mainfunc(void)
+{
+ printf("Testing if swapcontext() alters TLS pointer if _UC_TLSBASE "
+ "is %s\n", (alter_tlsbase) ? "left set" : "cleared");
+
+ _lwp_setprivate(&val1);
+ printf("before swapcontext TLS pointer = %p\n", &val1);
+
+ ATF_REQUIRE(getcontext(&nctx) == 0);
+
+ nctx.uc_stack.ss_sp = stack;
+ nctx.uc_stack.ss_size = sizeof(stack);
+
+#ifndef _UC_TLSBASE
+ ATF_REQUIRE_MSG(0, "_UC_TLSBASE is not defined");
+#else /* _UC_TLSBASE */
+ ATF_REQUIRE(nctx.uc_flags & _UC_TLSBASE);
+ if (!alter_tlsbase)
+ nctx.uc_flags &= ~_UC_TLSBASE;
+#endif /* _UC_TLSBASE */
+
+ makecontext(&nctx, (void *)*swapfunc, 0);
+
+ _lwp_setprivate(&val2);
+ otls = _lwp_getprivate();
+ printf("before swapcontext TLS pointer = %p\n", otls);
+ ATF_REQUIRE(swapcontext(&octx, &nctx) == 0);
+
+ printf("Test completed\n");
+}
+
+
+ATF_TC(swapcontext1);
+ATF_TC_HEAD(swapcontext1, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Testing if swapcontext() can let "
+ "TLS pointer untouched");
+}
+ATF_TC_BODY(swapcontext1, tc)
+{
+ alter_tlsbase = 0;
+ mainfunc();
+}
+
+ATF_TC(swapcontext2);
+ATF_TC_HEAD(swapcontext2, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Testing if swapcontext() can "
+ "modify TLS pointer");
+}
+ATF_TC_BODY(swapcontext2, tc)
+{
+ alter_tlsbase = 1;
+ mainfunc();
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, swapcontext1);
+ ATF_TP_ADD_TC(tp, swapcontext2);
+
+ return atf_no_error();
+}
--- tests/lib/libpthread/t_swapcontext.c.orig 1970-01-01 01:00:00.000000000
+0100
+++ tests/lib/libpthread/t_swapcontext.c 2012-08-22 10:46:13.000000000
+0200
@@ -0,0 +1,110 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 2012 Emmanuel Dreyfus. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD");
+
+#include <pthread.h>
+#include <ucontext.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <atf-c.h>
+
+#include "h_common.h"
+
+#define STACKSIZE 65536
+
+char stack[STACKSIZE];
+ucontext_t nctx;
+ucontext_t octx;
+void *oself;
+void *nself;
+int val1, val2;
+
+/* ARGSUSED0 */
+static void
+swapfunc(void *arg)
+{
+ /*
+ * If the test fails, we are very likely to crash
+ * without the opportunity to report
+ */
+ nself = (void *)pthread_self();
+ printf("after swapcontext self = %p\n", nself);
+
+ ATF_REQUIRE_EQ(oself, nself);
+ printf("Test succeeded\n");
+
+ return;
+}
+
+/* ARGSUSED0 */
+static void *
+threadfunc(void *arg)
+{
+ nctx.uc_stack.ss_sp = stack;
+ nctx.uc_stack.ss_size = sizeof(stack);
+
+ makecontext(&nctx, (void *)*swapfunc, 0);
+
+ oself = (void *)pthread_self();
+ printf("before swapcontext self = %p\n", oself);
+ PTHREAD_REQUIRE(swapcontext(&octx, &nctx));
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+
+ATF_TC(swapcontext1);
+ATF_TC_HEAD(swapcontext1, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Testing if swapcontext() "
+ "alters pthread_self()");
+}
+ATF_TC_BODY(swapcontext1, tc)
+{
+ pthread_t thread;
+
+ oself = (void *)&val1;
+ nself = (void *)&val2;
+
+ printf("Testing if swapcontext() alters pthread_self()\n");
+
+ PTHREAD_REQUIRE(getcontext(&nctx));
+ PTHREAD_REQUIRE(pthread_create(&thread, NULL, threadfunc, NULL));
+
+ return;
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, swapcontext1);
+
+ return atf_no_error();
+}
Home |
Main Index |
Thread Index |
Old Index