* Since the page scanner and thief can work more effectively when no vm_caches

are locked, there is now a vm_page_reserve_pages() call to ensure upfront that
  there is a page for me when I need it, and may have locked some caches.
* The vm_soft_fault() routine now makes use of that feature.
* vm_page_allocate_page() now resets the vm_page::usage_count, so that the file
  cache does not need to do this in read_chunk_into_cache() and
  write_chunk_to_cache().
* In cache_io() however, it need to update the usage_count - and it does that
  now. Since non-mapped caches don't have mappings, the page scanner will punish
  the cache pages stronger than other pages which is accidently just what we
  want.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22319 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-09-26 17:42:25 +00:00
parent 8a25e1293b
commit 8e0f884c71
6 changed files with 89 additions and 41 deletions
+12 -12
View File
@@ -538,7 +538,7 @@ read_chunk_into_cache(file_cache_ref *ref, off_t offset, size_t numBytes,
// allocate pages for the cache and mark them busy
for (size_t pos = 0; pos < numBytes; pos += B_PAGE_SIZE) {
vm_page *page = pages[pageIndex++] = vm_page_allocate_page(
PAGE_STATE_FREE);
PAGE_STATE_FREE, false);
if (page == NULL)
panic("no more pages!");
@@ -612,10 +612,6 @@ read_chunk_into_cache(file_cache_ref *ref, off_t offset, size_t numBytes,
// make the pages accessible in the cache
for (int32 i = pageIndex; i-- > 0;) {
pages[i]->state = PAGE_STATE_ACTIVE;
if (pages[i]->usage_count < 0)
pages[i]->usage_count = 1;
else
pages[i]->usage_count++;
busyConditions[i].Unpublish();
}
@@ -697,11 +693,13 @@ write_chunk_to_cache(file_cache_ref *ref, off_t offset, size_t numBytes,
// allocate pages for the cache and mark them busy
for (size_t pos = 0; pos < numBytes; pos += B_PAGE_SIZE) {
// ToDo: if space is becoming tight, and this cache is already grown
// TODO: if space is becoming tight, and this cache is already grown
// big - shouldn't we better steal the pages directly in that case?
// (a working set like approach for the file cache)
// TODO: the pages we allocate here should have been reserved upfront
// in cache_io()
vm_page *page = pages[pageIndex++] = vm_page_allocate_page(
PAGE_STATE_FREE);
PAGE_STATE_FREE, false);
busyConditions[pageIndex - 1].Publish(page, "page");
vm_cache_insert_page(ref->cache, page, offset + pos);
@@ -797,11 +795,6 @@ write_chunk_to_cache(file_cache_ref *ref, off_t offset, size_t numBytes,
for (int32 i = pageIndex; i-- > 0;) {
busyConditions[i].Unpublish();
if (pages[i]->usage_count < 0)
pages[i]->usage_count = 1;
else
pages[i]->usage_count++;
if (writeThrough)
pages[i]->state = PAGE_STATE_ACTIVE;
else
@@ -960,6 +953,13 @@ cache_io(void *_cacheRef, off_t offset, addr_t buffer, size_t *_size,
vm_get_physical_page(page->physical_page_number * B_PAGE_SIZE,
&virtualAddress, PHYSICAL_PAGE_CAN_WAIT);
// Since we don't actually map pages as part of an area, we have
// to manually maintain its usage_count
if (page->usage_count < 0)
page->usage_count = 1;
else
page->usage_count++;
// and copy the contents of the page already in memory
if (doWrite) {
user_memcpy((void *)(virtualAddress + pageOffset),