mirror of
https://review.haiku-os.org/haiku
synced 2025-01-18 12:38:51 +01:00
kernel/vm: Rework ordering of _RemoveConsumer and drop "unmergeable" flag.
This reverts a8877df135
.
Previously, the "unmergeable" flag was necessary for the RAMFS,
because if the last vnode reference was released while there
was still a consumer (as the old ordering of _RemoveConsumer
had), then the release of the cache reference when the vnode
was removed would result in the cache trying to merge with
its now-only consumer and sole referrer.
Now, instead, we remove the consumer before releasing the store
reference, so that there's no chance the cache will be merged
inside this method.
mmap_cut_tests still pass, web browsers using ramfs shared_memory
still seem to work.
This commit is contained in:
parent
7eeb28152e
commit
f836917f47
@ -200,7 +200,6 @@ public:
|
||||
// TODO: Remove!
|
||||
uint32 page_count;
|
||||
uint32 temporary : 1;
|
||||
uint32 unmergeable : 1;
|
||||
uint32 type : 6;
|
||||
|
||||
#if DEBUG_CACHE_LIST
|
||||
|
@ -303,7 +303,6 @@ DataContainer::_SwitchToCacheMode()
|
||||
|
||||
fCache = cache;
|
||||
fCache->temporary = 1;
|
||||
fCache->unmergeable = 1;
|
||||
fCache->virtual_end = fSize;
|
||||
|
||||
error = fCache->Commit(fSize, VM_PRIORITY_USER);
|
||||
|
@ -611,7 +611,7 @@ VMCacheRef::VMCacheRef(VMCache* cache)
|
||||
bool
|
||||
VMCache::_IsMergeable() const
|
||||
{
|
||||
return areas.IsEmpty() && temporary && !unmergeable
|
||||
return areas.IsEmpty() && temporary
|
||||
&& !consumers.IsEmpty() && consumers.Head() == consumers.Tail();
|
||||
}
|
||||
|
||||
@ -642,7 +642,6 @@ VMCache::Init(uint32 cacheType, uint32 allocationFlags)
|
||||
virtual_end = 0;
|
||||
committed_size = 0;
|
||||
temporary = 0;
|
||||
unmergeable = 0;
|
||||
page_count = 0;
|
||||
fWiredPagesCount = 0;
|
||||
type = cacheType;
|
||||
@ -1561,21 +1560,22 @@ void
|
||||
VMCache::_RemoveConsumer(VMCache* consumer)
|
||||
{
|
||||
TRACE(("remove consumer vm cache %p from cache %p\n", consumer, this));
|
||||
consumer->AssertLocked();
|
||||
|
||||
T(RemoveConsumer(this, consumer));
|
||||
|
||||
// Remove the store ref before locking the cache. Otherwise we'd call into
|
||||
// the VFS while holding the cache lock, which would reverse the usual
|
||||
// locking order.
|
||||
ReleaseStoreRef();
|
||||
consumer->AssertLocked();
|
||||
|
||||
// remove the consumer from the cache, but keep its reference until later
|
||||
// Remove the consumer from the cache, but keep its reference until the end.
|
||||
Lock();
|
||||
consumers.Remove(consumer);
|
||||
consumer->source = NULL;
|
||||
Unlock();
|
||||
|
||||
ReleaseRefAndUnlock();
|
||||
// Release the store ref without holding the cache lock, as calling into
|
||||
// the VFS while holding the cache lock would reverse the usual locking order.
|
||||
ReleaseStoreRef();
|
||||
|
||||
// Now release the consumer's reference.
|
||||
ReleaseRef();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user