1//===-- allocator_config_wrapper.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_WRAPPER_H_
10#define SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_
11
12#include "condition_variable.h"
13#include "internal_defs.h"
14#include "secondary.h"
15#include "type_traits.h"
16
17namespace scudo {
18
19#define OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, MEMBER) \
20 template <typename Config, typename = TYPE> struct NAME##State { \
21 static constexpr removeConst<TYPE>::type getValue() { return DEFAULT; } \
22 }; \
23 template <typename Config> \
24 struct NAME##State< \
25 Config, typename assertSameType<decltype(Config::MEMBER), TYPE>::type> { \
26 static constexpr removeConst<TYPE>::type getValue() { \
27 return Config::MEMBER; \
28 } \
29 };
30
31#define OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, MEMBER) \
32 template <typename Config, typename Void = void> struct NAME##Type { \
33 static constexpr bool enabled() { return false; } \
34 using NAME = DEFAULT; \
35 }; \
36 template <typename Config> \
37 struct NAME##Type<Config, \
38 typename voidAdaptor<typename Config::MEMBER>::type> { \
39 static constexpr bool enabled() { return true; } \
40 using NAME = typename Config::MEMBER; \
41 };
42
43template <typename AllocatorConfig> struct BaseConfig {
44#define BASE_REQUIRED_TEMPLATE_TYPE(NAME) \
45 template <typename T> using NAME = typename AllocatorConfig::template NAME<T>;
46
47#define BASE_OPTIONAL(TYPE, NAME, DEFAULT) \
48 OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \
49 static constexpr removeConst<TYPE>::type get##NAME() { \
50 return NAME##State<AllocatorConfig>::getValue(); \
51 }
52
53#include "allocator_config.def"
54
55 static void getConfigValues(ScopedString *Str) {
56#define BASE_OPTIONAL(TYPE, NAME, DEFAULT) \
57 Str->append(#NAME); \
58 Str->append(": "); \
59 Str->append(get##NAME()); \
60 Str->append("; ");
61#include "allocator_config.def"
62 }
63
64}; // BaseConfig
65
66template <typename AllocatorConfig> struct PrimaryConfig {
67 // TODO: Pass this flag through template argument to remove this hard-coded
68 // function.
69 static constexpr bool getMaySupportMemoryTagging() {
70 return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
71 }
72
73 static constexpr bool getQuarantineDisabled() {
74 return BaseConfig<AllocatorConfig>::getQuarantineDisabled();
75 }
76
77#define PRIMARY_REQUIRED_TYPE(NAME) \
78 using NAME = typename AllocatorConfig::Primary::NAME;
79
80#define PRIMARY_REQUIRED(TYPE, NAME) \
81 static constexpr removeConst<TYPE>::type get##NAME() { \
82 return AllocatorConfig::Primary::NAME; \
83 }
84
85#define PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT) \
86 OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \
87 static constexpr removeConst<TYPE>::type get##NAME() { \
88 return NAME##State<typename AllocatorConfig::Primary>::getValue(); \
89 }
90
91#define PRIMARY_OPTIONAL_TYPE(NAME, DEFAULT) \
92 OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, NAME) \
93 static constexpr bool has##NAME() { \
94 return NAME##Type<typename AllocatorConfig::Primary>::enabled(); \
95 } \
96 using NAME = typename NAME##Type<typename AllocatorConfig::Primary>::NAME;
97
98#include "allocator_config.def"
99
100 static void getConfigValues(ScopedString *Str) {
101#define PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT) \
102 Str->append(#NAME); \
103 Str->append(": "); \
104 Str->append(get##NAME()); \
105 Str->append("; ");
106#include "allocator_config.def"
107 }
108
109}; // PrimaryConfig
110
111template <typename AllocatorConfig> struct SecondaryConfig {
112 // TODO: Pass this flag through template argument to remove this hard-coded
113 // function.
114 static constexpr bool getMaySupportMemoryTagging() {
115 return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
116 }
117
118 static constexpr bool getQuarantineDisabled() {
119 return BaseConfig<AllocatorConfig>::getQuarantineDisabled();
120 }
121
122#define SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME) \
123 template <typename T> \
124 using NAME = typename AllocatorConfig::Secondary::template NAME<T>;
125
126#define SECONDARY_OPTIONAL(TYPE, NAME, DEFAULT) \
127 OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \
128 static constexpr removeConst<TYPE>::type get##NAME() { \
129 return NAME##State<typename AllocatorConfig::Secondary>::getValue(); \
130 }
131
132#include "allocator_config.def"
133
134 struct CacheConfig {
135 // TODO: Pass this flag through template argument to remove this hard-coded
136 // function.
137 static constexpr bool getMaySupportMemoryTagging() {
138 return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging();
139 }
140
141 static constexpr bool getQuarantineDisabled() {
142 return BaseConfig<AllocatorConfig>::getQuarantineDisabled();
143 }
144
145#define SECONDARY_CACHE_OPTIONAL(TYPE, NAME, DEFAULT) \
146 OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, Cache::NAME) \
147 static constexpr removeConst<TYPE>::type get##NAME() { \
148 return NAME##State<typename AllocatorConfig::Secondary>::getValue(); \
149 }
150#include "allocator_config.def"
151
152 static void getConfigValues(ScopedString *Str) {
153#define SECONDARY_CACHE_OPTIONAL(TYPE, NAME, DEFAULT) \
154 Str->append(#NAME); \
155 Str->append(": "); \
156 Str->append(get##NAME()); \
157 Str->append("; ");
158#include "allocator_config.def"
159 }
160
161 }; // CacheConfig
162
163 static void getConfigValues(ScopedString *Str) {
164#define SECONDARY_OPTIONAL(TYPE, NAME, DEFAULT) \
165 Str->append(#NAME); \
166 Str->append(": "); \
167 Str->append(get##NAME()); \
168 Str->append("; ");
169#include "allocator_config.def"
170 Str->append(Format: "\nConfig Stats Secondary Cache: ");
171 CacheConfig::getConfigValues(Str);
172 }
173}; // SecondaryConfig
174
175#undef OPTIONAL_TEMPLATE
176#undef OPTIONAL_TEMPLATE_TYPE
177
178} // namespace scudo
179
180#endif // SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_
181