From 7fa3e4e68a17d41ffa9b2ce945d5aeec6ddf7e61 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 26 Jan 2010 17:22:46 +0000 Subject: [PATCH] cache_io(): Reevaluate the memory situation periodically. Deciding at the beginning whether to pass the cache by really doesn't help when reading/writing a huge amount of data, since a low memory situation is likely to occur at some point during the operation. This should fix the main issue of #3768. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35299 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/cache/file_cache.cpp | 37 ++++++++++++-------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/system/kernel/cache/file_cache.cpp b/src/system/kernel/cache/file_cache.cpp index 8efea17f67..3746ef0232 100644 --- a/src/system/kernel/cache/file_cache.cpp +++ b/src/system/kernel/cache/file_cache.cpp @@ -736,25 +736,6 @@ cache_io(void* _cacheRef, void* cookie, off_t offset, addr_t buffer, if (size == 0) return B_OK; - cache_func function; - if (doWrite) { - // in low memory situations, we bypass the cache beyond a - // certain I/O size - if (size >= BYPASS_IO_SIZE - && low_resource_state(B_KERNEL_RESOURCE_PAGES) - != B_NO_LOW_RESOURCE) { - function = write_to_file; - } else - function = write_to_cache; - } else { - if (size >= BYPASS_IO_SIZE - && low_resource_state(B_KERNEL_RESOURCE_PAGES) - != B_NO_LOW_RESOURCE) { - function = read_from_file; - } else - function = read_into_cache; - } - // "offset" and "lastOffset" are always aligned to B_PAGE_SIZE, // the "last*" variables always point to the end of the last // satisfied request part @@ -767,18 +748,33 @@ cache_io(void* _cacheRef, void* cookie, off_t offset, addr_t buffer, size_t lastReservedPages = min_c(MAX_IO_VECS, (pageOffset + bytesLeft + B_PAGE_SIZE - 1) >> PAGE_SHIFT); size_t reservePages = 0; + size_t pagesProcessed = 0; + cache_func function = NULL; reserve_pages(ref, lastReservedPages, doWrite); AutoLocker locker(cache); while (bytesLeft > 0) { + // Periodically reevaluate the low memory situation and select the + // read/write hook accordingly + if (pagesProcessed % 32 == 0) { + if (size >= BYPASS_IO_SIZE + && low_resource_state(B_KERNEL_RESOURCE_PAGES) + != B_NO_LOW_RESOURCE) { + // In low memory situations we bypass the cache beyond a + // certain I/O size. + function = doWrite ? write_to_file : read_from_file; + } else + function = doWrite ? write_to_cache : read_into_cache; + } + // check if this page is already in memory vm_page* page = cache->LookupPage(offset); if (page != NULL) { // The page may be busy - since we need to unlock the cache sometime // in the near future, we need to satisfy the request of the pages // we didn't get yet (to make sure no one else interferes in the - // mean time). + // meantime). status_t status = satisfy_cache_io(ref, cookie, function, offset, buffer, useBuffer, pageOffset, bytesLeft, reservePages, lastOffset, lastBuffer, lastPageOffset, lastLeft, @@ -863,6 +859,7 @@ cache_io(void* _cacheRef, void* cookie, off_t offset, addr_t buffer, bytesLeft -= bytesInPage; pageOffset = 0; offset += B_PAGE_SIZE; + pagesProcessed++; if (buffer - lastBuffer + lastPageOffset >= kMaxChunkSize) { status_t status = satisfy_cache_io(ref, cookie, function, offset,