diff options
author | Lei Zhang <thestig@chromium.org> | 2018-10-16 18:40:15 +0000 |
---|---|---|
committer | Chromium commit bot <commit-bot@chromium.org> | 2018-10-16 18:40:15 +0000 |
commit | f1fae3cd1b9492cf9411dffd3c486b9672d8cc76 (patch) | |
tree | bee5d8b2528e714149d399163519f0fa35ec532b /third_party/base/allocator/partition_allocator/page_allocator.h | |
parent | 1b6fcaad0722fb586620efc974726dee3fb0f80f (diff) | |
download | pdfium-f1fae3cd1b9492cf9411dffd3c486b9672d8cc76.tar.xz |
Update PartitionAlloc from Chromium at r599712.
BUG=pdfium:1170
Change-Id: I0f8dfb3d517beaa682a9ca7ad4831c5a7a10dc3b
Reviewed-on: https://pdfium-review.googlesource.com/c/44073
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Diffstat (limited to 'third_party/base/allocator/partition_allocator/page_allocator.h')
-rw-r--r-- | third_party/base/allocator/partition_allocator/page_allocator.h | 222 |
1 files changed, 135 insertions, 87 deletions
diff --git a/third_party/base/allocator/partition_allocator/page_allocator.h b/third_party/base/allocator/partition_allocator/page_allocator.h index bf9c0987a0..64be33c3c2 100644 --- a/third_party/base/allocator/partition_allocator/page_allocator.h +++ b/third_party/base/allocator/partition_allocator/page_allocator.h @@ -2,132 +2,180 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H -#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H +#ifndef THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H_ +#define THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H_ #include <stdint.h> #include <cstddef> #include "build/build_config.h" +#include "third_party/base/allocator/partition_allocator/page_allocator_constants.h" #include "third_party/base/base_export.h" #include "third_party/base/compiler_specific.h" namespace pdfium { namespace base { -#if defined(OS_WIN) -static const size_t kPageAllocationGranularityShift = 16; // 64KB -#elif defined(_MIPS_ARCH_LOONGSON) -static const size_t kPageAllocationGranularityShift = 14; // 16KB -#else -static const size_t kPageAllocationGranularityShift = 12; // 4KB -#endif -static const size_t kPageAllocationGranularity = - 1 << kPageAllocationGranularityShift; -static const size_t kPageAllocationGranularityOffsetMask = - kPageAllocationGranularity - 1; -static const size_t kPageAllocationGranularityBaseMask = - ~kPageAllocationGranularityOffsetMask; - -// All Blink-supported systems have 4096 sized system pages and can handle -// permissions and commit / decommit at this granularity. -// Loongson have 16384 sized system pages. -#if defined(_MIPS_ARCH_LOONGSON) -static const size_t kSystemPageSize = 16384; -#else -static const size_t kSystemPageSize = 4096; -#endif -static const size_t kSystemPageOffsetMask = kSystemPageSize - 1; -static const size_t kSystemPageBaseMask = ~kSystemPageOffsetMask; - enum PageAccessibilityConfiguration { - PageAccessible, PageInaccessible, + PageRead, + PageReadWrite, + PageReadExecute, + // This flag is deprecated and will go away soon. + // TODO(bbudge) Remove this as soon as V8 doesn't need RWX pages. + PageReadWriteExecute, +}; + +// Mac OSX supports tagged memory regions, to help in debugging. +enum class PageTag { + kFirst = 240, // Minimum tag value. + kChromium = 254, // Chromium page, including off-heap V8 ArrayBuffers. + kV8 = 255, // V8 heap pages. + kLast = kV8 // Maximum tag value. }; // Allocate one or more pages. -// The requested address is just a hint; the actual address returned may -// differ. The returned address will be aligned at least to align bytes. -// len is in bytes, and must be a multiple of kPageAllocationGranularity. -// align is in bytes, and must be a power-of-two multiple of -// kPageAllocationGranularity. -// If addr is null, then a suitable and randomized address will be chosen +// +// The requested |address| is just a hint; the actual address returned may +// differ. The returned address will be aligned at least to |align| bytes. +// |length| is in bytes, and must be a multiple of |kPageAllocationGranularity|. +// |align| is in bytes, and must be a power-of-two multiple of +// |kPageAllocationGranularity|. +// +// If |address| is null, then a suitable and randomized address will be chosen // automatically. -// PageAccessibilityConfiguration controls the permission of the -// allocated pages. +// +// |page_accessibility| controls the permission of the allocated pages. +// // This call will return null if the allocation cannot be satisfied. BASE_EXPORT void* AllocPages(void* address, - size_t len, + size_t length, size_t align, - PageAccessibilityConfiguration); - -// Free one or more pages. -// addr and len must match a previous call to allocPages(). + PageAccessibilityConfiguration page_accessibility, + PageTag tag = PageTag::kChromium, + bool commit = true); + +// Free one or more pages starting at |address| and continuing for |length| +// bytes. +// +// |address| and |length| must match a previous call to |AllocPages|. Therefore, +// |address| must be aligned to |kPageAllocationGranularity| bytes, and |length| +// must be a multiple of |kPageAllocationGranularity|. BASE_EXPORT void FreePages(void* address, size_t length); -// Mark one or more system pages as being inaccessible. -// Subsequently accessing any address in the range will fault, and the -// addresses will not be re-used by future allocations. -// len must be a multiple of kSystemPageSize bytes. -BASE_EXPORT void SetSystemPagesInaccessible(void* address, size_t length); - -// Mark one or more system pages as being accessible. -// The pages will be readable and writeable. -// len must be a multiple of kSystemPageSize bytes. -// The result bool value indicates whether the permission -// change succeeded or not. You must check the result -// (in most cases you need to CHECK that it is true). -BASE_EXPORT WARN_UNUSED_RESULT bool SetSystemPagesAccessible(void* address, - size_t length); - -// Decommit one or more system pages. Decommitted means that the physical memory -// is released to the system, but the virtual address space remains reserved. -// System pages are re-committed by calling recommitSystemPages(). Touching -// a decommitted page _may_ fault. -// Clients should not make any assumptions about the contents of decommitted -// system pages, before or after they write to the page. The only guarantee -// provided is that the contents of the system page will be deterministic again -// after recommitting and writing to it. In particlar note that system pages are -// not guaranteed to be zero-filled upon re-commit. len must be a multiple of -// kSystemPageSize bytes. +// Mark one or more system pages, starting at |address| with the given +// |page_accessibility|. |length| must be a multiple of |kSystemPageSize| bytes. +// +// Returns true if the permission change succeeded. In most cases you must +// |CHECK| the result. +BASE_EXPORT WARN_UNUSED_RESULT bool SetSystemPagesAccess( + void* address, + size_t length, + PageAccessibilityConfiguration page_accessibility); + +// Decommit one or more system pages starting at |address| and continuing for +// |length| bytes. |length| must be a multiple of |kSystemPageSize|. +// +// Decommitted means that physical resources (RAM or swap) backing the allocated +// virtual address range are released back to the system, but the address space +// is still allocated to the process (possibly using up page table entries or +// other accounting resources). Any access to a decommitted region of memory +// is an error and will generate a fault. +// +// This operation is not atomic on all platforms. +// +// Note: "Committed memory" is a Windows Memory Subsystem concept that ensures +// processes will not fault when touching a committed memory region. There is +// no analogue in the POSIX memory API where virtual memory pages are +// best-effort allocated resources on the first touch. To create a +// platform-agnostic abstraction, this API simulates the Windows "decommit" +// state by both discarding the region (allowing the OS to avoid swap +// operations) and changing the page protections so accesses fault. +// +// TODO(ajwong): This currently does not change page protections on POSIX +// systems due to a perf regression. Tracked at http://crbug.com/766882. BASE_EXPORT void DecommitSystemPages(void* address, size_t length); -// Recommit one or more system pages. Decommitted system pages must be -// recommitted before they are read are written again. -// Note that this operation may be a no-op on some platforms. -// len must be a multiple of kSystemPageSize bytes. -BASE_EXPORT void RecommitSystemPages(void* address, size_t length); - -// Discard one or more system pages. Discarding is a hint to the system that -// the page is no longer required. The hint may: -// - Do nothing. -// - Discard the page immediately, freeing up physical pages. -// - Discard the page at some time in the future in response to memory pressure. -// Only committed pages should be discarded. Discarding a page does not -// decommit it, and it is valid to discard an already-discarded page. -// A read or write to a discarded page will not fault. -// Reading from a discarded page may return the original page content, or a -// page full of zeroes. +// Recommit one or more system pages, starting at |address| and continuing for +// |length| bytes with the given |page_accessibility|. |length| must be a +// multiple of |kSystemPageSize|. +// +// Decommitted system pages must be recommitted with their original permissions +// before they are used again. +// +// Returns true if the recommit change succeeded. In most cases you must |CHECK| +// the result. +BASE_EXPORT WARN_UNUSED_RESULT bool RecommitSystemPages( + void* address, + size_t length, + PageAccessibilityConfiguration page_accessibility); + +// Discard one or more system pages starting at |address| and continuing for +// |length| bytes. |length| must be a multiple of |kSystemPageSize|. +// +// Discarding is a hint to the system that the page is no longer required. The +// hint may: +// - Do nothing. +// - Discard the page immediately, freeing up physical pages. +// - Discard the page at some time in the future in response to memory +// pressure. +// +// Only committed pages should be discarded. Discarding a page does not decommit +// it, and it is valid to discard an already-discarded page. A read or write to +// a discarded page will not fault. +// +// Reading from a discarded page may return the original page content, or a page +// full of zeroes. +// // Writing to a discarded page is the only guaranteed way to tell the system // that the page is required again. Once written to, the content of the page is // guaranteed stable once more. After being written to, the page content may be // based on the original page content, or a page of zeroes. -// len must be a multiple of kSystemPageSize bytes. BASE_EXPORT void DiscardSystemPages(void* address, size_t length); -ALWAYS_INLINE uintptr_t RoundUpToSystemPage(uintptr_t address) { +// Rounds up |address| to the next multiple of |kSystemPageSize|. Returns +// 0 for an |address| of 0. +constexpr ALWAYS_INLINE uintptr_t RoundUpToSystemPage(uintptr_t address) { return (address + kSystemPageOffsetMask) & kSystemPageBaseMask; } -ALWAYS_INLINE uintptr_t RoundDownToSystemPage(uintptr_t address) { +// Rounds down |address| to the previous multiple of |kSystemPageSize|. Returns +// 0 for an |address| of 0. +constexpr ALWAYS_INLINE uintptr_t RoundDownToSystemPage(uintptr_t address) { return address & kSystemPageBaseMask; } -// Returns errno (or GetLastError code) when mmap (or VirtualAlloc) fails. +// Rounds up |address| to the next multiple of |kPageAllocationGranularity|. +// Returns 0 for an |address| of 0. +constexpr ALWAYS_INLINE uintptr_t +RoundUpToPageAllocationGranularity(uintptr_t address) { + return (address + kPageAllocationGranularityOffsetMask) & + kPageAllocationGranularityBaseMask; +} + +// Rounds down |address| to the previous multiple of +// |kPageAllocationGranularity|. Returns 0 for an |address| of 0. +constexpr ALWAYS_INLINE uintptr_t +RoundDownToPageAllocationGranularity(uintptr_t address) { + return address & kPageAllocationGranularityBaseMask; +} + +// Reserves (at least) |size| bytes of address space, aligned to +// |kPageAllocationGranularity|. This can be called early on to make it more +// likely that large allocations will succeed. Returns true if the reservation +// succeeded, false if the reservation failed or a reservation was already made. +BASE_EXPORT bool ReserveAddressSpace(size_t size); + +// Releases any reserved address space. |AllocPages| calls this automatically on +// an allocation failure. External allocators may also call this on failure. +BASE_EXPORT void ReleaseReservation(); + +// Returns |errno| (POSIX) or the result of |GetLastError| (Windows) when |mmap| +// (POSIX) or |VirtualAlloc| (Windows) fails. BASE_EXPORT uint32_t GetAllocPageErrorCode(); } // namespace base } // namespace pdfium -#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H +#endif // THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H_ |