kernel/vm: Set the upper cache's commitment in vm_copy_on_write_area.
Otherwise we may fault later but have no memory to satisfy the fault. For a compile of HaikuDepot and the mime_db in VMware with -j4, this seems to increase the wait time on the "available memory" lock from ~0.1s to ~0.5s, and the wait count from ~500 to ~1500 (overall real time ~30s.) Probably we can mitigate that later by doing atomic updates on sAvailableMemory, at least for releasing memory. Change-Id: I61abc28d1fc30f7b3d5fd9a2e68e4f4ec960f88d Reviewed-on: https://review.haiku-os.org/c/haiku/+/8677 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
2acb67eef0
commit
b592ba6662
@@ -2735,14 +2735,13 @@ static status_t
|
|||||||
vm_copy_on_write_area(VMCache* lowerCache,
|
vm_copy_on_write_area(VMCache* lowerCache,
|
||||||
vm_page_reservation* wiredPagesReservation)
|
vm_page_reservation* wiredPagesReservation)
|
||||||
{
|
{
|
||||||
VMCache* upperCache;
|
|
||||||
|
|
||||||
TRACE(("vm_copy_on_write_area(cache = %p)\n", lowerCache));
|
TRACE(("vm_copy_on_write_area(cache = %p)\n", lowerCache));
|
||||||
|
|
||||||
// We need to separate the cache from its areas. The cache goes one level
|
// We need to separate the cache from its areas. The cache goes one level
|
||||||
// deeper and we create a new cache inbetween.
|
// deeper and we create a new cache inbetween.
|
||||||
|
|
||||||
// create an anonymous cache
|
// create an anonymous cache
|
||||||
|
VMCache* upperCache;
|
||||||
status_t status = VMCacheFactory::CreateAnonymousCache(upperCache,
|
status_t status = VMCacheFactory::CreateAnonymousCache(upperCache,
|
||||||
lowerCache->CanOvercommit(), 0,
|
lowerCache->CanOvercommit(), 0,
|
||||||
lowerCache->GuardSize() / B_PAGE_SIZE,
|
lowerCache->GuardSize() / B_PAGE_SIZE,
|
||||||
@@ -2757,6 +2756,22 @@ vm_copy_on_write_area(VMCache* lowerCache,
|
|||||||
upperCache->virtual_base = lowerCache->virtual_base;
|
upperCache->virtual_base = lowerCache->virtual_base;
|
||||||
upperCache->virtual_end = lowerCache->virtual_end;
|
upperCache->virtual_end = lowerCache->virtual_end;
|
||||||
|
|
||||||
|
// Shrink the lower cache's commitment (if possible) and steal the remainder;
|
||||||
|
// and increase the upper cache's commitment to the lower cache's old commitment.
|
||||||
|
const off_t lowerOldCommitment = lowerCache->committed_size,
|
||||||
|
lowerNewCommitment = (lowerCache->page_count * B_PAGE_SIZE);
|
||||||
|
if (lowerNewCommitment < lowerOldCommitment) {
|
||||||
|
lowerCache->committed_size = lowerNewCommitment;
|
||||||
|
upperCache->committed_size = lowerOldCommitment - lowerNewCommitment;
|
||||||
|
}
|
||||||
|
status = upperCache->Commit(lowerOldCommitment, VM_PRIORITY_USER);
|
||||||
|
if (status != B_OK) {
|
||||||
|
lowerCache->committed_size += upperCache->committed_size;
|
||||||
|
upperCache->committed_size = 0;
|
||||||
|
upperCache->ReleaseRefAndUnlock();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
// transfer the lower cache areas to the upper cache
|
// transfer the lower cache areas to the upper cache
|
||||||
rw_lock_write_lock(&sAreaCacheLock);
|
rw_lock_write_lock(&sAreaCacheLock);
|
||||||
upperCache->TransferAreas(lowerCache);
|
upperCache->TransferAreas(lowerCache);
|
||||||
|
|||||||
Reference in New Issue
Block a user