mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:08:12 +00:00
Kernel: Extend the lifetime of Regions during page fault handling
Previously we had a race condition in the page fault handling: We were relying on the affected Region staying alive while handling the page fault, but this was not actually guaranteed, as an munmap from another thread could result in the region being removed concurrently. This commit closes that hole by extending the lifetime of the region affected by the page fault until the handling of the page fault is complete. This is achieved by maintaing a psuedo-reference count on the region which counts the number of in-progress page faults being handled on this region, and extending the lifetime of the region while this counter is non zero. Since both the increment of the counter by the page fault handler and the spin loop waiting for it to reach 0 during Region destruction are serialized using the appropriate AddressSpace spinlock, eventual progress is guaranteed: As soon as the region is removed from the tree no more page faults on the region can start. And similarly correctness is ensured: The counter is incremented under the same lock, so any page faults that are being handled will have already incremented the counter before the region is deallocated.
This commit is contained in:
parent
003989e1b0
commit
1c2dbed38a
4 changed files with 51 additions and 32 deletions
|
@ -75,6 +75,16 @@ Region::~Region()
|
|||
|
||||
if (is_kernel())
|
||||
MM.unregister_kernel_region(*this);
|
||||
|
||||
// Extend the lifetime of the region if there are any page faults in progress for this region's pages.
|
||||
// Both the removal of regions from the region trees and the fetching of the regions from the tree
|
||||
// during the start of page fault handling are serialized under the address space spinlock. This means
|
||||
// that once the region is removed no more page faults on this region can start, so this counter will
|
||||
// eventually reach 0. And similarly since we can only reach the region destructor once the region was
|
||||
// removed from the appropriate region tree, it is guaranteed that any page faults that are still being
|
||||
// handled have already increased this counter, and will be allowed to finish before deallocation.
|
||||
while (m_in_progress_page_faults)
|
||||
Processor::wait_check();
|
||||
}
|
||||
|
||||
ErrorOr<NonnullOwnPtr<Region>> Region::create_unbacked()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue