1*76559068SAndroid Build Coastguard Worker //===-- allocator_config_wrapper.h ------------------------------*- C++ -*-===// 2*76559068SAndroid Build Coastguard Worker // 3*76559068SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*76559068SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information. 5*76559068SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*76559068SAndroid Build Coastguard Worker // 7*76559068SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 8*76559068SAndroid Build Coastguard Worker 9*76559068SAndroid Build Coastguard Worker #ifndef SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_ 10*76559068SAndroid Build Coastguard Worker #define SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_ 11*76559068SAndroid Build Coastguard Worker 12*76559068SAndroid Build Coastguard Worker #include "condition_variable.h" 13*76559068SAndroid Build Coastguard Worker #include "internal_defs.h" 14*76559068SAndroid Build Coastguard Worker #include "secondary.h" 15*76559068SAndroid Build Coastguard Worker 16*76559068SAndroid Build Coastguard Worker namespace { 17*76559068SAndroid Build Coastguard Worker 18*76559068SAndroid Build Coastguard Worker template <typename T> struct removeConst { 19*76559068SAndroid Build Coastguard Worker using type = T; 20*76559068SAndroid Build Coastguard Worker }; 21*76559068SAndroid Build Coastguard Worker template <typename T> struct removeConst<const T> { 22*76559068SAndroid Build Coastguard Worker using type = T; 23*76559068SAndroid Build Coastguard Worker }; 24*76559068SAndroid Build Coastguard Worker 25*76559068SAndroid Build Coastguard Worker // This is only used for SFINAE when detecting if a type is defined. 26*76559068SAndroid Build Coastguard Worker template <typename T> struct voidAdaptor { 27*76559068SAndroid Build Coastguard Worker using type = void; 28*76559068SAndroid Build Coastguard Worker }; 29*76559068SAndroid Build Coastguard Worker 30*76559068SAndroid Build Coastguard Worker // This is used for detecting the case that defines the flag with wrong type and 31*76559068SAndroid Build Coastguard Worker // it'll be viewed as undefined optional flag. 32*76559068SAndroid Build Coastguard Worker template <typename L, typename R> struct assertSameType { 33*76559068SAndroid Build Coastguard Worker template <typename, typename> struct isSame { 34*76559068SAndroid Build Coastguard Worker static constexpr bool value = false; 35*76559068SAndroid Build Coastguard Worker }; 36*76559068SAndroid Build Coastguard Worker template <typename T> struct isSame<T, T> { 37*76559068SAndroid Build Coastguard Worker static constexpr bool value = true; 38*76559068SAndroid Build Coastguard Worker }; 39*76559068SAndroid Build Coastguard Worker static_assert(isSame<L, R>::value, "Flag type mismatches"); 40*76559068SAndroid Build Coastguard Worker using type = R; 41*76559068SAndroid Build Coastguard Worker }; 42*76559068SAndroid Build Coastguard Worker 43*76559068SAndroid Build Coastguard Worker } // namespace 44*76559068SAndroid Build Coastguard Worker 45*76559068SAndroid Build Coastguard Worker namespace scudo { 46*76559068SAndroid Build Coastguard Worker 47*76559068SAndroid Build Coastguard Worker #define OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, MEMBER) \ 48*76559068SAndroid Build Coastguard Worker template <typename Config, typename = TYPE> struct NAME##State { \ 49*76559068SAndroid Build Coastguard Worker static constexpr removeConst<TYPE>::type getValue() { return DEFAULT; } \ 50*76559068SAndroid Build Coastguard Worker }; \ 51*76559068SAndroid Build Coastguard Worker template <typename Config> \ 52*76559068SAndroid Build Coastguard Worker struct NAME##State< \ 53*76559068SAndroid Build Coastguard Worker Config, typename assertSameType<decltype(Config::MEMBER), TYPE>::type> { \ 54*76559068SAndroid Build Coastguard Worker static constexpr removeConst<TYPE>::type getValue() { \ 55*76559068SAndroid Build Coastguard Worker return Config::MEMBER; \ 56*76559068SAndroid Build Coastguard Worker } \ 57*76559068SAndroid Build Coastguard Worker }; 58*76559068SAndroid Build Coastguard Worker 59*76559068SAndroid Build Coastguard Worker #define OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, MEMBER) \ 60*76559068SAndroid Build Coastguard Worker template <typename Config, typename Void = void> struct NAME##Type { \ 61*76559068SAndroid Build Coastguard Worker static constexpr bool enabled() { return false; } \ 62*76559068SAndroid Build Coastguard Worker using NAME = DEFAULT; \ 63*76559068SAndroid Build Coastguard Worker }; \ 64*76559068SAndroid Build Coastguard Worker template <typename Config> \ 65*76559068SAndroid Build Coastguard Worker struct NAME##Type<Config, \ 66*76559068SAndroid Build Coastguard Worker typename voidAdaptor<typename Config::MEMBER>::type> { \ 67*76559068SAndroid Build Coastguard Worker static constexpr bool enabled() { return true; } \ 68*76559068SAndroid Build Coastguard Worker using NAME = typename Config::MEMBER; \ 69*76559068SAndroid Build Coastguard Worker }; 70*76559068SAndroid Build Coastguard Worker 71*76559068SAndroid Build Coastguard Worker template <typename AllocatorConfig> struct BaseConfig { 72*76559068SAndroid Build Coastguard Worker #define BASE_REQUIRED_TEMPLATE_TYPE(NAME) \ 73*76559068SAndroid Build Coastguard Worker template <typename T> using NAME = typename AllocatorConfig::template NAME<T>; 74*76559068SAndroid Build Coastguard Worker 75*76559068SAndroid Build Coastguard Worker #define BASE_OPTIONAL(TYPE, NAME, DEFAULT) \ 76*76559068SAndroid Build Coastguard Worker OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \ 77*76559068SAndroid Build Coastguard Worker static constexpr removeConst<TYPE>::type get##NAME() { \ 78*76559068SAndroid Build Coastguard Worker return NAME##State<AllocatorConfig>::getValue(); \ 79*76559068SAndroid Build Coastguard Worker } 80*76559068SAndroid Build Coastguard Worker 81*76559068SAndroid Build Coastguard Worker #include "allocator_config.def" 82*76559068SAndroid Build Coastguard Worker }; // BaseConfig 83*76559068SAndroid Build Coastguard Worker 84*76559068SAndroid Build Coastguard Worker template <typename AllocatorConfig> struct PrimaryConfig { 85*76559068SAndroid Build Coastguard Worker // TODO: Pass this flag through template argument to remove this hard-coded 86*76559068SAndroid Build Coastguard Worker // function. 87*76559068SAndroid Build Coastguard Worker static constexpr bool getMaySupportMemoryTagging() { 88*76559068SAndroid Build Coastguard Worker return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging(); 89*76559068SAndroid Build Coastguard Worker } 90*76559068SAndroid Build Coastguard Worker 91*76559068SAndroid Build Coastguard Worker #define PRIMARY_REQUIRED_TYPE(NAME) \ 92*76559068SAndroid Build Coastguard Worker using NAME = typename AllocatorConfig::Primary::NAME; 93*76559068SAndroid Build Coastguard Worker 94*76559068SAndroid Build Coastguard Worker #define PRIMARY_REQUIRED(TYPE, NAME) \ 95*76559068SAndroid Build Coastguard Worker static constexpr removeConst<TYPE>::type get##NAME() { \ 96*76559068SAndroid Build Coastguard Worker return AllocatorConfig::Primary::NAME; \ 97*76559068SAndroid Build Coastguard Worker } 98*76559068SAndroid Build Coastguard Worker 99*76559068SAndroid Build Coastguard Worker #define PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT) \ 100*76559068SAndroid Build Coastguard Worker OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \ 101*76559068SAndroid Build Coastguard Worker static constexpr removeConst<TYPE>::type get##NAME() { \ 102*76559068SAndroid Build Coastguard Worker return NAME##State<typename AllocatorConfig::Primary>::getValue(); \ 103*76559068SAndroid Build Coastguard Worker } 104*76559068SAndroid Build Coastguard Worker 105*76559068SAndroid Build Coastguard Worker #define PRIMARY_OPTIONAL_TYPE(NAME, DEFAULT) \ 106*76559068SAndroid Build Coastguard Worker OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, NAME) \ 107*76559068SAndroid Build Coastguard Worker static constexpr bool has##NAME() { \ 108*76559068SAndroid Build Coastguard Worker return NAME##Type<typename AllocatorConfig::Primary>::enabled(); \ 109*76559068SAndroid Build Coastguard Worker } \ 110*76559068SAndroid Build Coastguard Worker using NAME = typename NAME##Type<typename AllocatorConfig::Primary>::NAME; 111*76559068SAndroid Build Coastguard Worker 112*76559068SAndroid Build Coastguard Worker #include "allocator_config.def" 113*76559068SAndroid Build Coastguard Worker 114*76559068SAndroid Build Coastguard Worker }; // PrimaryConfig 115*76559068SAndroid Build Coastguard Worker 116*76559068SAndroid Build Coastguard Worker template <typename AllocatorConfig> struct SecondaryConfig { 117*76559068SAndroid Build Coastguard Worker // TODO: Pass this flag through template argument to remove this hard-coded 118*76559068SAndroid Build Coastguard Worker // function. 119*76559068SAndroid Build Coastguard Worker static constexpr bool getMaySupportMemoryTagging() { 120*76559068SAndroid Build Coastguard Worker return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging(); 121*76559068SAndroid Build Coastguard Worker } 122*76559068SAndroid Build Coastguard Worker 123*76559068SAndroid Build Coastguard Worker #define SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME) \ 124*76559068SAndroid Build Coastguard Worker template <typename T> \ 125*76559068SAndroid Build Coastguard Worker using NAME = typename AllocatorConfig::Secondary::template NAME<T>; 126*76559068SAndroid Build Coastguard Worker #include "allocator_config.def" 127*76559068SAndroid Build Coastguard Worker 128*76559068SAndroid Build Coastguard Worker struct CacheConfig { 129*76559068SAndroid Build Coastguard Worker // TODO: Pass this flag through template argument to remove this hard-coded 130*76559068SAndroid Build Coastguard Worker // function. 131*76559068SAndroid Build Coastguard Worker static constexpr bool getMaySupportMemoryTagging() { 132*76559068SAndroid Build Coastguard Worker return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging(); 133*76559068SAndroid Build Coastguard Worker } 134*76559068SAndroid Build Coastguard Worker 135*76559068SAndroid Build Coastguard Worker #define SECONDARY_CACHE_OPTIONAL(TYPE, NAME, DEFAULT) \ 136*76559068SAndroid Build Coastguard Worker OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, Cache::NAME) \ 137*76559068SAndroid Build Coastguard Worker static constexpr removeConst<TYPE>::type get##NAME() { \ 138*76559068SAndroid Build Coastguard Worker return NAME##State<typename AllocatorConfig::Secondary>::getValue(); \ 139*76559068SAndroid Build Coastguard Worker } 140*76559068SAndroid Build Coastguard Worker #include "allocator_config.def" 141*76559068SAndroid Build Coastguard Worker }; // CacheConfig 142*76559068SAndroid Build Coastguard Worker }; // SecondaryConfig 143*76559068SAndroid Build Coastguard Worker 144*76559068SAndroid Build Coastguard Worker #undef OPTIONAL_TEMPLATE 145*76559068SAndroid Build Coastguard Worker #undef OPTIONAL_TEMPLATE_TYPE 146*76559068SAndroid Build Coastguard Worker 147*76559068SAndroid Build Coastguard Worker } // namespace scudo 148*76559068SAndroid Build Coastguard Worker 149*76559068SAndroid Build Coastguard Worker #endif // SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_ 150