* Added kernel tracing for insertion and removal of cache pages (tracing
level 2). * merge_cache_with_only_consumer() marked the source cache unbusy when it was done, which caused a race condition with the page fault code. I accidentally introduced this problem in r25716. Fixes #2326. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26068 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -259,8 +259,63 @@ class RemoveArea : public VMCacheTraceEntry {
|
|||||||
} // namespace VMCacheTracing
|
} // namespace VMCacheTracing
|
||||||
|
|
||||||
# define T(x) new(std::nothrow) VMCacheTracing::x;
|
# define T(x) new(std::nothrow) VMCacheTracing::x;
|
||||||
|
|
||||||
|
# if VM_CACHE_TRACING >= 2
|
||||||
|
|
||||||
|
namespace VMCacheTracing {
|
||||||
|
|
||||||
|
class InsertPage : public VMCacheTraceEntry {
|
||||||
|
public:
|
||||||
|
InsertPage(vm_cache* cache, vm_page* page, off_t offset)
|
||||||
|
:
|
||||||
|
VMCacheTraceEntry(cache),
|
||||||
|
fPage(page),
|
||||||
|
fOffset(offset)
|
||||||
|
{
|
||||||
|
Initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AddDump(TraceOutput& out)
|
||||||
|
{
|
||||||
|
out.Print("vm cache insert page: cache: %p, page: %p, offset: %lld",
|
||||||
|
fCache, fPage, fOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
vm_page* fPage;
|
||||||
|
off_t fOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class RemovePage : public VMCacheTraceEntry {
|
||||||
|
public:
|
||||||
|
RemovePage(vm_cache* cache, vm_page* page)
|
||||||
|
:
|
||||||
|
VMCacheTraceEntry(cache),
|
||||||
|
fPage(page)
|
||||||
|
{
|
||||||
|
Initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AddDump(TraceOutput& out)
|
||||||
|
{
|
||||||
|
out.Print("vm cache remove page: cache: %p, page: %p", fCache,
|
||||||
|
fPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
vm_page* fPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace VMCacheTracing
|
||||||
|
|
||||||
|
# define T2(x) new(std::nothrow) VMCacheTracing::x;
|
||||||
|
# else
|
||||||
|
# define T2(x) ;
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
# define T(x) ;
|
# define T(x) ;
|
||||||
|
# define T2(x) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -510,7 +565,11 @@ if (cache->ref_count < 2)
|
|||||||
panic("cacheRef %p ref count too low!\n", cache);
|
panic("cacheRef %p ref count too low!\n", cache);
|
||||||
vm_cache_release_ref(cache);
|
vm_cache_release_ref(cache);
|
||||||
|
|
||||||
cache->busy = false;
|
// Unpublishing the condition variable will wake up all threads waiting for
|
||||||
|
// the cache. It will still remain marked busy, though. In fact "busy" is
|
||||||
|
// a misnomer, since it actually means "to be deleted". Any thread we woke
|
||||||
|
// up will not touch the cache anymore, but release its reference and retry
|
||||||
|
// the hierarchy (cf. fault_find_page()).
|
||||||
busyCondition.Unpublish();
|
busyCondition.Unpublish();
|
||||||
|
|
||||||
mutex_unlock(&consumer->lock);
|
mutex_unlock(&consumer->lock);
|
||||||
@@ -699,6 +758,8 @@ vm_cache_insert_page(vm_cache* cache, vm_page* page, off_t offset)
|
|||||||
page, cache, page->cache);
|
page, cache, page->cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T2(InsertPage(cache, page, offset));
|
||||||
|
|
||||||
page->cache_offset = (uint32)(offset >> PAGE_SHIFT);
|
page->cache_offset = (uint32)(offset >> PAGE_SHIFT);
|
||||||
|
|
||||||
if (cache->page_list != NULL)
|
if (cache->page_list != NULL)
|
||||||
@@ -746,6 +807,8 @@ vm_cache_remove_page(vm_cache* cache, vm_page* page)
|
|||||||
cache, page->cache);
|
cache, page->cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T2(RemovePage(cache, page));
|
||||||
|
|
||||||
cpu_status state = disable_interrupts();
|
cpu_status state = disable_interrupts();
|
||||||
acquire_spinlock(&sPageCacheTableLock);
|
acquire_spinlock(&sPageCacheTableLock);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user