Subject: Re: SA, libpthread and page faults
To: Stephan Uphoff <ups@stups.com>
From: Christian Limpach <chris@pin.lu>
List: tech-kern
Date: 08/18/2003 16:11:20
--1366390-14228-1061215882=:3008
Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
Content-Disposition: INLINE

On Wed, 13 Aug 2003 14:30:25 -0400 Stephan Uphoff <ups@stups.com> wrote:

> Right now the only idea I have is normal sleeping (no upcalls) on page
> faults.
> 
> Perhaps by stealing the PC trick from restartable atomic sequences we can
> limit disabling upcalls to the thread being active in libpthread ?
> ( Requires some ugly linking tricks to combine object files ? )
> 
> Any ideas on how to solve these problems would be appreciated.

How about checking if the stack that the lwp which page faulted ran on is
an upcall stack?  I have implemented this and it seems to work.  At least it
manages to avoid the pagefault/upcall horde at program startup when
libpthread.so isn't in memory yet and thus avoid running out of stacks (see
also kern/22490).

It goes like this:
- pagefault trap handler sets L_SA_PAGEFAULT.
- sa_switch checks for case 1 if L_SA_PAGEFAULT is set and if the lwp's
user stack is an upcall stack and doesn't make a SA_UPCALL_BLOCKED upcall
in this case.
- the check if the stack is an upcall stack is done by saving the upcall's
stack_t in struct sadata and checking if the lwp's user sp is in the saved
stack.  The saved stack_t has to be saved per-vp in the multi-vp case (not
tested yet, but the vp is known both at saving and checking time).

What do you think?


--1366390-14228-1061215882=:3008
Content-Type: TEXT/PLAIN; CHARSET=US-ASCII; NAME="sapf030818.patch"
Content-Disposition: INLINE; FILENAME="sapf030818.patch"

Index: arch/i386/i386/trap.c
===================================================================
RCS file: /cvs/netbsd/src/sys/arch/i386/i386/trap.c,v
retrieving revision 1.183
diff -u -r1.183 trap.c
--- arch/i386/i386/trap.c	7 Aug 2003 16:27:56 -0000	1.183
+++ arch/i386/i386/trap.c	18 Aug 2003 13:23:10 -0000
@@ -494,6 +496,7 @@
 
 		cr2 = rcr2();
 		KERNEL_PROC_LOCK(l);
+		l->l_flag |= L_SA_PAGEFAULT;
 	faultcommon:
 		vm = p->p_vmspace;
 		if (vm == NULL)
Index: kern/kern_sa.c
===================================================================
RCS file: /cvs/netbsd/src/sys/kern/kern_sa.c,v
retrieving revision 1.20
diff -u -r1.20 kern_sa.c
--- kern/kern_sa.c	11 Aug 2003 21:18:18 -0000	1.20
+++ kern/kern_sa.c	18 Aug 2003 13:23:10 -0000
@@ -515,6 +515,26 @@
 }
 
 
+static int
+sa_check_upcall(struct lwp *l, struct sadata *sa)
+{
+	ucontext_t l_ctx;
+	uintptr_t usp;
+	getucontext(l, &l_ctx);
+	usp = (uintptr_t)_UC_MACHINE_SP(&l_ctx);
+	l->l_flag &= ~L_SA_PAGEFAULT;
+#if 0
+	printf ("sa_check_upcall %p: usp: 0x%08x < 0x%08x < 0x%08x : %s\n", l,
+	    (uintptr_t)sa->sa_vp_upcall_stack.ss_sp, usp,
+	    (uintptr_t)sa->sa_vp_upcall_stack.ss_sp + sa->sa_vp_upcall_stack.ss_size, 
+	    usp >= (uintptr_t)sa->sa_vp_upcall_stack.ss_sp &&
+	    usp < (uintptr_t)sa->sa_vp_upcall_stack.ss_sp + sa->sa_vp_upcall_stack.ss_size ? "yes" : "no");
+#endif
+	if (usp >= (uintptr_t)sa->sa_vp_upcall_stack.ss_sp &&
+	    usp < (uintptr_t)sa->sa_vp_upcall_stack.ss_sp + sa->sa_vp_upcall_stack.ss_size)
+		return 1;
+	return 0;
+}
 /*
  * Called by tsleep(). Block current LWP and switch to another.
  *
@@ -542,6 +562,10 @@
 		return;
 	}
 
+	if ((sa->sa_vp == l) && (l->l_flag & L_SA_PAGEFAULT) && 
+	    sa_check_upcall (l, sa)) {
+		l2 = NULL;
+	} else
 	if (sa->sa_vp == l) {
 		/*
 		 * Case 1: we're blocking for the first time; generate
@@ -966,6 +990,7 @@
 	stack = (void *)
 	    (((uintptr_t)sau->sau_stack.ss_sp + sau->sau_stack.ss_size)
 		& ~ALIGNBYTES);
+	sa->sa_vp_upcall_stack = sau->sau_stack;
 
 	self_sa.sa_id = l->l_lid;
 	self_sa.sa_cpu = 0; /* XXX l->l_cpu; */
Index: sys/lwp.h
===================================================================
RCS file: /cvs/netbsd/src/sys/sys/lwp.h,v
retrieving revision 1.8
diff -u -r1.8 lwp.h
--- sys/lwp.h	28 Jul 2003 23:35:21 -0000	1.8
+++ sys/lwp.h	18 Aug 2003 13:23:10 -0000
@@ -119,6 +119,7 @@
 #define	L_DETACHED	0x800000 /* Won't be waited for. */
 #define L_SA_WANTS_VP   0x1000000 /* SA LWP wants a virtual processor */
 #define	L_CANCELLED	0x2000000 /* tsleep should not sleep */
+#define L_SA_PAGEFAULT	0x4000000
 
 /*
  * Status values.
Index: sys/savar.h
===================================================================
RCS file: /cvs/netbsd/src/sys/sys/savar.h,v
retrieving revision 1.5
diff -u -r1.5 savar.h
--- sys/savar.h	17 Jul 2003 18:16:59 -0000	1.5
+++ sys/savar.h	18 Aug 2003 13:23:10 -0000
@@ -80,6 +80,7 @@
 
 	struct lwp	*sa_woken;	/* list of woken lwps */
 	struct lwp	*sa_idle;      	/* lwp in sawait */
+	stack_t	sa_vp_upcall_stack;
 	int	sa_concurrency;		/* desired concurrency */
 	LIST_HEAD(, lwp)	sa_lwpcache;	/* list of avaliable lwps */
 	int	sa_ncached;		/* list length */

--1366390-14228-1061215882=:3008
Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
Content-Disposition: INLINE



-- 
Christian Limpach <chris@pin.lu>

--1366390-14228-1061215882=:3008--