add comments to the pagefault code
This commit is contained in:
parent
fe74654bab
commit
52a920b5da
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: kern_sa.c,v 1.24 2003/09/16 13:46:24 cl Exp $ */
|
/* $NetBSD: kern_sa.c,v 1.25 2003/09/16 15:28:45 cl Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||||
@ -37,7 +37,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.24 2003/09/16 13:46:24 cl Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.25 2003/09/16 15:28:45 cl Exp $");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
@ -220,6 +220,13 @@ sys_sa_stacks(struct lwp *l, void *v, register_t *retval)
|
|||||||
if ((sa->sa_nstacks == 0) && (sa->sa_vp_wait_count != 0))
|
if ((sa->sa_nstacks == 0) && (sa->sa_vp_wait_count != 0))
|
||||||
l->l_flag |= L_SA_UPCALL;
|
l->l_flag |= L_SA_UPCALL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save addresses of the first and last stack on initial load
|
||||||
|
* the pagefault code uses the saved address to detect threads
|
||||||
|
* running on an upcall stack.
|
||||||
|
* XXX assumes all stacks are adjoining
|
||||||
|
* XXX assumes initial load includes all stacks ever used
|
||||||
|
*/
|
||||||
if (sa->sa_vp_stacks_low == 0) {
|
if (sa->sa_vp_stacks_low == 0) {
|
||||||
sa->sa_vp_stacks_low = (uintptr_t)sa->sa_stacks[0].ss_sp;
|
sa->sa_vp_stacks_low = (uintptr_t)sa->sa_stacks[0].ss_sp;
|
||||||
sa->sa_vp_stacks_high = (uintptr_t)sa->sa_stacks[count - 1].ss_sp +
|
sa->sa_vp_stacks_high = (uintptr_t)sa->sa_stacks[count - 1].ss_sp +
|
||||||
@ -428,6 +435,22 @@ sa_preempt(struct lwp *l)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Help userspace library resolve locks and critical sections
|
||||||
|
* - recycles the calling LWP and its stack if it was not preempted
|
||||||
|
* and idle the VP until the sa_id LWP unblocks
|
||||||
|
* - recycles the to be unblocked LWP if the calling LWP was preempted
|
||||||
|
* and returns control to the userspace library so it can switch to
|
||||||
|
* the blocked thread
|
||||||
|
* This is used if a thread blocks because of a pagefault and is in a
|
||||||
|
* critical section in the userspace library and the critical section
|
||||||
|
* resolving code cannot continue until the blocked thread is unblocked.
|
||||||
|
* If the userspace library switches to the blocked thread in the second
|
||||||
|
* case, it will either continue (because the pagefault has been handled)
|
||||||
|
* or it will pagefault again. The second pagefault will be detected by
|
||||||
|
* the double pagefault code and the VP will idle until the pagefault
|
||||||
|
* has been handled.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
sys_sa_unblockyield(struct lwp *l, void *v, register_t *retval)
|
sys_sa_unblockyield(struct lwp *l, void *v, register_t *retval)
|
||||||
{
|
{
|
||||||
@ -653,6 +676,13 @@ sa_upcall_getstate(struct sadata_upcall *sau, struct lwp *event,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detect double pagefaults and pagefaults on upcalls.
|
||||||
|
* - double pagefaults are detected by comparing the previous faultaddr
|
||||||
|
* against the current faultaddr
|
||||||
|
* - pagefaults on upcalls are detected by checking if the userspace
|
||||||
|
* thread is running on an upcall stack
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
sa_pagefault(struct lwp *l, ucontext_t *l_ctx)
|
sa_pagefault(struct lwp *l, ucontext_t *l_ctx)
|
||||||
{
|
{
|
||||||
@ -781,7 +811,16 @@ sa_switch(struct lwp *l, int type)
|
|||||||
goto sa_upcall_failed;
|
goto sa_upcall_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l->l_flag & L_SA_PAGEFAULT && sa_pagefault(l,
|
/*
|
||||||
|
* Perform the double/upcall pagefault check.
|
||||||
|
* We do this only here since we need l's ucontext to
|
||||||
|
* get l's userspace stack. sa_upcall0 above has saved
|
||||||
|
* it for us.
|
||||||
|
* The L_SA_PAGEFAULT flag is set in the MD
|
||||||
|
* pagefault code to indicate a pagefault. The MD
|
||||||
|
* pagefault code also saves the faultaddr for us.
|
||||||
|
*/
|
||||||
|
if ((l->l_flag & L_SA_PAGEFAULT) && sa_pagefault(l,
|
||||||
&sau->sau_state.captured.e_ctx) != 0) {
|
&sau->sau_state.captured.e_ctx) != 0) {
|
||||||
sadata_upcall_free(sau);
|
sadata_upcall_free(sau);
|
||||||
sa->sa_stacks[sa->sa_nstacks++] = st;
|
sa->sa_stacks[sa->sa_nstacks++] = st;
|
||||||
|
Loading…
Reference in New Issue
Block a user