[haiku-commits] Change in haiku[master]: VMCache: Factor out a _FreePageRange method.

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 30 May 2020 00:02:36 +0000

From Michael Lotz <mmlr@xxxxxxxx>:

Michael Lotz has uploaded this change for review. ( 
https://review.haiku-os.org/c/haiku/+/2835 ;)


Change subject: VMCache: Factor out a _FreePageRange method.
......................................................................

VMCache: Factor out a _FreePageRange method.

The code in the Resize and Rebase methods was identical except for the
iterator.
---
M headers/private/kernel/vm/VMCache.h
M src/system/kernel/vm/VMCache.cpp
2 files changed, 52 insertions(+), 67 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/35/2835/1

diff --git a/headers/private/kernel/vm/VMCache.h 
b/headers/private/kernel/vm/VMCache.h
index d5185b9..0aee4f9 100644
--- a/headers/private/kernel/vm/VMCache.h
+++ b/headers/private/kernel/vm/VMCache.h
@@ -215,6 +215,9 @@
                        void                            
_MergeWithOnlyConsumer();
                        void                            
_RemoveConsumer(VMCache* consumer);

+                       bool                            
_FreePageRange(VMCachePagesTree::Iterator it,
+                                                                       
page_num_t* toPage);
+
 private:
                        int32                           fRefCount;
                        mutex                           fLock;
diff --git a/src/system/kernel/vm/VMCache.cpp b/src/system/kernel/vm/VMCache.cpp
index f0f626c..d820333 100644
--- a/src/system/kernel/vm/VMCache.cpp
+++ b/src/system/kernel/vm/VMCache.cpp
@@ -1111,6 +1111,46 @@
 }


+bool
+VMCache::_FreePageRange(VMCachePagesTree::Iterator it,
+       page_num_t* toPage = NULL)
+{
+       for (vm_page* page = it.Next();
+               page != NULL && (toPage == NULL || page->cache_offset < 
*toPage);
+               page = it.Next()) {
+
+               if (page->busy) {
+                       if (page->busy_writing) {
+                               // We cannot wait for the page to become 
available
+                               // as we might cause a deadlock this way
+                               page->busy_writing = false;
+                                       // this will notify the writer to free 
the page
+                               continue;
+                       }
+
+                       // wait for page to become unbusy
+                       WaitForPageEvents(page, PAGE_EVENT_NOT_BUSY, true);
+                       return true;
+               }
+
+               // remove the page and put it into the free queue
+               DEBUG_PAGE_ACCESS_START(page);
+               vm_remove_all_page_mappings(page);
+               ASSERT(page->WiredCount() == 0);
+                       // TODO: Find a real solution! If the page is wired
+                       // temporarily (e.g. by lock_memory()), we actually 
must not
+                       // unmap it!
+               RemovePage(page);
+                       // Note: When iterating through a IteratableSplayTree
+                       // removing the current node is safe.
+
+               vm_page_free(this, page);
+       }
+
+       return false;
+}
+
+
 /*!    This function updates the size field of the cache.
        If needed, it will free up all pages that don't belong to the cache 
anymore.
        The cache lock must be held when you call it.
@@ -1133,44 +1173,16 @@
        if (status != B_OK)
                return status;

-       uint32 oldPageCount = (uint32)((virtual_end + B_PAGE_SIZE - 1)
+       page_num_t oldPageCount = (page_num_t)((virtual_end + B_PAGE_SIZE - 1)
                >> PAGE_SHIFT);
-       uint32 newPageCount = (uint32)((newSize + B_PAGE_SIZE - 1) >> 
PAGE_SHIFT);
+       page_num_t newPageCount = (page_num_t)((newSize + B_PAGE_SIZE - 1)
+               >> PAGE_SHIFT);

        if (newPageCount < oldPageCount) {
                // we need to remove all pages in the cache outside of the new 
virtual
                // size
-               for (VMCachePagesTree::Iterator it
-                                       = pages.GetIterator(newPageCount, true, 
true);
-                               vm_page* page = it.Next();) {
-                       if (page->busy) {
-                               if (page->busy_writing) {
-                                       // We cannot wait for the page to 
become available
-                                       // as we might cause a deadlock this way
-                                       page->busy_writing = false;
-                                               // this will notify the writer 
to free the page
-                               } else {
-                                       // wait for page to become unbusy
-                                       WaitForPageEvents(page, 
PAGE_EVENT_NOT_BUSY, true);
-
-                                       // restart from the start of the list
-                                       it = pages.GetIterator(newPageCount, 
true, true);
-                               }
-                               continue;
-                       }
-
-                       // remove the page and put it into the free queue
-                       DEBUG_PAGE_ACCESS_START(page);
-                       vm_remove_all_page_mappings(page);
-                       ASSERT(page->WiredCount() == 0);
-                               // TODO: Find a real solution! If the page is 
wired
-                               // temporarily (e.g. by lock_memory()), we 
actually must not
-                               // unmap it!
-                       RemovePage(page);
-                       vm_page_free(this, page);
-                               // Note: When iterating through a 
IteratableSplayTree
-                               // removing the current node is safe.
-               }
+               while (_FreePageRange(pages.GetIterator(newPageCount, true, 
true)))
+                       ;
        }

        virtual_end = newSize;
@@ -1199,43 +1211,13 @@
        if (status != B_OK)
                return status;

-       uint32 basePage = (uint32)(newBase >> PAGE_SHIFT);
+       page_num_t basePage = (page_num_t)(newBase >> PAGE_SHIFT);

        if (newBase > virtual_base) {
                // we need to remove all pages in the cache outside of the new 
virtual
-               // size
-               VMCachePagesTree::Iterator it = pages.GetIterator();
-               for (vm_page* page = it.Next();
-                               page != NULL && page->cache_offset < basePage;
-                               page = it.Next()) {
-                       if (page->busy) {
-                               if (page->busy_writing) {
-                                       // We cannot wait for the page to 
become available
-                                       // as we might cause a deadlock this way
-                                       page->busy_writing = false;
-                                               // this will notify the writer 
to free the page
-                               } else {
-                                       // wait for page to become unbusy
-                                       WaitForPageEvents(page, 
PAGE_EVENT_NOT_BUSY, true);
-
-                                       // restart from the start of the list
-                                       it = pages.GetIterator();
-                               }
-                               continue;
-                       }
-
-                       // remove the page and put it into the free queue
-                       DEBUG_PAGE_ACCESS_START(page);
-                       vm_remove_all_page_mappings(page);
-                       ASSERT(page->WiredCount() == 0);
-                               // TODO: Find a real solution! If the page is 
wired
-                               // temporarily (e.g. by lock_memory()), we 
actually must not
-                               // unmap it!
-                       RemovePage(page);
-                       vm_page_free(this, page);
-                               // Note: When iterating through a 
IteratableSplayTree
-                               // removing the current node is safe.
-               }
+               // base
+               while (_FreePageRange(pages.GetIterator(), &basePage))
+                       ;
        }

        virtual_base = newBase;

--
To view, visit https://review.haiku-os.org/c/haiku/+/2835
To unsubscribe, or for help writing mail filters, visit 
https://review.haiku-os.org/settings

Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I9f6b3c2c09af0c26778215bd627fed030c4d46f1
Gerrit-Change-Number: 2835
Gerrit-PatchSet: 1
Gerrit-Owner: Michael Lotz <mmlr@xxxxxxxx>
Gerrit-MessageType: newchange

Other related posts:

  • » [haiku-commits] Change in haiku[master]: VMCache: Factor out a _FreePageRange method. - Gerrit