handle a locking problem where the second (or later) call in the loanentry
loop returns 0. loanentry was returning >0, but was unlocking the maps (because of the zero). reworked to avoid this. problem reported by chuck silvers. also clarify a comment that jdolecek asked about.
This commit is contained in:
parent
df657b5158
commit
2dec1a929d
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: uvm_loan.c,v 1.30 2001/08/18 05:51:44 chs Exp $ */
|
||||
/* $NetBSD: uvm_loan.c,v 1.31 2001/08/27 02:34:29 chuck Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -119,13 +119,14 @@ static int uvm_loanzero __P((struct uvm_faultinfo *, void ***, int));
|
|||
* uvm_loanentry: loan out pages in a map entry (helper fn for uvm_loan())
|
||||
*
|
||||
* => "ufi" is the result of a successful map lookup (meaning that
|
||||
* the map is locked by the caller)
|
||||
* on entry the map is locked by the caller)
|
||||
* => we may unlock and then relock the map if needed (for I/O)
|
||||
* => we put our output result in "output"
|
||||
* => we always return with the map unlocked
|
||||
* => possible return values:
|
||||
* -1 == error, map is unlocked
|
||||
* 0 == map relock error (try again!), map is unlocked
|
||||
* >0 == number of pages we loaned, map remain locked
|
||||
* >0 == number of pages we loaned, map is unlocked
|
||||
*/
|
||||
|
||||
static __inline int
|
||||
|
@ -174,15 +175,15 @@ uvm_loanentry(ufi, output, flags)
|
|||
} else {
|
||||
rv = -1; /* null map entry... fail now */
|
||||
}
|
||||
/* locked: if (rv > 0) => map, amap, uobj */
|
||||
/* locked: if (rv > 0) => map, amap, uobj [o.w. unlocked] */
|
||||
|
||||
/* total failure */
|
||||
if (rv < 0)
|
||||
return(-1);
|
||||
return(-1); /* everything unlocked */
|
||||
|
||||
/* relock failed, need to do another lookup */
|
||||
if (rv == 0)
|
||||
return(result);
|
||||
return(result); /* everything unlocked */
|
||||
|
||||
/*
|
||||
* got it... advance to next page
|
||||
|
@ -193,12 +194,13 @@ uvm_loanentry(ufi, output, flags)
|
|||
}
|
||||
|
||||
/*
|
||||
* unlock what we locked and return (with map still locked)
|
||||
* unlock what we locked, unlock the maps and return
|
||||
*/
|
||||
if (aref->ar_amap)
|
||||
amap_unlock(aref->ar_amap);
|
||||
if (uobj)
|
||||
simple_unlock(&uobj->vmobjlock);
|
||||
uvmfault_unlockmaps(ufi, FALSE);
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
@ -280,18 +282,16 @@ uvm_loan(map, start, len, result, flags)
|
|||
}
|
||||
|
||||
/*
|
||||
* done! the map is locked only if rv > 0. if that
|
||||
* is the case, advance and unlock.
|
||||
* done! the map is unlocked. advance, if possible.
|
||||
*
|
||||
* XXXCDC: could avoid the unlock with smarter code
|
||||
* (but it only happens on map entry boundaries,
|
||||
* so it isn't that bad).
|
||||
* XXXCDC: could be recoded to hold the map lock with
|
||||
* smarter code (but it only happens on map entry
|
||||
* boundaries, so it isn't that bad).
|
||||
*/
|
||||
if (rv) {
|
||||
rv <<= PAGE_SHIFT;
|
||||
len -= rv;
|
||||
start += rv;
|
||||
uvmfault_unlockmaps(&ufi, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -760,7 +760,7 @@ uvm_unloanpage(ploans, npages)
|
|||
panic("uvm_unloanpage: page %p isn't loaned", pg);
|
||||
|
||||
pg->loan_count--; /* drop loan */
|
||||
uvm_pageunwire(pg); /* and wire */
|
||||
uvm_pageunwire(pg); /* and unwire */
|
||||
|
||||
/*
|
||||
* if page is unowned and we killed last loan, then we can
|
||||
|
|
Loading…
Reference in New Issue