Skip to content

Commit

Permalink
Replace VirtualFree(DECOMMIT) with DiscardVirtualMemory in Purge().
Browse files Browse the repository at this point in the history
Windows does not allow page-file backed memory-mapped file pages to be
de-committed, so the call to VirtualFree(MEM_DECOMMIT) always fails.

Windows 8.1 and above provide DiscardVirtualMemory(), which releases
the underlying storage for pages without decommitting them. This is
equivalent to swapping-out the pages, freeing up the physical memory
they occupied, but without any actual paging activity, since their
contents are being lost. The pages continue to be accounted against
the system's total commit charge, so this won't prevent apps OOMing
if the available commit charge is low.

Bug: 747657
Change-Id: Icf6d4b16c1adcc545b09bad207a9abd4a97e4726
Reviewed-on: https://chromium-review.googlesource.com/615062
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Penny MacNeil <pennymac@chromium.org>
Commit-Queue: Penny MacNeil <pennymac@chromium.org>
Cr-Commit-Position: refs/heads/master@{#495691}
  • Loading branch information
Wez authored and Commit Bot committed Aug 18, 2017
1 parent f8f68d1 commit 17da1b4
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions base/memory/discardable_shared_memory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
#include "third_party/ashmem/ashmem.h"
#endif

#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif

namespace base {
namespace {

Expand Down Expand Up @@ -383,12 +387,24 @@ bool DiscardableSharedMemory::Purge(Time current_time) {
DPLOG(ERROR) << "madvise() failed";
}
#elif defined(OS_WIN)
// MEM_DECOMMIT the purged pages to release the physical storage,
// either in memory or in the paging file on disk. Pages remain RESERVED.
if (!VirtualFree(reinterpret_cast<char*>(shared_memory_.memory()) +
AlignToPageSize(sizeof(SharedState)),
AlignToPageSize(mapped_size_), MEM_DECOMMIT)) {
DPLOG(ERROR) << "VirtualFree() MEM_DECOMMIT failed in Purge()";
if (base::win::GetVersion() >= base::win::VERSION_WIN8_1) {
// Discard the purged pages, which releases the physical storage (resident
// memory, compressed or swapped), but leaves them reserved & committed.
// This does not free commit for use by other applications, but allows the
// system to avoid compressing/swapping these pages to free physical memory.
static const auto discard_virtual_memory =
reinterpret_cast<decltype(&::DiscardVirtualMemory)>(GetProcAddress(
GetModuleHandle(L"kernel32.dll"), "DiscardVirtualMemory"));
if (discard_virtual_memory) {
DWORD discard_result = discard_virtual_memory(
reinterpret_cast<char*>(shared_memory_.memory()) +
AlignToPageSize(sizeof(SharedState)),
AlignToPageSize(mapped_size_));
if (discard_result != ERROR_SUCCESS) {
DLOG(FATAL) << "DiscardVirtualMemory() failed in Purge(): "
<< logging::SystemErrorCodeToString(discard_result);
}
}
}
#endif

Expand Down

0 comments on commit 17da1b4

Please sign in to comment.