diff options
Diffstat (limited to 'third_party/base/allocator/partition_allocator/page_allocator_internals_win.h')
-rw-r--r-- | third_party/base/allocator/partition_allocator/page_allocator_internals_win.h | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/third_party/base/allocator/partition_allocator/page_allocator_internals_win.h b/third_party/base/allocator/partition_allocator/page_allocator_internals_win.h new file mode 100644 index 0000000000..57a11c521b --- /dev/null +++ b/third_party/base/allocator/partition_allocator/page_allocator_internals_win.h @@ -0,0 +1,123 @@ +// Copyright (c) 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNALS_WIN_H_ +#define THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNALS_WIN_H_ + +#include "third_party/base/allocator/partition_allocator/page_allocator_internal.h" + +namespace pdfium { +namespace base { + +// |VirtualAlloc| will fail if allocation at the hint address is blocked. +constexpr bool kHintIsAdvisory = false; +std::atomic<int32_t> s_allocPageErrorCode{ERROR_SUCCESS}; + +int GetAccessFlags(PageAccessibilityConfiguration accessibility) { + switch (accessibility) { + case PageRead: + return PAGE_READONLY; + case PageReadWrite: + return PAGE_READWRITE; + case PageReadExecute: + return PAGE_EXECUTE_READ; + case PageReadWriteExecute: + return PAGE_EXECUTE_READWRITE; + default: + NOTREACHED(); + FALLTHROUGH; + case PageInaccessible: + return PAGE_NOACCESS; + } +} + +void* SystemAllocPagesInternal(void* hint, + size_t length, + PageAccessibilityConfiguration accessibility, + PageTag page_tag, + bool commit) { + DWORD access_flag = GetAccessFlags(accessibility); + const DWORD type_flags = commit ? (MEM_RESERVE | MEM_COMMIT) : MEM_RESERVE; + void* ret = VirtualAlloc(hint, length, type_flags, access_flag); + if (ret == nullptr) { + s_allocPageErrorCode = GetLastError(); + } + return ret; +} + +void* TrimMappingInternal(void* base, + size_t base_length, + size_t trim_length, + PageAccessibilityConfiguration accessibility, + bool commit, + size_t pre_slack, + size_t post_slack) { + void* ret = base; + if (pre_slack || post_slack) { + // We cannot resize the allocation run. Free it and retry at the aligned + // address within the freed range. + ret = reinterpret_cast<char*>(base) + pre_slack; + FreePages(base, base_length); + ret = SystemAllocPages(ret, trim_length, accessibility, PageTag::kChromium, + commit); + } + return ret; +} + +bool SetSystemPagesAccessInternal( + void* address, + size_t length, + PageAccessibilityConfiguration accessibility) { + if (accessibility == PageInaccessible) { + return VirtualFree(address, length, MEM_DECOMMIT) != 0; + } else { + return nullptr != VirtualAlloc(address, length, MEM_COMMIT, + GetAccessFlags(accessibility)); + } +} + +void FreePagesInternal(void* address, size_t length) { + CHECK(VirtualFree(address, 0, MEM_RELEASE)); +} + +void DecommitSystemPagesInternal(void* address, size_t length) { + CHECK(SetSystemPagesAccess(address, length, PageInaccessible)); +} + +bool RecommitSystemPagesInternal(void* address, + size_t length, + PageAccessibilityConfiguration accessibility) { + return SetSystemPagesAccess(address, length, accessibility); +} + +void DiscardSystemPagesInternal(void* address, size_t length) { + // On Windows, discarded pages are not returned to the system immediately and + // not guaranteed to be zeroed when returned to the application. + using DiscardVirtualMemoryFunction = + DWORD(WINAPI*)(PVOID virtualAddress, SIZE_T size); + static DiscardVirtualMemoryFunction discard_virtual_memory = + reinterpret_cast<DiscardVirtualMemoryFunction>(-1); + if (discard_virtual_memory == + reinterpret_cast<DiscardVirtualMemoryFunction>(-1)) + discard_virtual_memory = + reinterpret_cast<DiscardVirtualMemoryFunction>(GetProcAddress( + GetModuleHandle(L"Kernel32.dll"), "DiscardVirtualMemory")); + // Use DiscardVirtualMemory when available because it releases faster than + // MEM_RESET. + DWORD ret = 1; + if (discard_virtual_memory) { + ret = discard_virtual_memory(address, length); + } + // DiscardVirtualMemory is buggy in Win10 SP0, so fall back to MEM_RESET on + // failure. + if (ret) { + void* ptr = VirtualAlloc(address, length, MEM_RESET, PAGE_READWRITE); + CHECK(ptr); + } +} + +} // namespace base +} // namespace pdfium + +#endif // THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNALS_WIN_H_ |