This is the set of changes required for snmalloc2 to be usable by the process sandboxing code and incorporates some API changes that reduce the amount of code required to embed snmalloc. Highlights: - Merge the config and back-end classes. - Everything in config is now global (all methods are static) - The GlobalState class is gone (all global state is managed by global methods on the config class) - LocalState is now a member of the config class, all methods are instance methods. - Not every configuration needs to use the lazy initialisation hooks. They now need to be provided only if they are used. If the configuration does not provide an `ensure_init` method, it is not called. If it does not provide an `is_initialised` method then the global initialisation state is not checked. - There is now an `snmalloc::Options` class that default initialises itself to the default behaviour. Every configuration must provide a `constexpr` instance of this class. Each flag can be separately overridden and new flags can be added without breaking any existing API consumers. The config classes are moved into the backend directory.
104 lines
2.4 KiB
C++
104 lines
2.4 KiB
C++
#pragma once
|
|
|
|
#include "../backend/backend.h"
|
|
#include "../mem/corealloc.h"
|
|
#include "../mem/pool.h"
|
|
#include "../mem/slaballocator.h"
|
|
#include "commonconfig.h"
|
|
|
|
#include <iostream>
|
|
|
|
namespace snmalloc
|
|
{
|
|
// Forward reference to thread local cleanup.
|
|
void register_clean_up();
|
|
|
|
#ifdef USE_SNMALLOC_STATS
|
|
inline static void print_stats()
|
|
{
|
|
printf("No Stats yet!");
|
|
// Stats s;
|
|
// current_alloc_pool()->aggregate_stats(s);
|
|
// s.print<Alloc>(std::cout);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* The default configuration for a global snmalloc. This allocates memory
|
|
* from the operating system and expects to manage memory anywhere in the
|
|
* address space.
|
|
*/
|
|
class Globals final : public BackendAllocator<Pal, false>
|
|
{
|
|
private:
|
|
using Backend = BackendAllocator<Pal, false>;
|
|
SNMALLOC_REQUIRE_CONSTINIT
|
|
inline static ChunkAllocatorState slab_allocator_state;
|
|
|
|
SNMALLOC_REQUIRE_CONSTINIT
|
|
inline static PoolState<CoreAllocator<Globals>> alloc_pool;
|
|
|
|
SNMALLOC_REQUIRE_CONSTINIT
|
|
inline static std::atomic<bool> initialised{false};
|
|
|
|
SNMALLOC_REQUIRE_CONSTINIT
|
|
inline static std::atomic_flag initialisation_lock{};
|
|
|
|
public:
|
|
static ChunkAllocatorState&
|
|
get_slab_allocator_state(Backend::LocalState* = nullptr)
|
|
{
|
|
return slab_allocator_state;
|
|
}
|
|
|
|
static PoolState<CoreAllocator<Globals>>& pool()
|
|
{
|
|
return alloc_pool;
|
|
}
|
|
|
|
static constexpr Flags Options{};
|
|
|
|
// Performs initialisation for this configuration
|
|
// of allocators. Needs to be idempotent,
|
|
// and concurrency safe.
|
|
static void ensure_init()
|
|
{
|
|
FlagLock lock{initialisation_lock};
|
|
#ifdef SNMALLOC_TRACING
|
|
std::cout << "Run init_impl" << std::endl;
|
|
#endif
|
|
|
|
if (initialised)
|
|
return;
|
|
|
|
LocalEntropy entropy;
|
|
entropy.init<Pal>();
|
|
// Initialise key for remote deallocation lists
|
|
key_global = FreeListKey(entropy.get_free_list_key());
|
|
|
|
// Need to initialise pagemap.
|
|
Backend::init();
|
|
|
|
#ifdef USE_SNMALLOC_STATS
|
|
atexit(snmalloc::print_stats);
|
|
#endif
|
|
|
|
initialised = true;
|
|
}
|
|
|
|
static bool is_initialised()
|
|
{
|
|
return initialised;
|
|
}
|
|
|
|
// This needs to be a forward reference as the
|
|
// thread local state will need to know about this.
|
|
// This may allocate, so should only be called once
|
|
// a thread local allocator is available.
|
|
static void register_clean_up()
|
|
{
|
|
snmalloc::register_clean_up();
|
|
}
|
|
};
|
|
} // namespace snmalloc
|