提交 5e3c72c4 创建 作者: Austin Clements's avatar Austin Clements

Fix concurrent unmap/page fault in radix

Previously we just looked at whether the fauling VMA was deleted once we had the PTE lock, but that's not enough since a VMA can be partially deleted. Instead, we check the radix tree again after taking the PTE lock.
上级 6a5aee25
......@@ -243,6 +243,8 @@ struct radix_iterator {
}
radix_elem* operator*() const {
// XXX(austin) If we don't hold a lock on this element, it's
// possible it will morph into a node under us.
return path_[level_]->load().elem();
}
......
......@@ -618,7 +618,12 @@ vmap::pagefault(uptr va, u32 err)
}
scoped_gc_epoch gc;
#if VM_CRANGE
vma *m = lookup(va, 1);
#elif VM_RADIX
auto vma_it = vmas.find(va);
vma *m = static_cast<vma*>(*vma_it);
#endif
if (m == 0)
return -1;
......@@ -659,10 +664,20 @@ vmap::pagefault(uptr va, u32 err)
if (!cmpxch(pte, ptev, ptev | PTE_LOCK))
goto retry;
#if VM_CRANGE
if (m->deleted()) {
*pte = ptev;
goto retry;
}
#elif VM_RADIX
// The radix tree is the source of truth about where the VMA is
// mapped. It might have been unmapped from this va but still be
// around, so we can't just test if it's deleted.
if (*vma_it != m) {
*pte = ptev;
goto retry;
}
#endif
if (m->va_type == COW) {
*pte = v2p(m->n->page[npg]) | PTE_P | PTE_U | PTE_COW;
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论