borrow checker: reset index when empty, handle oom
This commit is contained in:
@@ -17,10 +17,7 @@ impl BorrowChecker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn borrow(&self, r: Region) -> Result<BorrowHandle, GuestError> {
|
pub fn borrow(&self, r: Region) -> Result<BorrowHandle, GuestError> {
|
||||||
self.bc
|
self.bc.borrow_mut().borrow(r)
|
||||||
.borrow_mut()
|
|
||||||
.borrow(r)
|
|
||||||
.ok_or_else(|| GuestError::PtrBorrowed(r))
|
|
||||||
}
|
}
|
||||||
pub fn unborrow(&self, h: BorrowHandle) {
|
pub fn unborrow(&self, h: BorrowHandle) {
|
||||||
self.bc.borrow_mut().unborrow(h)
|
self.bc.borrow_mut().unborrow(h)
|
||||||
@@ -45,19 +42,26 @@ impl InnerBorrowChecker {
|
|||||||
!self.borrows.values().all(|b| !b.overlaps(r))
|
!self.borrows.values().all(|b| !b.overlaps(r))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_handle(&mut self) -> BorrowHandle {
|
fn new_handle(&mut self) -> Result<BorrowHandle, GuestError> {
|
||||||
|
// Reset handles to 0 if all handles have been returned.
|
||||||
|
if self.borrows.is_empty() {
|
||||||
|
self.next_handle = BorrowHandle(0);
|
||||||
|
}
|
||||||
let h = self.next_handle;
|
let h = self.next_handle;
|
||||||
self.next_handle = BorrowHandle(h.0 + 1);
|
self.next_handle = BorrowHandle(
|
||||||
h
|
h.0.checked_add(1)
|
||||||
|
.ok_or_else(|| GuestError::BorrowCheckerOOM)?,
|
||||||
|
);
|
||||||
|
Ok(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn borrow(&mut self, r: Region) -> Option<BorrowHandle> {
|
fn borrow(&mut self, r: Region) -> Result<BorrowHandle, GuestError> {
|
||||||
if self.is_borrowed(r) {
|
if self.is_borrowed(r) {
|
||||||
return None;
|
return Err(GuestError::PtrBorrowed(r));
|
||||||
}
|
}
|
||||||
let h = self.new_handle();
|
let h = self.new_handle()?;
|
||||||
self.borrows.insert(h, r);
|
self.borrows.insert(h, r);
|
||||||
Some(h)
|
Ok(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unborrow(&mut self, h: BorrowHandle) {
|
fn unborrow(&mut self, h: BorrowHandle) {
|
||||||
@@ -92,28 +96,28 @@ mod test {
|
|||||||
let r2 = Region::new(9, 10);
|
let r2 = Region::new(9, 10);
|
||||||
assert!(r1.overlaps(r2));
|
assert!(r1.overlaps(r2));
|
||||||
bs.borrow(r1).expect("can borrow r1");
|
bs.borrow(r1).expect("can borrow r1");
|
||||||
assert!(bs.borrow(r2).is_none(), "cant borrow r2");
|
assert!(bs.borrow(r2).is_err(), "cant borrow r2");
|
||||||
|
|
||||||
let mut bs = InnerBorrowChecker::new();
|
let mut bs = InnerBorrowChecker::new();
|
||||||
let r1 = Region::new(0, 10);
|
let r1 = Region::new(0, 10);
|
||||||
let r2 = Region::new(2, 5);
|
let r2 = Region::new(2, 5);
|
||||||
assert!(r1.overlaps(r2));
|
assert!(r1.overlaps(r2));
|
||||||
bs.borrow(r1).expect("can borrow r1");
|
bs.borrow(r1).expect("can borrow r1");
|
||||||
assert!(bs.borrow(r2).is_none(), "cant borrow r2");
|
assert!(bs.borrow(r2).is_err(), "cant borrow r2");
|
||||||
|
|
||||||
let mut bs = InnerBorrowChecker::new();
|
let mut bs = InnerBorrowChecker::new();
|
||||||
let r1 = Region::new(9, 10);
|
let r1 = Region::new(9, 10);
|
||||||
let r2 = Region::new(0, 10);
|
let r2 = Region::new(0, 10);
|
||||||
assert!(r1.overlaps(r2));
|
assert!(r1.overlaps(r2));
|
||||||
bs.borrow(r1).expect("can borrow r1");
|
bs.borrow(r1).expect("can borrow r1");
|
||||||
assert!(bs.borrow(r2).is_none(), "cant borrow r2");
|
assert!(bs.borrow(r2).is_err(), "cant borrow r2");
|
||||||
|
|
||||||
let mut bs = InnerBorrowChecker::new();
|
let mut bs = InnerBorrowChecker::new();
|
||||||
let r1 = Region::new(2, 5);
|
let r1 = Region::new(2, 5);
|
||||||
let r2 = Region::new(0, 10);
|
let r2 = Region::new(0, 10);
|
||||||
assert!(r1.overlaps(r2));
|
assert!(r1.overlaps(r2));
|
||||||
bs.borrow(r1).expect("can borrow r1");
|
bs.borrow(r1).expect("can borrow r1");
|
||||||
assert!(bs.borrow(r2).is_none(), "cant borrow r2");
|
assert!(bs.borrow(r2).is_err(), "cant borrow r2");
|
||||||
|
|
||||||
let mut bs = InnerBorrowChecker::new();
|
let mut bs = InnerBorrowChecker::new();
|
||||||
let r1 = Region::new(2, 5);
|
let r1 = Region::new(2, 5);
|
||||||
@@ -124,7 +128,7 @@ mod test {
|
|||||||
bs.borrow(r1).expect("can borrow r1");
|
bs.borrow(r1).expect("can borrow r1");
|
||||||
bs.borrow(r2).expect("can borrow r2");
|
bs.borrow(r2).expect("can borrow r2");
|
||||||
bs.borrow(r3).expect("can borrow r3");
|
bs.borrow(r3).expect("can borrow r3");
|
||||||
assert!(bs.borrow(r4).is_none(), "cant borrow r4");
|
assert!(bs.borrow(r4).is_err(), "cant borrow r4");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -136,7 +140,7 @@ mod test {
|
|||||||
let _h1 = bs.borrow(r1).expect("can borrow r1");
|
let _h1 = bs.borrow(r1).expect("can borrow r1");
|
||||||
let h2 = bs.borrow(r2).expect("can borrow r2");
|
let h2 = bs.borrow(r2).expect("can borrow r2");
|
||||||
|
|
||||||
assert!(bs.borrow(r2).is_none(), "can't borrow r2 twice");
|
assert!(bs.borrow(r2).is_err(), "can't borrow r2 twice");
|
||||||
bs.unborrow(h2);
|
bs.unborrow(h2);
|
||||||
|
|
||||||
let _h3 = bs
|
let _h3 = bs
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ pub enum GuestError {
|
|||||||
PtrNotAligned(Region, u32),
|
PtrNotAligned(Region, u32),
|
||||||
#[error("Pointer already borrowed: {0:?}")]
|
#[error("Pointer already borrowed: {0:?}")]
|
||||||
PtrBorrowed(Region),
|
PtrBorrowed(Region),
|
||||||
|
#[error("Borrow checker out of memory")]
|
||||||
|
BorrowCheckerOOM,
|
||||||
#[error("Slice length mismatch")]
|
#[error("Slice length mismatch")]
|
||||||
SliceLengthsDiffer,
|
SliceLengthsDiffer,
|
||||||
#[error("In func {funcname}:{location}:")]
|
#[error("In func {funcname}:{location}:")]
|
||||||
|
|||||||
Reference in New Issue
Block a user