Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable client meta-data #662

Merged
merged 26 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions src/snmalloc/backend/fixedglobalconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace snmalloc
{
public:
using PagemapEntry = DefaultPagemapEntry<ClientMetaDataProvider>;
using ClientMeta = ClientMetaDataProvider;

private:
using ConcretePagemap =
Expand Down
1 change: 1 addition & 0 deletions src/snmalloc/backend/globalconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace snmalloc
public:
using Pal = DefaultPal;
using PagemapEntry = DefaultPagemapEntry<ClientMetaDataProvider>;
using ClientMeta = ClientMetaDataProvider;

private:
using ConcretePagemap =
Expand Down
8 changes: 6 additions & 2 deletions src/snmalloc/backend_helpers/commonconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,14 @@ namespace snmalloc
struct NoClientMetaDataProvider
{
using StorageType = Empty;
using DataRef = Empty&;
using ConstDataRef = const Empty&;
nwf-msr marked this conversation as resolved.
Show resolved Hide resolved

static size_t required_count(size_t) {
return 1;
}

static Empty& get(Empty* base, size_t) {
static DataRef get(StorageType* base, size_t) {
return *base;
}
};
Expand All @@ -112,12 +114,14 @@ namespace snmalloc
struct ArrayClientMetaDataProvider
{
using StorageType = T;
using DataRef = T&;
using ConstDataRef = const T&;

static size_t required_count(size_t max_count) {
return max_count;
}

static T& get(StorageType* base, size_t index) {
static DataRef get(StorageType* base, size_t index) {
return base[index];
}
};
Expand Down
13 changes: 13 additions & 0 deletions src/snmalloc/global/libc.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,17 @@ namespace snmalloc::libc
*memptr = p;
return 0;
}

inline typename snmalloc::Alloc::Config::ClientMeta::DataRef
get_client_meta_data(void* p)
{
return ThreadAlloc::get().get_client_meta_data(p);
}

inline typename snmalloc::Alloc::Config::ClientMeta::ConstDataRef
get_client_meta_data_const(void* p)
{
return ThreadAlloc::get().get_client_meta_data_const(p);
}

} // namespace snmalloc::libc
1 change: 0 additions & 1 deletion src/snmalloc/mem/corealloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,6 @@ namespace snmalloc

// Calculate the extra bytes required to store the client meta-data.
size_t extra_bytes = BackendSlabMetadata::get_extra_bytes(sizeclass);
mjp41 marked this conversation as resolved.
Show resolved Hide resolved
message<1024>("extra_bytes={}, sizeclass={}", extra_bytes, sizeclass);

auto [slab, meta] = Config::Backend::alloc_chunk(
get_backend_local_state(),
Expand Down
43 changes: 43 additions & 0 deletions src/snmalloc/mem/localalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,49 @@ namespace snmalloc
}
}

/**
* @brief Get the client meta data for the snmalloc allocation covering this pointer.
*
*/
typename Config::ClientMeta::DataRef get_client_meta_data(void* p)
{
const PagemapEntry& entry = Config::Backend::template get_metaentry(address_cast(p));

size_t index = slab_index(entry.get_sizeclass(), address_cast(p));

auto* meta_slab = entry.get_slab_metadata();

if (SNMALLOC_UNLIKELY(meta_slab == nullptr))
{
// TODO handle const case, where we read fake meta-data.
abort();
}

return meta_slab->get_meta_for_object(index);
}

/**
* @brief Get the client meta data for the snmalloc allocation covering this pointer.
*
*/
typename Config::ClientMeta::ConstDataRef get_client_meta_data_const(void* p)
{
const PagemapEntry& entry = Config::Backend::template get_metaentry(address_cast(p));

size_t index = slab_index(entry.get_sizeclass(), address_cast(p));

auto* meta_slab = entry.get_slab_metadata();

if (SNMALLOC_UNLIKELY(meta_slab == nullptr))
{
static typename Config::ClientMeta::StorageType null_meta_store{};
return Config::ClientMeta::get(&null_meta_store, 0);
}

return meta_slab->get_meta_for_object(index);
}


/**
* Returns the number of remaining bytes in an object.
*
Expand Down
8 changes: 4 additions & 4 deletions src/snmalloc/mem/metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ namespace snmalloc
friend class FrontendSlabMetadata;

// Can only be constructed by FrontendSlabMetadata
FrontendSlabMetadata_Trait() = default;
constexpr FrontendSlabMetadata_Trait() = default;
};

/**
Expand Down Expand Up @@ -434,7 +434,7 @@ namespace snmalloc
* slab. The meta data will actually allocate multiple elements after this
* type, so that client_meta_[1] will work for the required meta-data size.
*/
SNMALLOC_NO_UNIQUE_ADDRESS typename ClientMeta::StorageType client_meta_;
SNMALLOC_NO_UNIQUE_ADDRESS typename ClientMeta::StorageType client_meta_{};

uint16_t& needed()
{
Expand Down Expand Up @@ -601,9 +601,9 @@ namespace snmalloc
return address_cast(free_queue.read_head(0, key));
}

typename ClientMeta::StorageType* get_client_meta_base()
typename ClientMeta::DataRef get_meta_for_object(size_t index)
{
return &client_meta_;
return ClientMeta::get(&client_meta_, index);
}

static size_t get_client_storage_count(smallsizeclass_t sizeclass)
Expand Down
22 changes: 14 additions & 8 deletions src/snmalloc/mem/sizeclasstable.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,11 @@ namespace snmalloc
.capacity;
}

constexpr address_t start_of_object(sizeclass_t sc, address_t addr)
SNMALLOC_FAST_PATH constexpr size_t slab_index(sizeclass_t sc, address_t addr)
{
auto meta = sizeclass_metadata.fast(sc);
address_t slab_start = addr & ~meta.slab_mask;
size_t offset = addr & meta.slab_mask;
size_t size = meta.size;

if constexpr (sizeof(addr) >= 8)
if constexpr (sizeof(offset) >= 8)
{
// Only works for 64 bit multiplication, as the following will overflow in
// 32bit.
Expand All @@ -351,17 +348,26 @@ namespace snmalloc
// the slab_mask by making the `div_mult` zero. The link uses 128 bit
// multiplication, we have shrunk the range of the calculation to remove
// this dependency.
size_t offset_start = ((offset * meta.div_mult) >> DIV_MULT_SHIFT) * size;
return slab_start + offset_start;
size_t index = ((offset * meta.div_mult) >> DIV_MULT_SHIFT);
return index;
}
else
{
size_t size = meta.size;
if (size == 0)
return 0;
return slab_start + (offset / size) * size;
return offset / size;
}
}

SNMALLOC_FAST_PATH constexpr address_t start_of_object(sizeclass_t sc, address_t addr)
{
auto meta = sizeclass_metadata.fast(sc);
address_t slab_start = addr & ~meta.slab_mask;
size_t index = slab_index(sc, addr);
return slab_start + (index * meta.size);
}

constexpr size_t index_in_object(sizeclass_t sc, address_t addr)
{
return addr - start_of_object(sc, addr);
Expand Down
1 change: 0 additions & 1 deletion src/snmalloc/pal/pal_posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/mman.h>
Expand Down
1 change: 1 addition & 0 deletions src/test/func/domestication/domestication.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace snmalloc
public:
using Pal = DefaultPal;
using PagemapEntry = DefaultPagemapEntry<NoClientMetaDataProvider>;
using ClientMeta = NoClientMetaDataProvider;

private:
using ConcretePagemap =
Expand Down