1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H
6 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H
7
8 #include <stdint.h>
9
10 #include <cstddef>
11
12 #include "third_party/base/base_export.h"
13 #include "third_party/base/compiler_specific.h"
14 #include "third_party/build/build_config.h"
15
16 namespace pdfium {
17 namespace base {
18
19 #if defined(OS_WIN)
20 static const size_t kPageAllocationGranularityShift = 16; // 64KB
21 #elif defined(_MIPS_ARCH_LOONGSON)
22 static const size_t kPageAllocationGranularityShift = 14; // 16KB
23 #else
24 static const size_t kPageAllocationGranularityShift = 12; // 4KB
25 #endif
26 static const size_t kPageAllocationGranularity =
27 1 << kPageAllocationGranularityShift;
28 static const size_t kPageAllocationGranularityOffsetMask =
29 kPageAllocationGranularity - 1;
30 static const size_t kPageAllocationGranularityBaseMask =
31 ~kPageAllocationGranularityOffsetMask;
32
33 // All Blink-supported systems have 4096 sized system pages and can handle
34 // permissions and commit / decommit at this granularity.
35 // Loongson have 16384 sized system pages.
36 #if defined(_MIPS_ARCH_LOONGSON)
37 static const size_t kSystemPageSize = 16384;
38 #else
39 static const size_t kSystemPageSize = 4096;
40 #endif
41 static const size_t kSystemPageOffsetMask = kSystemPageSize - 1;
42 static const size_t kSystemPageBaseMask = ~kSystemPageOffsetMask;
43
44 enum PageAccessibilityConfiguration {
45 PageAccessible,
46 PageInaccessible,
47 };
48
49 // Allocate one or more pages.
50 // The requested address is just a hint; the actual address returned may
51 // differ. The returned address will be aligned at least to align bytes.
52 // len is in bytes, and must be a multiple of kPageAllocationGranularity.
53 // align is in bytes, and must be a power-of-two multiple of
54 // kPageAllocationGranularity.
55 // If addr is null, then a suitable and randomized address will be chosen
56 // automatically.
57 // PageAccessibilityConfiguration controls the permission of the
58 // allocated pages.
59 // This call will return null if the allocation cannot be satisfied.
60 BASE_EXPORT void* AllocPages(void* address,
61 size_t len,
62 size_t align,
63 PageAccessibilityConfiguration);
64
65 // Free one or more pages.
66 // addr and len must match a previous call to allocPages().
67 BASE_EXPORT void FreePages(void* address, size_t length);
68
69 // Mark one or more system pages as being inaccessible.
70 // Subsequently accessing any address in the range will fault, and the
71 // addresses will not be re-used by future allocations.
72 // len must be a multiple of kSystemPageSize bytes.
73 BASE_EXPORT void SetSystemPagesInaccessible(void* address, size_t length);
74
75 // Mark one or more system pages as being accessible.
76 // The pages will be readable and writeable.
77 // len must be a multiple of kSystemPageSize bytes.
78 // The result bool value indicates whether the permission
79 // change succeeded or not. You must check the result
80 // (in most cases you need to CHECK that it is true).
81 BASE_EXPORT WARN_UNUSED_RESULT bool SetSystemPagesAccessible(void* address,
82 size_t length);
83
84 // Decommit one or more system pages. Decommitted means that the physical memory
85 // is released to the system, but the virtual address space remains reserved.
86 // System pages are re-committed by calling recommitSystemPages(). Touching
87 // a decommitted page _may_ fault.
88 // Clients should not make any assumptions about the contents of decommitted
89 // system pages, before or after they write to the page. The only guarantee
90 // provided is that the contents of the system page will be deterministic again
91 // after recommitting and writing to it. In particlar note that system pages are
92 // not guaranteed to be zero-filled upon re-commit. len must be a multiple of
93 // kSystemPageSize bytes.
94 BASE_EXPORT void DecommitSystemPages(void* address, size_t length);
95
96 // Recommit one or more system pages. Decommitted system pages must be
97 // recommitted before they are read are written again.
98 // Note that this operation may be a no-op on some platforms.
99 // len must be a multiple of kSystemPageSize bytes.
100 BASE_EXPORT void RecommitSystemPages(void* address, size_t length);
101
102 // Discard one or more system pages. Discarding is a hint to the system that
103 // the page is no longer required. The hint may:
104 // - Do nothing.
105 // - Discard the page immediately, freeing up physical pages.
106 // - Discard the page at some time in the future in response to memory pressure.
107 // Only committed pages should be discarded. Discarding a page does not
108 // decommit it, and it is valid to discard an already-discarded page.
109 // A read or write to a discarded page will not fault.
110 // Reading from a discarded page may return the original page content, or a
111 // page full of zeroes.
112 // Writing to a discarded page is the only guaranteed way to tell the system
113 // that the page is required again. Once written to, the content of the page is
114 // guaranteed stable once more. After being written to, the page content may be
115 // based on the original page content, or a page of zeroes.
116 // len must be a multiple of kSystemPageSize bytes.
117 BASE_EXPORT void DiscardSystemPages(void* address, size_t length);
118
RoundUpToSystemPage(uintptr_t address)119 ALWAYS_INLINE uintptr_t RoundUpToSystemPage(uintptr_t address) {
120 return (address + kSystemPageOffsetMask) & kSystemPageBaseMask;
121 }
122
RoundDownToSystemPage(uintptr_t address)123 ALWAYS_INLINE uintptr_t RoundDownToSystemPage(uintptr_t address) {
124 return address & kSystemPageBaseMask;
125 }
126
127 // Returns errno (or GetLastError code) when mmap (or VirtualAlloc) fails.
128 BASE_EXPORT uint32_t GetAllocPageErrorCode();
129
130 } // namespace base
131 } // namespace pdfium
132
133 #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H
134