Skip to content
Draft
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
25 changes: 8 additions & 17 deletions src/snmalloc/backend_helpers/statsrange.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ namespace snmalloc
{
using ContainsParent<ParentRange>::parent;

static inline stl::Atomic<size_t> current_usage{};
static inline stl::Atomic<size_t> peak_usage{};
static inline Stat usage{};

public:
static constexpr bool Aligned = ParentRange::Aligned;
Expand All @@ -30,34 +29,26 @@ namespace snmalloc

CapPtr<void, ChunkBounds> alloc_range(size_t size)
{
auto result = parent.alloc_range(size);
if (result != nullptr)
{
auto prev = current_usage.fetch_add(size);
auto curr = peak_usage.load();
while (curr < prev + size)
{
if (peak_usage.compare_exchange_weak(curr, prev + size))
break;
}
}
return result;
auto r = parent.alloc_range(size);
if (r != nullptr)
usage += size;
return r;
}

void dealloc_range(CapPtr<void, ChunkBounds> base, size_t size)
{
current_usage -= size;
usage -= size;
parent.dealloc_range(base, size);
}

size_t get_current_usage()
{
return current_usage.load();
return usage.get_curr();
}

size_t get_peak_usage()
{
return peak_usage.load();
return usage.get_peak();
}
};
};
Expand Down
1 change: 0 additions & 1 deletion src/snmalloc/ds_aal/seqset.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once

#include "../aal/aal.h"
#include "../ds_core/ds_core.h"
#include "snmalloc/stl/type_traits.h"
#include "snmalloc/stl/utility.h"
Expand Down
185 changes: 185 additions & 0 deletions src/snmalloc/ds_core/array.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
#pragma once

#include "defines.h"

#include <stddef.h>

namespace snmalloc
{
/**
* A simple fixed-size array container.
*
* This provides a std::array-like interface without depending on the
* standard library. The array supports aggregate initialization and
* provides iterators for range-based for loops.
*
* @tparam T The element type
* @tparam N The number of elements
*/
template<typename T, size_t N>
struct Array
{
// Expose this to public to allow aggregate initialization.
T storage_[N];

[[nodiscard]] constexpr SNMALLOC_FAST_PATH size_t size() const
{
return N;
}

constexpr T& operator[](size_t i)
{
return storage_[i];
}

constexpr const T& operator[](size_t i) const
{
return storage_[i];
}

using value_type = T;
using size_type = size_t;
using iterator = T*;
using const_iterator = const T*;

[[nodiscard]] constexpr SNMALLOC_FAST_PATH iterator begin()
{
return &storage_[0];
}

[[nodiscard]] constexpr SNMALLOC_FAST_PATH const_iterator begin() const
{
return &storage_[0];
}

[[nodiscard]] constexpr SNMALLOC_FAST_PATH iterator end()
{
return &storage_[N];
}

[[nodiscard]] constexpr SNMALLOC_FAST_PATH const_iterator end() const
{
return &storage_[N];
}

[[nodiscard]] constexpr SNMALLOC_FAST_PATH T* data()
{
return &storage_[0];
}

[[nodiscard]] constexpr SNMALLOC_FAST_PATH const T* data() const
{
return &storage_[0];
}
};

/**
* Specialization for zero-length arrays.
*
* Zero-length arrays are not valid in standard C++, so we provide
* a specialization that has no storage but maintains the same interface.
*/
template<typename T>
struct Array<T, 0>
{
[[nodiscard]] constexpr SNMALLOC_FAST_PATH size_t size() const
{
return 0;
}

constexpr T& operator[](size_t)
{
SNMALLOC_FAST_FAIL();
}

constexpr const T& operator[](size_t) const
{
SNMALLOC_FAST_FAIL();
}

using value_type = T;
using size_type = size_t;
using iterator = T*;
using const_iterator = const T*;

[[nodiscard]] constexpr SNMALLOC_FAST_PATH iterator begin()
{
return nullptr;
}

[[nodiscard]] constexpr SNMALLOC_FAST_PATH const_iterator begin() const
{
return nullptr;
}

[[nodiscard]] constexpr SNMALLOC_FAST_PATH iterator end()
{
return nullptr;
}

[[nodiscard]] constexpr SNMALLOC_FAST_PATH const_iterator end() const
{
return nullptr;
}

[[nodiscard]] constexpr SNMALLOC_FAST_PATH T* data()
{
return nullptr;
}

[[nodiscard]] constexpr SNMALLOC_FAST_PATH const T* data() const
{
return nullptr;
}
};

// Free function begin/end for Array
template<typename T, size_t N>
constexpr T* begin(Array<T, N>& a)
{
return a.begin();
}

template<typename T, size_t N>
constexpr T* end(Array<T, N>& a)
{
return a.end();
}

template<typename T, size_t N>
constexpr const T* begin(const Array<T, N>& a)
{
return a.begin();
}

template<typename T, size_t N>
constexpr const T* end(const Array<T, N>& a)
{
return a.end();
}

// Free function begin/end for C-style arrays
template<typename T, size_t N>
constexpr T* begin(T (&a)[N])
{
return &a[0];
}

template<typename T, size_t N>
constexpr T* end(T (&a)[N])
{
return &a[N];
}

template<typename T, size_t N>
constexpr const T* begin(const T (&a)[N])
{
return &a[0];
}

template<typename T, size_t N>
constexpr const T* end(const T (&a)[N])
{
return &a[N];
}
} // namespace snmalloc
3 changes: 2 additions & 1 deletion src/snmalloc/ds_core/ds_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
#include "mitigations.h"
#include "ptrwrap.h"
#include "redblacktree.h"
#include "tid.h"
#include "stats.h"
#include "tid.h"
101 changes: 101 additions & 0 deletions src/snmalloc/ds_core/stats.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#pragma once

#include "defines.h"
#include "snmalloc/stl/atomic.h"
#include "stddef.h"

namespace snmalloc
{
/**
* Very basic statistic that tracks current and peak values.
*/
class Stat
{
private:
stl::Atomic<size_t> curr{0};
stl::Atomic<size_t> peak{0};

public:
void increase(size_t amount)
{
size_t old = curr.fetch_add(amount);
size_t c = old + amount;
size_t p = peak.load(stl::memory_order_relaxed);
while (c > p)
{
if (peak.compare_exchange_strong(p, c))
break;
}
}

void decrease(size_t amount)
{
size_t prev = curr.fetch_sub(amount);
SNMALLOC_ASSERT_MSG(
prev >= amount, "prev = {}, amount = {}", prev, amount);
UNUSED(prev);
}

size_t get_curr()
{
return curr.load(stl::memory_order_relaxed);
}

size_t get_peak()
{
return peak.load(stl::memory_order_relaxed);
}

void operator+=(size_t amount)
{
increase(amount);
}

void operator-=(size_t amount)
{
decrease(amount);
}

void operator++()
{
increase(1);
}

void operator--()
{
decrease(1);
}
};

/**
* Very basic statistic that can only grow. Not thread-safe.
*/
class MonotoneLocalStat
{
stl::Atomic<size_t> value{0};

public:
SNMALLOC_FAST_PATH void operator++(int)
{
auto old = value.load(stl::memory_order_relaxed);
value.store(old + 1, stl::memory_order_relaxed);
}

SNMALLOC_FAST_PATH void operator+=(const MonotoneLocalStat& other)
{
auto v = other.value.load(stl::memory_order_relaxed);
value.fetch_add(v, stl::memory_order_relaxed);
}

SNMALLOC_FAST_PATH void operator+=(size_t v)
{
auto old = value.load(stl::memory_order_relaxed);
value.store(old + v, stl::memory_order_relaxed);
}

SNMALLOC_FAST_PATH size_t operator*()
{
return value.load(stl::memory_order_relaxed);
}
};
} // namespace snmalloc
Loading
Loading