Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/snmalloc/backend/fixedglobalconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ namespace snmalloc
auto [heap_base, heap_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);

Pagemap::register_range(Authmap::arena, heap_length);
Expand Down
10 changes: 8 additions & 2 deletions src/snmalloc/backend/standard_range.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ namespace snmalloc
// Use buddy allocators to cache locally.
using LargeObjectRange = Pipe<
Stats,
LargeBuddyRange<
StaticConditionalRange<LargeBuddyRange<
LocalCacheSizeBits,
LocalCacheSizeBits,
Pagemap,
page_size_bits>>;
page_size_bits>>>;

private:
using ObjectRange = Pipe<LargeObjectRange, SmallBuddyRange>;
Expand Down Expand Up @@ -85,5 +85,11 @@ namespace snmalloc
// Use the object range to service meta-data requests.
return object_range;
}

static void set_small_heap()
{
// This disables the thread local caching of large objects.
LargeObjectRange::disable_range();
}
};
} // namespace snmalloc
1 change: 1 addition & 0 deletions src/snmalloc/backend_helpers/backend_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
#include "palrange.h"
#include "range_helpers.h"
#include "smallbuddyrange.h"
#include "staticconditionalrange.h"
#include "statsrange.h"
#include "subrange.h"
78 changes: 78 additions & 0 deletions src/snmalloc/backend_helpers/staticconditionalrange.h
Original file line number Diff line number Diff line change
@@ -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>>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've nothing to add here except to quote Hackers:

It's so neat and clean.
Doesn't look like a hacker wrote it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I need to watch "Hackers" ;)

{
// 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
6 changes: 6 additions & 0 deletions src/snmalloc/ds/allocconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,10 @@ namespace snmalloc
1 << MIN_CHUNK_BITS
#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