From 0b4dac74e0aa7cf9d2637b1a2ce57c42f21970ba Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 21 Jun 2008 21:08:07 +0000 Subject: [PATCH] * 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 --- src/system/kernel/vm/vm_cache.cpp | 65 ++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/system/kernel/vm/vm_cache.cpp b/src/system/kernel/vm/vm_cache.cpp index caf33ac107..e2205c8d69 100644 --- a/src/system/kernel/vm/vm_cache.cpp +++ b/src/system/kernel/vm/vm_cache.cpp @@ -259,8 +259,63 @@ class RemoveArea : public VMCacheTraceEntry { } // namespace VMCacheTracing # 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 # define T(x) ; +# define T2(x) ; #endif @@ -510,7 +565,11 @@ if (cache->ref_count < 2) panic("cacheRef %p ref count too low!\n", 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(); 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); } + T2(InsertPage(cache, page, offset)); + page->cache_offset = (uint32)(offset >> PAGE_SHIFT); if (cache->page_list != NULL) @@ -746,6 +807,8 @@ vm_cache_remove_page(vm_cache* cache, vm_page* page) cache, page->cache); } + T2(RemovePage(cache, page)); + cpu_status state = disable_interrupts(); acquire_spinlock(&sPageCacheTableLock);