Skip to content

Commit

Permalink
When arena is flat, sequential allocations don't need special rules
Browse files Browse the repository at this point in the history
  • Loading branch information
fwsGonzo committed Jun 23, 2024
1 parent a62235a commit 320a8cd
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
45 changes: 41 additions & 4 deletions lib/libriscv/native_heap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,51 @@ struct Arena
using unknown_realloc_func_t = Function<ReallocResult(PointerType, size_t)>;
using unknown_free_func_t = Function<int(PointerType, ArenaChunk *)>;

Arena(const Arena& other);
/// @brief Construct an arena that manages allocations for a given memory range.
/// @param base The base address of the memory range.
/// @param end The end address of the memory range.
Arena(PointerType base, PointerType end);

/// @brief Transfer allocations from another arena.
/// @param other The arena to transfer allocations from.
/// @note The other arena is left unchanged, allowing for multiple transfers.
Arena(const Arena& other);

/// @brief Allocate memory from the arena.
/// @param size The size of the allocation.
/// @return Address to the allocated memory range, or 0 if allocation failed.
/// @note The memory range is not guaranteed to be zeroed. 8-byte alignment is guaranteed.
PointerType malloc(size_t size);

/// @brief Reallocate memory from the arena.
/// @param ptr The allocation to resize.
/// @param newsize The new size of the allocation.
/// @return Pointer to the reallocated memory range, or 0 if reallocation failed.
/// @note Memory is not moved here, only the allocation itself. An implementor
/// should copy the data from the old pointer to the new pointer if necessary.
ReallocResult realloc(PointerType old, size_t size);

/// @brief Get the size of an allocation.
/// @param src The pointer to the memory range.
/// @param allow_free Whether to allow querying the size of a free chunk.
/// @return The size of the memory range, or 0 if the pointer is invalid.
size_t size(PointerType src, bool allow_free = false);

/// @brief Free a previous allocation.
/// @param src The pointer to the memory range.
/// @return 0 if the memory range was successfully freed, or -1 if the pointer is invalid.
signed int free(PointerType);

PointerType seq_alloc_aligned(size_t size, size_t alignment);
/// @brief Attempt to allocate a fully sequential memory range,
/// unless the arena is flat, in which case all memory is sequential.
/// Alignment is currently ignored, but 8-byte alignment is guaranteed.
/// @param size The size of the memory range to allocate.
/// @param alignment The alignment of the returned address.
/// @param arena_is_flat Whether the arena is flat. A configuration option.
/// @return Pointer to the allocated memory range, or 0 if allocation failed.
/// @note The memory range is not guaranteed to be zeroed.
/// @note If an excessive amount of chunks are allocated, an exception is thrown.
PointerType seq_alloc_aligned(size_t size, size_t alignment, bool arena_is_flat = riscv::flat_readwrite_arena);

size_t bytes_free() const;
size_t bytes_used() const;
Expand Down Expand Up @@ -229,7 +265,7 @@ inline Arena::PointerType Arena::malloc(size_t size)
// when accessed outside of emulation. A single page
// has fully sequential memory within itself, so we can
// always allocate sequential memory within a single page.
inline Arena::PointerType Arena::seq_alloc_aligned(size_t size, size_t alignment)
inline Arena::PointerType Arena::seq_alloc_aligned(size_t size, size_t alignment, bool arena_is_flat)
{
assert(alignment != 0x0);
(void)alignment;
Expand All @@ -245,7 +281,8 @@ inline Arena::PointerType Arena::seq_alloc_aligned(size_t size, size_t alignment
if (ch != nullptr) {
// XXX: Assume that alignment of data is OK
// Check if the allocation crosses a page
if ((ch->data & ~(RISCV_PAGE_SIZE-1)) !=
if (arena_is_flat ||
(ch->data & ~(RISCV_PAGE_SIZE-1)) !=
((ch->data + size) & ~(RISCV_PAGE_SIZE-1)))
{
// The second page boundary
Expand Down
5 changes: 3 additions & 2 deletions tests/unit/heaptest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ static Allocation alloc_random(riscv::Arena& arena)
static Allocation alloc_sequential(riscv::Arena& arena)
{
const size_t size = randInt(0, 8000);
const uintptr_t addr = arena.seq_alloc_aligned(size, 8);
const uintptr_t addr = arena.seq_alloc_aligned(size, 8, false);
REQUIRE(IS_WITHIN(addr));
// In order for the memory to be sequential in both the
// host and the guest, it must be on the same page (for now).
// host and the guest, it must be on the same page. We explicitly
// disable the flat read-write arena optimization for this test.
if (size > 0 && size < RISCV_PAGE_SIZE)
{
const auto page1 = addr & ~(RISCV_PAGE_SIZE - 1);
Expand Down

0 comments on commit 320a8cd

Please sign in to comment.