1 //===-- allocator_config.h --------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef SCUDO_ALLOCATOR_CONFIG_H_
10 #define SCUDO_ALLOCATOR_CONFIG_H_
11 
12 #include "combined.h"
13 #include "common.h"
14 #include "flags.h"
15 #include "primary32.h"
16 #include "primary64.h"
17 #include "secondary.h"
18 #include "size_class_map.h"
19 #include "tsd_exclusive.h"
20 #include "tsd_shared.h"
21 
22 namespace scudo {
23 
24 // The combined allocator uses a structure as a template argument that
25 // specifies the configuration options for the various subcomponents of the
26 // allocator.
27 //
28 // struct ExampleConfig {
29 //   // SizeClasMmap to use with the Primary.
30 //   using SizeClassMap = DefaultSizeClassMap;
31 //   // Indicates possible support for Memory Tagging.
32 //   static const bool MaySupportMemoryTagging = false;
33 //   // Defines the Primary allocator to use.
34 //   typedef SizeClassAllocator64<ExampleConfig> Primary;
35 //   // Log2 of the size of a size class region, as used by the Primary.
36 //   static const uptr PrimaryRegionSizeLog = 30U;
37 //   // Log2 of the size of block group, as used by the Primary. Each group
38 //   // contains a range of memory addresses, blocks in the range will belong to
39 //   // the same group. In general, single region may have 1 or 2MB group size.
40 //   // Multiple regions will have the group size equal to the region size
41 //   // because the region size is usually smaller than 1 MB.
42 //   // Smaller value gives fine-grained control of memory usage but the trade
43 //   // off is that it may take longer time of deallocation.
44 //   static const uptr PrimaryGroupSizeLog = 20U;
45 //   // Defines the type and scale of a compact pointer. A compact pointer can
46 //   // be understood as the offset of a pointer within the region it belongs
47 //   // to, in increments of a power-of-2 scale.
48 //   // eg: Ptr = Base + (CompactPtr << Scale).
49 //   typedef u32 PrimaryCompactPtrT;
50 //   static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
51 //   // Indicates support for offsetting the start of a region by
52 //   // a random number of pages. Only used with primary64.
53 //   static const bool PrimaryEnableRandomOffset = true;
54 //   // Call map for user memory with at least this size. Only used with
55 //   // primary64.
56 //   static const uptr PrimaryMapSizeIncrement = 1UL << 18;
57 //   // Defines the minimal & maximal release interval that can be set.
58 //   static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
59 //   static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
60 //   // Defines the type of cache used by the Secondary. Some additional
61 //   // configuration entries can be necessary depending on the Cache.
62 //   typedef MapAllocatorNoCache SecondaryCache;
63 //   // Thread-Specific Data Registry used, shared or exclusive.
64 //   template <class A> using TSDRegistryT = TSDRegistrySharedT<A, 8U, 4U>;
65 // };
66 
67 // Default configurations for various platforms.
68 
69 struct DefaultConfig {
70   using SizeClassMap = DefaultSizeClassMap;
71   static const bool MaySupportMemoryTagging = true;
72 
73 #if SCUDO_CAN_USE_PRIMARY64
74   typedef SizeClassAllocator64<DefaultConfig> Primary;
75   static const uptr PrimaryRegionSizeLog = 32U;
76   static const uptr PrimaryGroupSizeLog = 21U;
77   typedef uptr PrimaryCompactPtrT;
78   static const uptr PrimaryCompactPtrScale = 0;
79   static const bool PrimaryEnableRandomOffset = true;
80   static const uptr PrimaryMapSizeIncrement = 1UL << 18;
81 #else
82   typedef SizeClassAllocator32<DefaultConfig> Primary;
83   static const uptr PrimaryRegionSizeLog = 19U;
84   static const uptr PrimaryGroupSizeLog = 19U;
85   typedef uptr PrimaryCompactPtrT;
86 #endif
87   static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
88   static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
89 
90   typedef MapAllocatorCache<DefaultConfig> SecondaryCache;
91   static const u32 SecondaryCacheEntriesArraySize = 32U;
92   static const u32 SecondaryCacheQuarantineSize = 0U;
93   static const u32 SecondaryCacheDefaultMaxEntriesCount = 32U;
94   static const uptr SecondaryCacheDefaultMaxEntrySize = 1UL << 19;
95   static const s32 SecondaryCacheMinReleaseToOsIntervalMs = INT32_MIN;
96   static const s32 SecondaryCacheMaxReleaseToOsIntervalMs = INT32_MAX;
97 
98   template <class A> using TSDRegistryT = TSDRegistryExT<A>; // Exclusive
99 };
100 struct AndroidConfig {
101   using SizeClassMap = AndroidSizeClassMap;
102   static const bool MaySupportMemoryTagging = true;
103 
104 #if SCUDO_CAN_USE_PRIMARY64
105   typedef SizeClassAllocator64<AndroidConfig> Primary;
106   static const uptr PrimaryRegionSizeLog = 28U;
107   typedef u32 PrimaryCompactPtrT;
108   static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
109   static const uptr PrimaryGroupSizeLog = 20U;
110   static const bool PrimaryEnableRandomOffset = true;
111   static const uptr PrimaryMapSizeIncrement = 1UL << 18;
112 #else
113   typedef SizeClassAllocator32<AndroidConfig> Primary;
114   static const uptr PrimaryRegionSizeLog = 18U;
115   static const uptr PrimaryGroupSizeLog = 18U;
116   typedef uptr PrimaryCompactPtrT;
117 #endif
118   static const s32 PrimaryMinReleaseToOsIntervalMs = 1000;
119   static const s32 PrimaryMaxReleaseToOsIntervalMs = 1000;
120 
121   typedef MapAllocatorCache<AndroidConfig> SecondaryCache;
122   static const u32 SecondaryCacheEntriesArraySize = 256U;
123   static const u32 SecondaryCacheQuarantineSize = 32U;
124   static const u32 SecondaryCacheDefaultMaxEntriesCount = 32U;
125   static const uptr SecondaryCacheDefaultMaxEntrySize = 2UL << 20;
126   static const s32 SecondaryCacheMinReleaseToOsIntervalMs = 0;
127   static const s32 SecondaryCacheMaxReleaseToOsIntervalMs = 1000;
128 
129   template <class A>
130   using TSDRegistryT = TSDRegistrySharedT<A, 8U, 2U>; // Shared, max 8 TSDs.
131 };
132 
133 struct AndroidSvelteConfig {
134   using SizeClassMap = SvelteSizeClassMap;
135   static const bool MaySupportMemoryTagging = false;
136 
137 #if SCUDO_CAN_USE_PRIMARY64
138   typedef SizeClassAllocator64<AndroidSvelteConfig> Primary;
139   static const uptr PrimaryRegionSizeLog = 27U;
140   typedef u32 PrimaryCompactPtrT;
141   static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
142   static const uptr PrimaryGroupSizeLog = 18U;
143   static const bool PrimaryEnableRandomOffset = true;
144   static const uptr PrimaryMapSizeIncrement = 1UL << 18;
145 #else
146   typedef SizeClassAllocator32<AndroidSvelteConfig> Primary;
147   static const uptr PrimaryRegionSizeLog = 16U;
148   static const uptr PrimaryGroupSizeLog = 16U;
149   typedef uptr PrimaryCompactPtrT;
150 #endif
151   static const s32 PrimaryMinReleaseToOsIntervalMs = 1000;
152   static const s32 PrimaryMaxReleaseToOsIntervalMs = 1000;
153 
154   typedef MapAllocatorCache<AndroidSvelteConfig> SecondaryCache;
155   static const u32 SecondaryCacheEntriesArraySize = 16U;
156   static const u32 SecondaryCacheQuarantineSize = 32U;
157   static const u32 SecondaryCacheDefaultMaxEntriesCount = 4U;
158   static const uptr SecondaryCacheDefaultMaxEntrySize = 1UL << 18;
159   static const s32 SecondaryCacheMinReleaseToOsIntervalMs = 0;
160   static const s32 SecondaryCacheMaxReleaseToOsIntervalMs = 0;
161 
162   template <class A>
163   using TSDRegistryT = TSDRegistrySharedT<A, 2U, 1U>; // Shared, max 2 TSDs.
164 };
165 
166 #if SCUDO_CAN_USE_PRIMARY64
167 struct FuchsiaConfig {
168   using SizeClassMap = FuchsiaSizeClassMap;
169   static const bool MaySupportMemoryTagging = false;
170 
171   typedef SizeClassAllocator64<FuchsiaConfig> Primary;
172   static const uptr PrimaryRegionSizeLog = 30U;
173   static const uptr PrimaryGroupSizeLog = 21U;
174   typedef u32 PrimaryCompactPtrT;
175   static const bool PrimaryEnableRandomOffset = true;
176   static const uptr PrimaryMapSizeIncrement = 1UL << 18;
177   static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
178   static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
179   static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
180 
181   typedef MapAllocatorNoCache SecondaryCache;
182   template <class A>
183   using TSDRegistryT = TSDRegistrySharedT<A, 8U, 4U>; // Shared, max 8 TSDs.
184 };
185 
186 struct TrustyConfig {
187   using SizeClassMap = TrustySizeClassMap;
188   static const bool MaySupportMemoryTagging = false;
189 
190   typedef SizeClassAllocator64<TrustyConfig> Primary;
191   // Some apps have 1 page of heap total so small regions are necessary.
192   static const uptr PrimaryRegionSizeLog = 10U;
193   static const uptr PrimaryGroupSizeLog = 10U;
194   typedef u32 PrimaryCompactPtrT;
195   static const bool PrimaryEnableRandomOffset = false;
196   // Trusty is extremely memory-constrained so minimally round up map calls.
197   static const uptr PrimaryMapSizeIncrement = 1UL << 4;
198   static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
199   static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
200   static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
201 
202   typedef MapAllocatorNoCache SecondaryCache;
203   template <class A>
204   using TSDRegistryT = TSDRegistrySharedT<A, 1U, 1U>; // Shared, max 1 TSD.
205 };
206 #endif
207 
208 #if SCUDO_ANDROID
209 typedef AndroidConfig Config;
210 #elif SCUDO_FUCHSIA
211 typedef FuchsiaConfig Config;
212 #elif SCUDO_TRUSTY
213 typedef TrustyConfig Config;
214 #else
215 typedef DefaultConfig Config;
216 #endif
217 
218 } // namespace scudo
219 
220 #endif // SCUDO_ALLOCATOR_CONFIG_H_
221