blob: bf9c0987a0fbb705db25d61ca7832a3e4733d6ab [file] [log] [blame]
// Copyright (c) 2013 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 BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H
#include <stdint.h>
#include <cstddef>
#include "build/build_config.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,
};
// 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
// automatically.
// PageAccessibilityConfiguration 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 align,
PageAccessibilityConfiguration);
// Free one or more pages.
// addr and len must match a previous call to allocPages().
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.
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.
// 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) {
return (address + kSystemPageOffsetMask) & kSystemPageBaseMask;
}
ALWAYS_INLINE uintptr_t RoundDownToSystemPage(uintptr_t address) {
return address & kSystemPageBaseMask;
}
// Returns errno (or GetLastError code) when mmap (or VirtualAlloc) fails.
BASE_EXPORT uint32_t GetAllocPageErrorCode();
} // namespace base
} // namespace pdfium
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H