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 "condition_variable.h"
15#include "flags.h"
16#include "primary32.h"
17#include "primary64.h"
18#include "secondary.h"
19#include "size_class_map.h"
20#include "tsd_exclusive.h"
21#include "tsd_shared.h"
22
23// To import a custom configuration, define `SCUDO_USE_CUSTOM_CONFIG` and
24// aliasing the `Config` like:
25//
26// namespace scudo {
27//   // The instance of Scudo will be initiated with `Config`.
28//   typedef CustomConfig Config;
29//   // Aliasing as default configuration to run the tests with this config.
30//   typedef CustomConfig DefaultConfig;
31// } // namespace scudo
32//
33// Put them in the header `custom_scudo_config.h` then you will be using the
34// custom configuration and able to run all the tests as well.
35#ifdef SCUDO_USE_CUSTOM_CONFIG
36#include "custom_scudo_config.h"
37#endif
38
39namespace scudo {
40
41// The combined allocator uses a structure as a template argument that
42// specifies the configuration options for the various subcomponents of the
43// allocator.
44//
45// struct ExampleConfig {
46//   // Indicates possible support for Memory Tagging.
47//   static const bool MaySupportMemoryTagging = false;
48//
49//   // Thread-Specific Data Registry used, shared or exclusive.
50//   template <class A> using TSDRegistryT = TSDRegistrySharedT<A, 8U, 4U>;
51//
52//   struct Primary {
53//     // SizeClassMap to use with the Primary.
54//     using SizeClassMap = DefaultSizeClassMap;
55//
56//     // Log2 of the size of a size class region, as used by the Primary.
57//     static const uptr RegionSizeLog = 30U;
58//
59//     // Log2 of the size of block group, as used by the Primary. Each group
60//     // contains a range of memory addresses, blocks in the range will belong
61//     // to the same group. In general, single region may have 1 or 2MB group
62//     // size. Multiple regions will have the group size equal to the region
63//     // size because the region size is usually smaller than 1 MB.
64//     // Smaller value gives fine-grained control of memory usage but the
65//     // trade-off is that it may take longer time of deallocation.
66//     static const uptr GroupSizeLog = 20U;
67//
68//     // Defines the type and scale of a compact pointer. A compact pointer can
69//     // be understood as the offset of a pointer within the region it belongs
70//     // to, in increments of a power-of-2 scale.
71//     // eg: Ptr = Base + (CompactPtr << Scale).
72//     typedef u32 CompactPtrT;
73//     static const uptr CompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
74//
75//     // Indicates support for offsetting the start of a region by
76//     // a random number of pages. Only used with primary64.
77//     static const bool EnableRandomOffset = true;
78//
79//     // Call map for user memory with at least this size. Only used with
80//     // primary64.
81//     static const uptr MapSizeIncrement = 1UL << 18;
82//
83//     // Defines the minimal & maximal release interval that can be set.
84//     static const s32 MinReleaseToOsIntervalMs = INT32_MIN;
85//     static const s32 MaxReleaseToOsIntervalMs = INT32_MAX;
86//
87//     // Use condition variable to shorten the waiting time of refillment of
88//     // freelist. Note that this depends on the implementation of condition
89//     // variable on each platform and the performance may vary so that it
90//     // doesn't guarantee a performance benefit.
91//     // Note that both variables have to be defined to enable it.
92//     static const bool UseConditionVariable = true;
93//     using ConditionVariableT = ConditionVariableLinux;
94//   };
95//   // Defines the type of Primary allocator to use.
96//   template <typename Config> using PrimaryT = SizeClassAllocator64<Config>;
97//
98//   // Defines the type of cache used by the Secondary. Some additional
99//   // configuration entries can be necessary depending on the Cache.
100//   struct Secondary {
101//     struct Cache {
102//       static const u32 EntriesArraySize = 32U;
103//       static const u32 QuarantineSize = 0U;
104//       static const u32 DefaultMaxEntriesCount = 32U;
105//       static const uptr DefaultMaxEntrySize = 1UL << 19;
106//       static const s32 MinReleaseToOsIntervalMs = INT32_MIN;
107//       static const s32 MaxReleaseToOsIntervalMs = INT32_MAX;
108//     };
109//     // Defines the type of Secondary Cache to use.
110//     template <typename Config> using CacheT = MapAllocatorCache<Config>;
111//   };
112//   // Defines the type of Secondary allocator to use.
113//   template <typename Config> using SecondaryT = MapAllocator<Config>;
114// };
115
116#ifndef SCUDO_USE_CUSTOM_CONFIG
117
118// Default configurations for various platforms. Note this is only enabled when
119// there's no custom configuration in the build system.
120struct DefaultConfig {
121  static const bool MaySupportMemoryTagging = true;
122  template <class A> using TSDRegistryT = TSDRegistryExT<A>; // Exclusive
123
124  struct Primary {
125    using SizeClassMap = DefaultSizeClassMap;
126#if SCUDO_CAN_USE_PRIMARY64
127    static const uptr RegionSizeLog = 32U;
128    static const uptr GroupSizeLog = 21U;
129    typedef uptr CompactPtrT;
130    static const uptr CompactPtrScale = 0;
131    static const bool EnableRandomOffset = true;
132    static const uptr MapSizeIncrement = 1UL << 18;
133#else
134    static const uptr RegionSizeLog = 19U;
135    static const uptr GroupSizeLog = 19U;
136    typedef uptr CompactPtrT;
137#endif
138    static const s32 MinReleaseToOsIntervalMs = INT32_MIN;
139    static const s32 MaxReleaseToOsIntervalMs = INT32_MAX;
140  };
141#if SCUDO_CAN_USE_PRIMARY64
142  template <typename Config> using PrimaryT = SizeClassAllocator64<Config>;
143#else
144  template <typename Config> using PrimaryT = SizeClassAllocator32<Config>;
145#endif
146
147  struct Secondary {
148    struct Cache {
149      static const u32 EntriesArraySize = 32U;
150      static const u32 QuarantineSize = 0U;
151      static const u32 DefaultMaxEntriesCount = 32U;
152      static const uptr DefaultMaxEntrySize = 1UL << 19;
153      static const s32 MinReleaseToOsIntervalMs = INT32_MIN;
154      static const s32 MaxReleaseToOsIntervalMs = INT32_MAX;
155    };
156    template <typename Config> using CacheT = MapAllocatorCache<Config>;
157  };
158
159  template <typename Config> using SecondaryT = MapAllocator<Config>;
160};
161
162#endif // SCUDO_USE_CUSTOM_CONFIG
163
164struct AndroidConfig {
165  static const bool MaySupportMemoryTagging = true;
166  template <class A>
167  using TSDRegistryT = TSDRegistrySharedT<A, 8U, 2U>; // Shared, max 8 TSDs.
168
169  struct Primary {
170    using SizeClassMap = AndroidSizeClassMap;
171#if SCUDO_CAN_USE_PRIMARY64
172    static const uptr RegionSizeLog = 28U;
173    typedef u32 CompactPtrT;
174    static const uptr CompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
175    static const uptr GroupSizeLog = 20U;
176    static const bool EnableRandomOffset = true;
177    static const uptr MapSizeIncrement = 1UL << 18;
178#else
179    static const uptr RegionSizeLog = 18U;
180    static const uptr GroupSizeLog = 18U;
181    typedef uptr CompactPtrT;
182#endif
183    static const s32 MinReleaseToOsIntervalMs = 1000;
184    static const s32 MaxReleaseToOsIntervalMs = 1000;
185  };
186#if SCUDO_CAN_USE_PRIMARY64
187  template <typename Config> using PrimaryT = SizeClassAllocator64<Config>;
188#else
189  template <typename Config> using PrimaryT = SizeClassAllocator32<Config>;
190#endif
191
192  struct Secondary {
193    struct Cache {
194      static const u32 EntriesArraySize = 256U;
195      static const u32 QuarantineSize = 32U;
196      static const u32 DefaultMaxEntriesCount = 32U;
197      static const uptr DefaultMaxEntrySize = 2UL << 20;
198      static const s32 MinReleaseToOsIntervalMs = 0;
199      static const s32 MaxReleaseToOsIntervalMs = 1000;
200    };
201    template <typename Config> using CacheT = MapAllocatorCache<Config>;
202  };
203
204  template <typename Config> using SecondaryT = MapAllocator<Config>;
205};
206
207#if SCUDO_CAN_USE_PRIMARY64
208struct FuchsiaConfig {
209  static const bool MaySupportMemoryTagging = false;
210  template <class A>
211  using TSDRegistryT = TSDRegistrySharedT<A, 8U, 4U>; // Shared, max 8 TSDs.
212
213  struct Primary {
214    using SizeClassMap = FuchsiaSizeClassMap;
215#if SCUDO_RISCV64
216    // Support 39-bit VMA for riscv-64
217    static const uptr RegionSizeLog = 28U;
218    static const uptr GroupSizeLog = 19U;
219#else
220    static const uptr RegionSizeLog = 30U;
221    static const uptr GroupSizeLog = 21U;
222#endif
223    typedef u32 CompactPtrT;
224    static const bool EnableRandomOffset = true;
225    static const uptr MapSizeIncrement = 1UL << 18;
226    static const uptr CompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
227    static const s32 MinReleaseToOsIntervalMs = INT32_MIN;
228    static const s32 MaxReleaseToOsIntervalMs = INT32_MAX;
229  };
230  template <typename Config> using PrimaryT = SizeClassAllocator64<Config>;
231
232  struct Secondary {
233    template <typename Config> using CacheT = MapAllocatorNoCache<Config>;
234  };
235  template <typename Config> using SecondaryT = MapAllocator<Config>;
236};
237
238struct TrustyConfig {
239  static const bool MaySupportMemoryTagging = true;
240  template <class A>
241  using TSDRegistryT = TSDRegistrySharedT<A, 1U, 1U>; // Shared, max 1 TSD.
242
243  struct Primary {
244    using SizeClassMap = TrustySizeClassMap;
245    static const uptr RegionSizeLog = 28U;
246    static const uptr GroupSizeLog = 20U;
247    typedef u32 CompactPtrT;
248    static const bool EnableRandomOffset = false;
249    static const uptr MapSizeIncrement = 1UL << 12;
250    static const uptr CompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
251    static const s32 MinReleaseToOsIntervalMs = INT32_MIN;
252    static const s32 MaxReleaseToOsIntervalMs = INT32_MAX;
253  };
254  template <typename Config> using PrimaryT = SizeClassAllocator64<Config>;
255
256  struct Secondary {
257    template <typename Config> using CacheT = MapAllocatorNoCache<Config>;
258  };
259
260  template <typename Config> using SecondaryT = MapAllocator<Config>;
261};
262#endif
263
264#ifndef SCUDO_USE_CUSTOM_CONFIG
265
266#if SCUDO_ANDROID
267typedef AndroidConfig Config;
268#elif SCUDO_FUCHSIA
269typedef FuchsiaConfig Config;
270#elif SCUDO_TRUSTY
271typedef TrustyConfig Config;
272#else
273typedef DefaultConfig Config;
274#endif
275
276#endif // SCUDO_USE_CUSTOM_CONFIG
277
278} // namespace scudo
279
280#endif // SCUDO_ALLOCATOR_CONFIG_H_
281