* Make a conditional range

This range allows for a contained range to be disabled at runtime.
This allows for thread local caching to be disabled if the initial fixed
size heap is below a threshold.
This commit is contained in:
Matthew Parkinson 2023-06-20 12:00:34 -04:00 коммит произвёл GitHub
Родитель d9f5bd0500
Коммит ce489cfffe
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 99 добавлений и 2 удалений

Просмотреть файл

@ -87,6 +87,12 @@ namespace snmalloc
auto [heap_base, heap_length] = auto [heap_base, heap_length] =
Pagemap::concretePagemap.init(base, length); Pagemap::concretePagemap.init(base, length);
// Make this a alloc_config constant.
if (length < MIN_HEAP_SIZE_FOR_THREAD_LOCAL_BUDDY)
{
LocalState::set_small_heap();
}
Authmap::arena = capptr::Arena<void>::unsafe_from(heap_base); Authmap::arena = capptr::Arena<void>::unsafe_from(heap_base);
Pagemap::register_range(Authmap::arena, heap_length); Pagemap::register_range(Authmap::arena, heap_length);

Просмотреть файл

@ -49,11 +49,11 @@ namespace snmalloc
// Use buddy allocators to cache locally. // Use buddy allocators to cache locally.
using LargeObjectRange = Pipe< using LargeObjectRange = Pipe<
Stats, Stats,
LargeBuddyRange< StaticConditionalRange<LargeBuddyRange<
LocalCacheSizeBits, LocalCacheSizeBits,
LocalCacheSizeBits, LocalCacheSizeBits,
Pagemap, Pagemap,
page_size_bits>>; page_size_bits>>>;
private: private:
using ObjectRange = Pipe<LargeObjectRange, SmallBuddyRange>; using ObjectRange = Pipe<LargeObjectRange, SmallBuddyRange>;
@ -85,5 +85,11 @@ namespace snmalloc
// Use the object range to service meta-data requests. // Use the object range to service meta-data requests.
return object_range; return object_range;
} }
static void set_small_heap()
{
// This disables the thread local caching of large objects.
LargeObjectRange::disable_range();
}
}; };
} // namespace snmalloc } // namespace snmalloc

Просмотреть файл

@ -14,5 +14,6 @@
#include "palrange.h" #include "palrange.h"
#include "range_helpers.h" #include "range_helpers.h"
#include "smallbuddyrange.h" #include "smallbuddyrange.h"
#include "staticconditionalrange.h"
#include "statsrange.h" #include "statsrange.h"
#include "subrange.h" #include "subrange.h"

Просмотреть файл

@ -0,0 +1,78 @@
#pragma once
#include "../pal/pal.h"
#include "empty_range.h"
#include "range_helpers.h"
namespace snmalloc
{
template<typename OptionalRange>
struct StaticConditionalRange
{
// This is a range that can bypass the OptionalRange if it is disabled.
// Disabling is global, and not local.
// This is used to allow disabling thread local buddy allocators when the
// initial fixed size heap is small.
//
// The range builds a more complex parent
// Pipe<ParentRange, OptionalRange>
// and uses the ancestor functions to bypass the OptionalRange if the flag
// has been set.
template<typename ParentRange>
class Type : public ContainsParent<Pipe<ParentRange, OptionalRange>>
{
// This contains connects the optional range to the parent range.
using ActualParentRange = Pipe<ParentRange, OptionalRange>;
using ContainsParent<ActualParentRange>::parent;
// Global flag specifying if the optional range should be disabled.
static inline bool disable_range_{false};
public:
// Both parent and grandparent must be aligned for this range to be
// aligned.
static constexpr bool Aligned =
ActualParentRange::Aligned && ParentRange::Aligned;
// Both parent and grandparent must be aligned for this range to be
// concurrency safe.
static constexpr bool ConcurrencySafe =
ActualParentRange::ConcurrencySafe && ParentRange::ConcurrencySafe;
using ChunkBounds = typename ActualParentRange::ChunkBounds;
static_assert(
std::is_same_v<ChunkBounds, typename ParentRange::ChunkBounds>,
"Grandparent and optional parent range chunk bounds must be equal");
constexpr Type() = default;
CapPtr<void, ChunkBounds> alloc_range(size_t size)
{
if (disable_range_)
{
// Use ancestor to bypass the optional range.
return this->template ancestor<ParentRange>()->alloc_range(size);
}
return parent.alloc_range(size);
}
void dealloc_range(CapPtr<void, ChunkBounds> base, size_t size)
{
if (disable_range_)
{
// Use ancestor to bypass the optional range.
this->template ancestor<ParentRange>()->dealloc_range(base, size);
return;
}
parent.dealloc_range(base, size);
}
static void disable_range()
{
disable_range_ = true;
}
};
};
} // namespace snmalloc

Просмотреть файл

@ -92,4 +92,10 @@ namespace snmalloc
1 << MIN_CHUNK_BITS 1 << MIN_CHUNK_BITS
#endif #endif
; ;
// Used to configure when the backend should use thread local buddies.
// This only basically is used to disable some buddy allocators on small
// fixed heap scenarios like OpenEnclave.
static constexpr size_t MIN_HEAP_SIZE_FOR_THREAD_LOCAL_BUDDY =
bits::one_at_bit(27);
} // namespace snmalloc } // namespace snmalloc