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--