Module Name:    src
Committed By:   manu
Date:           Wed Sep 12 02:00:55 UTC 2012

Modified Files:
        src/distrib/sets/lists/tests: mi
        src/lib/libc/arch/hppa/gen: swapcontext.S
        src/lib/libc/arch/mips/gen: _resumecontext.S swapcontext.S
        src/lib/libc/arch/powerpc64/gen: swapcontext.S
        src/lib/libc/arch/sparc/gen: swapcontext.S
        src/lib/libc/arch/sparc64/gen: swapcontext.S
        src/lib/libc/include: extern.h
        src/lib/libc/sys: Makefile.inc
        src/lib/libpthread: pthread_specific.c
        src/sys/arch/alpha/alpha: machdep.c
        src/sys/arch/alpha/include: mcontext.h
        src/sys/arch/sh3/include: mcontext.h
        src/sys/arch/sparc/include: mcontext.h
        src/sys/arch/sparc64/include: mcontext.h
        src/sys/sys: ucontext.h
        src/tests/lib/libc/sys: Makefile
        src/tests/lib/libpthread: Makefile
Added Files:
        src/tests/lib/libc/sys: t_swapcontext.c
        src/tests/lib/libpthread: t_swapcontext.c

Log Message:
setcontext() used to be incompatible with -lpthread since it affected
the TLS pointer, therefore wrecking the pthread environement.

Some ports had _UC_TLSBASE flag or equivalent (_UC_UNIQUE on alpha)
that controlled whether setcontext() would change the TLS pointer.
This change let libpthread override setcontext() with its own version
that unsets _UC_TLSBASE, enabling safe usage of setcontext() with
-lpthread.

We also have the following required changes here:
- rename alpha's _UC_UNIQUE into _UC_TLSBASE
- add _UC_TLSBASE definition in header file for all ports
  (powerpc, sh3, sparc and sparc64 lack the implementation for now)
- introduce a libc stub that can be overriden for setcontext()
- modify MD libcs swapcontext() implementations so that they use the
  setcontext() libc stub instead of doing a plain system call.

While we are there:
- document various MD _UC_* flags in header file
- add libc and libpthread tests for swapcontext() behavior
  (hopefully helpful to spot MD problems introduced with this change)

Future work:
- Deciding whether kernel support or _UC_TLSBASE should be added for
  powerpc, sh3, sparc and sparc64 is left to portmasters
  sparc64

Approved by core@


To generate a diff of this commit:
cvs rdiff -u -r1.490 -r1.491 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.4 -r1.5 src/lib/libc/arch/hppa/gen/swapcontext.S
cvs rdiff -u -r1.6 -r1.7 src/lib/libc/arch/mips/gen/_resumecontext.S
cvs rdiff -u -r1.4 -r1.5 src/lib/libc/arch/mips/gen/swapcontext.S
cvs rdiff -u -r1.3 -r1.4 src/lib/libc/arch/powerpc64/gen/swapcontext.S
cvs rdiff -u -r1.3 -r1.4 src/lib/libc/arch/sparc/gen/swapcontext.S
cvs rdiff -u -r1.5 -r1.6 src/lib/libc/arch/sparc64/gen/swapcontext.S
cvs rdiff -u -r1.19 -r1.20 src/lib/libc/include/extern.h
cvs rdiff -u -r1.215 -r1.216 src/lib/libc/sys/Makefile.inc
cvs rdiff -u -r1.21 -r1.22 src/lib/libpthread/pthread_specific.c
cvs rdiff -u -r1.341 -r1.342 src/sys/arch/alpha/alpha/machdep.c
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/alpha/include/mcontext.h
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/sh3/include/mcontext.h
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/sparc/include/mcontext.h
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/sparc64/include/mcontext.h
cvs rdiff -u -r1.16 -r1.17 src/sys/sys/ucontext.h
cvs rdiff -u -r1.27 -r1.28 src/tests/lib/libc/sys/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/lib/libc/sys/t_swapcontext.c
cvs rdiff -u -r1.7 -r1.8 src/tests/lib/libpthread/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/lib/libpthread/t_swapcontext.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.490 src/distrib/sets/lists/tests/mi:1.491
--- src/distrib/sets/lists/tests/mi:1.490	Sun Aug 26 23:03:21 2012
+++ src/distrib/sets/lists/tests/mi	Wed Sep 12 02:00:51 2012
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.490 2012/08/26 23:03:21 jmmv Exp $
+# $NetBSD: mi,v 1.491 2012/09/12 02:00:51 manu Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -573,6 +573,7 @@
 ./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
@@ -674,6 +675,7 @@
 ./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
@@ -2486,6 +2488,7 @@
 ./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
@@ -2714,6 +2717,7 @@
 ./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

Index: src/lib/libc/arch/hppa/gen/swapcontext.S
diff -u src/lib/libc/arch/hppa/gen/swapcontext.S:1.4 src/lib/libc/arch/hppa/gen/swapcontext.S:1.5
--- src/lib/libc/arch/hppa/gen/swapcontext.S:1.4	Mon Apr 28 20:22:56 2008
+++ src/lib/libc/arch/hppa/gen/swapcontext.S	Wed Sep 12 02:00:52 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: swapcontext.S,v 1.4 2008/04/28 20:22:56 martin Exp $	*/
+/*	$NetBSD: swapcontext.S,v 1.5 2012/09/12 02:00:52 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
 #include <machine/mcontext.h>
 
 #if defined(SYSLIBC_SCCS) && !defined(lint)
-	RCSID("$NetBSD: swapcontext.S,v 1.4 2008/04/28 20:22:56 martin Exp $")
+	RCSID("$NetBSD: swapcontext.S,v 1.5 2012/09/12 02:00:52 manu Exp $")
 #endif /* SYSLIBC_SCCS && !lint */
 
 LEAF_ENTRY(swapcontext)
@@ -44,10 +44,15 @@ LEAF_ENTRY(swapcontext)
 
 	ldw	HPPA_FRAME_ARG(0)(%sp), %arg1
 	ldw	HPPA_FRAME_ARG(1)(%sp), %arg0
-	stw	%r0, (_OFFSETOF_UC_GREGS + _REG_RET0 * SZREG)(%arg1)
+
+	ldw	HPPA_FRAME_CRP(%sp), %rp
 	ldo	4(%rp), %r1
 	stw	%r1, (_OFFSETOF_UC_GREGS + _REG_PCOQT * SZREG)(%arg1)
 	stw	%rp, (_OFFSETOF_UC_GREGS + _REG_PCOQH * SZREG)(%arg1)
-	SYSCALL(setcontext)
+	bl	setcontext, %rp
+	stw	%r0, (_OFFSETOF_UC_GREGS + _REG_RET0 * SZREG)(%arg1)
+
+	ldw	HPPA_FRAME_CRP(%sp), %rp
+	bv,n	%r0(%rp)
 EXIT(swapcontext)
 	.end

Index: src/lib/libc/arch/mips/gen/_resumecontext.S
diff -u src/lib/libc/arch/mips/gen/_resumecontext.S:1.6 src/lib/libc/arch/mips/gen/_resumecontext.S:1.7
--- src/lib/libc/arch/mips/gen/_resumecontext.S:1.6	Mon Dec 14 01:07:42 2009
+++ src/lib/libc/arch/mips/gen/_resumecontext.S	Wed Sep 12 02:00:52 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: _resumecontext.S,v 1.6 2009/12/14 01:07:42 matt Exp $	*/
+/*	$NetBSD: _resumecontext.S,v 1.7 2012/09/12 02:00:52 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
 #include "assym.h"
 
 #if defined(SYSLIBC_SCCS) && !defined(lint)
-	RCSID("$NetBSD: _resumecontext.S,v 1.6 2009/12/14 01:07:42 matt Exp $")
+	RCSID("$NetBSD: _resumecontext.S,v 1.7 2012/09/12 02:00:52 manu Exp $")
 #endif /* SYSLIBC_SCCS && !lint */
 
 	.set	reorder
@@ -53,7 +53,7 @@ LEAF_NOPROFILE(__resumecontext)
 	PTR_L		a0, _OFFSETOF_UC_LINK(a0)	# linked context?
 	beq		a0, zero, 1f			#   nope, exit process
 	nop
-	SYSTRAP(setcontext)				#   yes, become it.
+	PIC_TAILCALL(setcontext)			#   yes, become it.
 	/* NOTREACHED (in theory) */
 	li		a0, -1				# failure, 
 1:

Index: src/lib/libc/arch/mips/gen/swapcontext.S
diff -u src/lib/libc/arch/mips/gen/swapcontext.S:1.4 src/lib/libc/arch/mips/gen/swapcontext.S:1.5
--- src/lib/libc/arch/mips/gen/swapcontext.S:1.4	Mon Dec 14 01:07:42 2009
+++ src/lib/libc/arch/mips/gen/swapcontext.S	Wed Sep 12 02:00:52 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: swapcontext.S,v 1.4 2009/12/14 01:07:42 matt Exp $	*/
+/*	$NetBSD: swapcontext.S,v 1.5 2012/09/12 02:00:52 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
 #include "assym.h"
 
 #if defined(SYSLIBC_SCCS) && !defined(lint)
-	RCSID("$NetBSD: swapcontext.S,v 1.4 2009/12/14 01:07:42 matt Exp $")
+	RCSID("$NetBSD: swapcontext.S,v 1.5 2012/09/12 02:00:52 manu Exp $")
 #endif /* SYSLIBC_SCCS && !lint */
 
 	.set	reorder
@@ -57,7 +57,7 @@ NESTED(swapcontext, CALLFRAME_SIZ, ra)
 	REG_S		v0, _OFFSETOF_UC_GREGS_SP(v1)
 	REG_EPILOGUE
 
-	SYSTRAP(setcontext)
+	PIC_TAILCALL(setcontext)
 	/* NOTREACHED */
 1:
 	PTR_ADDU	sp, sp, CALLFRAME_SIZ

Index: src/lib/libc/arch/powerpc64/gen/swapcontext.S
diff -u src/lib/libc/arch/powerpc64/gen/swapcontext.S:1.3 src/lib/libc/arch/powerpc64/gen/swapcontext.S:1.4
--- src/lib/libc/arch/powerpc64/gen/swapcontext.S:1.3	Mon Apr 28 20:22:57 2008
+++ src/lib/libc/arch/powerpc64/gen/swapcontext.S	Wed Sep 12 02:00:52 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: swapcontext.S,v 1.3 2008/04/28 20:22:57 martin Exp $	*/
+/*	$NetBSD: swapcontext.S,v 1.4 2012/09/12 02:00:52 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 	.text
-	.asciz "$NetBSD: swapcontext.S,v 1.3 2008/04/28 20:22:57 martin Exp $"
+	.asciz "$NetBSD: swapcontext.S,v 1.4 2012/09/12 02:00:52 manu Exp $"
 #endif /* LIBC_SCCS && !lint */
 
 ENTRY(swapcontext)
@@ -52,8 +52,8 @@ ENTRY(swapcontext)
 	std	%r0,mc_off+34*8(%r11)	# 	pc <- lr
 	la	%r0,16(%r1)
 	std	%r0,mc_off+1*8(%r11)		# adjust sp
-	ld	%r3,SF_PARAM+8(%r1)			# load ucp
-	bl	.setcontext			# setcontext(ucp)
+	ld	%r3,SF_PARAM+8(%r1)		# load ucp
+	bl	PIC_PLT(_C_LABEL(setcontext))	# setcontext(ucp)
 	nop
 1:
 	ld	%r0,SF_SZ+SF_LR(%r1)

Index: src/lib/libc/arch/sparc/gen/swapcontext.S
diff -u src/lib/libc/arch/sparc/gen/swapcontext.S:1.3 src/lib/libc/arch/sparc/gen/swapcontext.S:1.4
--- src/lib/libc/arch/sparc/gen/swapcontext.S:1.3	Mon Apr 28 20:22:57 2008
+++ src/lib/libc/arch/sparc/gen/swapcontext.S	Wed Sep 12 02:00:53 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: swapcontext.S,v 1.3 2008/04/28 20:22:57 martin Exp $	*/
+/*	$NetBSD: swapcontext.S,v 1.4 2012/09/12 02:00:53 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 #include "SYS.h"
 
 #if defined(LIBC_SCCS) && !defined(lint)
-	RCSID("$NetBSD: swapcontext.S,v 1.3 2008/04/28 20:22:57 martin Exp $")
+	RCSID("$NetBSD: swapcontext.S,v 1.4 2012/09/12 02:00:53 manu Exp $")
 #endif /* LIBC_SCCS && !lint */
 
 ENTRY(swapcontext)
@@ -49,8 +49,13 @@ ENTRY(swapcontext)
 	add	%o7, 8, %o1
 	st	%o1, [%o2 + 40 + 1 * 4]		! gr[_REG_PC] = retaddr
 
-	mov	%o3, %o0
-	mov	%o1, %g2			! optimize `return'
-	mov	SYS_setcontext|SYSCALL_G2RFLAG, %g1
-	t	ST_SYSCALL
-	ERROR()
+#ifdef PIC
+	PIC_PROLOGUE(%g1, %g2)			! %g1 = _GLOBAL_OFFSET_TABLE
+	set	_C_LABEL(setcontext), %g2
+	ld	[%g1 + %g2], %g1
+	jmp	%g1
+	 mov	%o3, %o0
+#else
+	jmp	_C_LABEL(setcontext)
+	 mov	%o3, %o0
+#endif

Index: src/lib/libc/arch/sparc64/gen/swapcontext.S
diff -u src/lib/libc/arch/sparc64/gen/swapcontext.S:1.5 src/lib/libc/arch/sparc64/gen/swapcontext.S:1.6
--- src/lib/libc/arch/sparc64/gen/swapcontext.S:1.5	Mon Mar 28 11:19:13 2011
+++ src/lib/libc/arch/sparc64/gen/swapcontext.S	Wed Sep 12 02:00:53 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: swapcontext.S,v 1.5 2011/03/28 11:19:13 martin Exp $	*/
+/*	$NetBSD: swapcontext.S,v 1.6 2012/09/12 02:00:53 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 #include "SYS.h"
 
 #if defined(LIBC_SCCS) && !defined(lint)
-	RCSID("$NetBSD: swapcontext.S,v 1.5 2011/03/28 11:19:13 martin Exp $")
+	RCSID("$NetBSD: swapcontext.S,v 1.6 2012/09/12 02:00:53 manu Exp $")
 #endif /* LIBC_SCCS && !lint */
 
 
@@ -50,8 +50,17 @@ ENTRY(swapcontext)
 	add	%o7, 8, %o1
 	stx	%o1, [%o2 + 64 + 1 * 8]		/* gr[_REG_PC] = retaddr */
 
-	mov	%o3, %o0
-	mov	%o1, %g5			/* optimize `return' */
-	mov	SYS_setcontext|SYSCALL_G5RFLAG, %g1
-	t	ST_SYSCALL
-	ERROR()
+#ifdef	PIC
+	PIC_PROLOGUE(%g5,%o4)			/* %g5 = _GLOBAL_OFFSET_TABLE */
+#ifdef	BIGPIC
+	set	_C_LABEL(setcontext), %o6
+	ldx	[%g5+%o6], %o5
+#else
+	ldx	[%g5+_C_LABEL(setcontext)], %o5
+#endif
+	jmp	%o5
+	 mov	%o3, %o0
+#else
+	ba,a	_C_LABEL(setcontext)
+	 mov	%o3, %o0
+#endif

Index: src/lib/libc/include/extern.h
diff -u src/lib/libc/include/extern.h:1.19 src/lib/libc/include/extern.h:1.20
--- src/lib/libc/include/extern.h:1.19	Mon Sep 19 21:24:58 2011
+++ src/lib/libc/include/extern.h	Wed Sep 12 02:00:53 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: extern.h,v 1.19 2011/09/19 21:24:58 joerg Exp $	*/
+/*	$NetBSD: extern.h,v 1.20 2012/09/12 02:00:53 manu Exp $	*/
 
 /*
  * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
@@ -25,6 +25,7 @@
  */
 
 #include <stdarg.h>
+#include <ucontext.h>
 
 __BEGIN_DECLS
 extern char *__minbrk;
@@ -67,4 +68,6 @@ int	vsnprintf_ss(char * __restrict, size
 void	_malloc_prefork(void);
 void	_malloc_postfork(void);
 
+int	_sys_setcontext(const ucontext_t *);
+
 __END_DECLS

Index: src/lib/libc/sys/Makefile.inc
diff -u src/lib/libc/sys/Makefile.inc:1.215 src/lib/libc/sys/Makefile.inc:1.216
--- src/lib/libc/sys/Makefile.inc:1.215	Fri Jun 22 18:28:38 2012
+++ src/lib/libc/sys/Makefile.inc	Wed Sep 12 02:00:53 2012
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.inc,v 1.215 2012/06/22 18:28:38 christos Exp $
+#	$NetBSD: Makefile.inc,v 1.216 2012/09/12 02:00:53 manu Exp $
 #	@(#)Makefile.inc	8.3 (Berkeley) 10/24/94
 
 # sys sources
@@ -120,7 +120,7 @@ ASM=	access.S acct.S \
 	rasctl.S readlinkat.S reboot.S recvfrom.S recvmmsg.S recvmsg.S rename.S \
 		renameat.S revoke.S rmdir.S \
 	semconfig.S semget.S semop.S \
-		sendmmsg.S sendmsg.S sendto.S setegid.S setcontext.S seteuid.S \
+		sendmmsg.S sendmsg.S sendto.S setegid.S seteuid.S \
 		setgid.S setgroups.S __setitimer50.S __setlogin.S setpgid.S \
 		setpriority.S \
 		setregid.S setreuid.S setrlimit.S setsid.S setsockopt.S \
@@ -156,7 +156,7 @@ WEAKASM= accept.S __aio_suspend50.S clos
 	__pollts50.S __pselect50.S read.S readlink.S \
 	readv.S _sched_setparam.S _sched_getparam.S _sched_setaffinity.S \
 	_sched_getaffinity.S sched_yield.S \
-	__select50.S __sigprocmask14.S __sigsuspend14.S sysarch.S \
+	__select50.S setcontext.S __sigprocmask14.S __sigsuspend14.S sysarch.S \
 	__wait450.S write.S writev.S
 
 NOERR=	getegid.S geteuid.S getgid.S getpid.S getppid.S getuid.S \

Index: src/lib/libpthread/pthread_specific.c
diff -u src/lib/libpthread/pthread_specific.c:1.21 src/lib/libpthread/pthread_specific.c:1.22
--- src/lib/libpthread/pthread_specific.c:1.21	Mon Jun 23 10:38:39 2008
+++ src/lib/libpthread/pthread_specific.c	Wed Sep 12 02:00:53 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: pthread_specific.c,v 1.21 2008/06/23 10:38:39 ad Exp $	*/
+/*	$NetBSD: pthread_specific.c,v 1.22 2012/09/12 02:00:53 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc.
@@ -30,19 +30,26 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_specific.c,v 1.21 2008/06/23 10:38:39 ad Exp $");
+__RCSID("$NetBSD: pthread_specific.c,v 1.22 2012/09/12 02:00:53 manu Exp $");
 
 /* Functions and structures dealing with thread-specific data */
 
 #include "pthread.h"
 #include "pthread_int.h"
 
+#include <string.h>
 #include <sys/lwpctl.h>
 
+#include "../libc/include/extern.h" /* for _sys_setcontext() */
+
+int	pthread_setcontext(const ucontext_t *);
+
 __strong_alias(__libc_thr_setspecific,pthread_setspecific)
 __strong_alias(__libc_thr_getspecific,pthread_getspecific)
 __strong_alias(__libc_thr_curcpu,pthread_curcpu_np)
 
+__strong_alias(setcontext,pthread_setcontext)
+
 int
 pthread_setspecific(pthread_key_t key, const void *value)
 {
@@ -75,3 +82,16 @@ pthread_curcpu_np(void)
 
 	return pthread__self()->pt_lwpctl->lc_curcpu;
 }
+
+/*
+ * Override setcontext so that pthread private pointer is preserved
+ */
+int
+pthread_setcontext(const ucontext_t *ucp)
+{
+	ucontext_t uc;
+
+	(void)memcpy(&uc, ucp, sizeof(uc));
+	uc.uc_flags &= ~_UC_TLSBASE;
+	return _sys_setcontext(&uc);
+}

Index: src/sys/arch/alpha/alpha/machdep.c
diff -u src/sys/arch/alpha/alpha/machdep.c:1.341 src/sys/arch/alpha/alpha/machdep.c:1.342
--- src/sys/arch/alpha/alpha/machdep.c:1.341	Sat Jul 28 00:57:04 2012
+++ src/sys/arch/alpha/alpha/machdep.c	Wed Sep 12 02:00:53 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.341 2012/07/28 00:57:04 matt Exp $ */
+/* $NetBSD: machdep.c,v 1.342 2012/09/12 02:00:53 manu Exp $ */
 
 /*-
  * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.341 2012/07/28 00:57:04 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.342 2012/09/12 02:00:53 manu Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1793,7 +1793,7 @@ cpu_getmcontext(struct lwp *l, mcontext_
 	    (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)) {
@@ -1840,7 +1840,7 @@ cpu_setmcontext(struct lwp *l, const mco
 		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) {

Index: src/sys/arch/alpha/include/mcontext.h
diff -u src/sys/arch/alpha/include/mcontext.h:1.7 src/sys/arch/alpha/include/mcontext.h:1.8
--- src/sys/arch/alpha/include/mcontext.h:1.7	Fri Feb 25 14:07:12 2011
+++ src/sys/arch/alpha/include/mcontext.h	Wed Sep 12 02:00:54 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: mcontext.h,v 1.7 2011/02/25 14:07:12 joerg Exp $	*/
+/*	$NetBSD: mcontext.h,v 1.8 2012/09/12 02:00:54 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -93,7 +93,7 @@ typedef struct {
 } mcontext_t;
 
 /* Machine-dependent uc_flags */
-#define _UC_UNIQUE	0x20	/* valid process-unique value in _REG_UNIQUE */
+#define _UC_TLSBASE	0x20	/* valid process-unique value in _REG_UNIQUE */
 
 #define _UC_MACHINE_SP(uc)	((uc)->uc_mcontext.__gregs[_REG_SP])
 #define _UC_MACHINE_PC(uc)	((uc)->uc_mcontext.__gregs[_REG_PC])

Index: src/sys/arch/sh3/include/mcontext.h
diff -u src/sys/arch/sh3/include/mcontext.h:1.9 src/sys/arch/sh3/include/mcontext.h:1.10
--- src/sys/arch/sh3/include/mcontext.h:1.9	Fri Feb 25 14:07:13 2011
+++ src/sys/arch/sh3/include/mcontext.h	Wed Sep 12 02:00:54 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: mcontext.h,v 1.9 2011/02/25 14:07:13 joerg Exp $	*/
+/*	$NetBSD: mcontext.h,v 1.10 2012/09/12 02:00:54 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -92,6 +92,7 @@ typedef struct {
  */
 #define	_UC_SETSTACK		0x10000
 #define	_UC_CLRSTACK		0x20000
+#define	_UC_TLSBASE		0x80000
 
 static __inline void *
 __lwp_getprivate_fast(void)

Index: src/sys/arch/sparc/include/mcontext.h
diff -u src/sys/arch/sparc/include/mcontext.h:1.12 src/sys/arch/sparc/include/mcontext.h:1.13
--- src/sys/arch/sparc/include/mcontext.h:1.12	Fri Feb 25 14:07:13 2011
+++ src/sys/arch/sparc/include/mcontext.h	Wed Sep 12 02:00:54 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: mcontext.h,v 1.12 2011/02/25 14:07:13 joerg Exp $	*/
+/*	$NetBSD: mcontext.h,v 1.13 2012/09/12 02:00:54 manu Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -34,6 +34,7 @@
 
 #define _UC_SETSTACK	0x00010000
 #define _UC_CLRSTACK	0x00020000
+#define _UC_TLSBASE	0x00080000
 
 /*
  * Layout of mcontext_t according the System V Application Binary Interface,

Index: src/sys/arch/sparc64/include/mcontext.h
diff -u src/sys/arch/sparc64/include/mcontext.h:1.8 src/sys/arch/sparc64/include/mcontext.h:1.9
--- src/sys/arch/sparc64/include/mcontext.h:1.8	Thu Mar 16 16:05:53 2006
+++ src/sys/arch/sparc64/include/mcontext.h	Wed Sep 12 02:00:54 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: mcontext.h,v 1.8 2006/03/16 16:05:53 cube Exp $	*/
+/*	$NetBSD: mcontext.h,v 1.9 2012/09/12 02:00:54 manu Exp $	*/
 
 #ifndef _SPARC64_MCONTEXT_H_
 #define _SPARC64_MCONTEXT_H_
@@ -74,5 +74,6 @@ typedef struct {
 
 #define	_UC_SETSTACK	0x00010000
 #define	_UC_CLRSTACK	0x00020000
+#define	_UC_TLSBASE	0x00080000
 
 #endif /* _SPARC64_MCONTEXT_H_ */

Index: src/sys/sys/ucontext.h
diff -u src/sys/sys/ucontext.h:1.16 src/sys/sys/ucontext.h:1.17
--- src/sys/sys/ucontext.h:1.16	Mon May 21 14:15:19 2012
+++ src/sys/sys/ucontext.h	Wed Sep 12 02:00:54 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ucontext.h,v 1.16 2012/05/21 14:15:19 martin Exp $	*/
+/*	$NetBSD: ucontext.h,v 1.17 2012/09/12 02:00:54 manu Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2003 The NetBSD Foundation, Inc.
@@ -57,21 +57,48 @@ struct __ucontext {
 #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_SETSTACK	0x00010000 (many ports) and 0x00020000 (arm)
- *	_UC_CLRSTACK	0x00020000 (many ports) and 0x00040000 (arm)
- *	_UC_POWERPC_VEC	0x00010000 (powerpc)
- *	_UC_M68K_UC_USER 0x40000000 (m68k)
- *	_UC_UNIQUE	0x00000020 (alpha)
- *	_UC_ARM_VFP	0x00010000 (arm)
- *	_UC_VM		0x00040000 (i386)
- *	_UC_FXSAVE	0x00000020 (i386)
- *
  * if your port needs more MD bits, please try to choose bits from _UC_MD
  * first, rather than picking random unused bits.
+ *
+ * _UC_MD details
+ *
+ * 	_UC_TLSBASE	Context contains valid pthread private pointer 
+ *			All ports must define this MD flag
+ * 			0x00040000	hppa, mips
+ * 			0x00000020	alpha
+ *			0x00080000	all other ports
+ *
+ *	_UC_SETSTACK	Context uses signal stack
+ *			0x00020000	arm
+ *			[undefined]	alpha, powerpc and vax
+ *			0x00010000	other ports
+ *
+ *	_UC_CLRSTACK	Context does not use signal stack
+ *			0x00040000	arm
+ *			[undefined]	alpha, powerpc and vax
+ *			0x00020000	other ports
+ *
+ *	_UC_POWERPC_VEC Context does not use signal stack
+ *			0x00010000	powerpc only
+ *
+ *	_UC_POWERPC_SPE	Context contains valid SPE context
+ *			0x00020000	powerpc only
+ *
+ *	_UC_M68K_UC_USER Used by m68k machdep code, but undocumented
+ *			0x40000000	m68k only
+ *
+ *	_UC_ARM_VFP	Unused
+ *			0x00010000	arm only
+ *
+ *	_UC_VM		Context contains valid virtual 8086 context
+ *			0x00040000	i386, amd64 only
+ *
+ *	_UC_FXSAVE	Context contains FPU context in that 
+ *			is in FXSAVE format in XMM space 
+ *			0x00000020	i386, amd64 only
  */
 
 #ifdef _KERNEL

Index: src/tests/lib/libc/sys/Makefile
diff -u src/tests/lib/libc/sys/Makefile:1.27 src/tests/lib/libc/sys/Makefile:1.28
--- src/tests/lib/libc/sys/Makefile:1.27	Wed Aug  8 13:57:06 2012
+++ src/tests/lib/libc/sys/Makefile	Wed Sep 12 02:00:55 2012
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.27 2012/08/08 13:57:06 christos Exp $
+# $NetBSD: Makefile,v 1.28 2012/09/12 02:00:55 manu Exp $
 
 MKMAN=	no
 
@@ -54,6 +54,7 @@ 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

Index: src/tests/lib/libpthread/Makefile
diff -u src/tests/lib/libpthread/Makefile:1.7 src/tests/lib/libpthread/Makefile:1.8
--- src/tests/lib/libpthread/Makefile:1.7	Wed Apr  6 16:04:16 2011
+++ src/tests/lib/libpthread/Makefile	Wed Sep 12 02:00:55 2012
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.7 2011/04/06 16:04:16 jruoho Exp $
+# $NetBSD: Makefile,v 1.8 2012/09/12 02:00:55 manu Exp $
 
 NOMAN=		# defined
 
@@ -35,6 +35,7 @@ TESTS_C+=	t_sigmask
 TESTS_C+=	t_sigsuspend
 TESTS_C+=	t_siglongjmp
 TESTS_C+=	t_sleep
+TESTS_C+=	t_swapcontext
 
 LDADD.t_sem+=	-lrt
 

Added files:

Index: src/tests/lib/libc/sys/t_swapcontext.c
diff -u /dev/null src/tests/lib/libc/sys/t_swapcontext.c:1.1
--- /dev/null	Wed Sep 12 02:00:56 2012
+++ src/tests/lib/libc/sys/t_swapcontext.c	Wed Sep 12 02:00:55 2012
@@ -0,0 +1,133 @@
+/* $NetBSD: t_swapcontext.c,v 1.1 2012/09/12 02:00:55 manu Exp $ */
+
+/*
+ * 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();
+}

Index: src/tests/lib/libpthread/t_swapcontext.c
diff -u /dev/null src/tests/lib/libpthread/t_swapcontext.c:1.1
--- /dev/null	Wed Sep 12 02:00:56 2012
+++ src/tests/lib/libpthread/t_swapcontext.c	Wed Sep 12 02:00:55 2012
@@ -0,0 +1,111 @@
+/* $NetBSD: t_swapcontext.c,v 1.1 2012/09/12 02:00:55 manu Exp $ */
+
+/*
+ * 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");
+
+	/* NOTREACHED */
+	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();
+}

Reply via email to