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