ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
arena.h File Reference

Unified double-ended server arena (Phase 1: core allocator, one region). More...

#include <stddef.h>
#include <stdint.h>

Go to the source code of this file.

Classes

struct  pc_arena
 Double-ended arena over one region [base, base+size). More...
 
struct  pc_arena_set
 A set of pc_arena regions searched in insertion (preference) order. More...
 
struct  pc_arena_mark
 A scratch savepoint across every region of a pc_arena_set. More...
 

Macros

#define PC_ARENA_ALIGN   8u
 Baseline alignment (bytes) applied to every allocation and to headers.
 
#define PC_ARENA_MAX_ALIGN   16u
 Strongest alignment a scratch borrow may request; the region base is aligned to it.
 
#define PC_ARENA_MAX_REGIONS   2u
 Max regions in a pc_arena_set (DRAM base + PSRAM extension).
 

Functions

size_t pc_arena_align_up (size_t n)
 Round n up to PC_ARENA_ALIGN.
 
void pc_arena_init (pc_arena *a, void *base, size_t size)
 Initialize a over the region [base, base+size).
 
void * pc_arena_persist_alloc (pc_arena *a, size_t n)
 Allocate n zero-initialized bytes of long-lived storage.
 
void pc_arena_persist_free (pc_arena *a, void *p)
 Free a pointer previously returned by pc_arena_persist_alloc().
 
void * pc_arena_scratch_alloc_aligned (pc_arena *a, size_t n, size_t align)
 Bump-allocate n bytes of transient storage, aligned to align.
 
void * pc_arena_scratch_alloc (pc_arena *a, size_t n)
 Bump-allocate n transient bytes at the baseline alignment (PC_ARENA_ALIGN).
 
size_t pc_arena_scratch_mark (const pc_arena *a)
 Capture the current scratch position (a savepoint for pc_arena_scratch_release()).
 
void pc_arena_scratch_release (pc_arena *a, size_t mark)
 Free every scratch allocation made since mark (a value from pc_arena_scratch_mark()).
 
void pc_arena_scratch_reset (pc_arena *a)
 Free ALL scratch allocations in O(1).
 
bool pc_arena_owns (const pc_arena *a, const void *p)
 True if p points inside this pool's region.
 
size_t pc_arena_free_bytes (const pc_arena *a)
 Free bytes in the middle (max a single new allocation could take, minus a header).
 
size_t pc_arena_persist_used (const pc_arena *a)
 Persistent payload bytes currently allocated.
 
size_t pc_arena_scratch_used (const pc_arena *a)
 Scratch bytes currently allocated.
 
void pc_arena_set_init (pc_arena_set *s)
 Initialize an empty set (no regions yet).
 
bool pc_arena_set_add (pc_arena_set *s, void *base, size_t size)
 Add a region [base, base+size); regions are searched in the order added.
 
void * pc_arena_set_persist_alloc (pc_arena_set *s, size_t n)
 Persistent alloc from the first region that fits (see pc_arena_persist_alloc()).
 
void pc_arena_set_persist_free (pc_arena_set *s, void *p)
 Free a persistent pointer, routed to its owning region by address.
 
void * pc_arena_set_scratch_alloc_aligned (pc_arena_set *s, size_t n, size_t align)
 Aligned scratch alloc from the first region that fits (see pc_arena_scratch_alloc_aligned()).
 
void * pc_arena_set_scratch_alloc (pc_arena_set *s, size_t n)
 Scratch alloc from the first region that fits (see pc_arena_scratch_alloc()).
 
pc_arena_mark pc_arena_set_scratch_mark (const pc_arena_set *s)
 Capture the scratch position of every region.
 
void pc_arena_set_scratch_release (pc_arena_set *s, const pc_arena_mark *m)
 Restore every region's scratch position to m (frees scratch made since).
 
void pc_arena_set_scratch_reset (pc_arena_set *s)
 Reset scratch in every region.
 
size_t pc_arena_set_free_bytes (const pc_arena_set *s)
 Total free middle bytes summed over all regions.
 
size_t pc_arena_set_persist_used (const pc_arena_set *s)
 Persistent payload bytes allocated, summed over all regions.
 
size_t pc_arena_set_scratch_used (const pc_arena_set *s)
 Scratch bytes allocated, summed over all regions.
 

Detailed Description

Unified double-ended server arena (Phase 1: core allocator, one region).

One contiguous region is shared by two allocators that grow toward each other, with the free space floating in the middle:

[ persistent –grows up--> | free | <–grows down– scratch ] low addr (floating boundary) high addr

  • Persistent (bottom): a first-fit free-list. Long-lived objects that are freed individually, in arbitrary order (e.g. per-connection state). Grows up into the middle only as far as the scratch end allows; a freed top block shrinks it back.
  • Scratch (top): a bump allocator reclaimed in bulk. Transient per-dispatch buffers. scratch_reset() empties it in O(1); mark/release give nested savepoints.

Whichever side needs more room grows into the shared middle - that is the win over two fixed pools. Both ends fail closed (return NULL) rather than crossing the boundary.

All state lives in pc_arena (no globals), so it is unit-testable and can back several arenas (a DRAM base and a PSRAM extension, in a later phase). No heap; no stdlib.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file arena.h.

Macro Definition Documentation

◆ PC_ARENA_ALIGN

#define PC_ARENA_ALIGN   8u

Baseline alignment (bytes) applied to every allocation and to headers.

Definition at line 37 of file arena.h.

◆ PC_ARENA_MAX_ALIGN

#define PC_ARENA_MAX_ALIGN   16u

Strongest alignment a scratch borrow may request; the region base is aligned to it.

Definition at line 46 of file arena.h.

◆ PC_ARENA_MAX_REGIONS

#define PC_ARENA_MAX_REGIONS   2u

Max regions in a pc_arena_set (DRAM base + PSRAM extension).

Definition at line 216 of file arena.h.

Function Documentation

◆ pc_arena_align_up()

size_t pc_arena_align_up ( size_t  n)
inline

Round n up to PC_ARENA_ALIGN.

Definition at line 40 of file arena.h.

References PC_ARENA_ALIGN.

Referenced by pc_arena_scratch_alloc_aligned().

◆ pc_arena_init()

void pc_arena_init ( pc_arena a,
void *  base,
size_t  size 
)

Initialize a over the region [base, base+size).

base should be PC_ARENA_ALIGN-aligned; size must be at least a few blocks.

Definition at line 29 of file arena.cpp.

References pc_arena::base, PC_ARENA_ALIGN, PC_ARENA_MAX_ALIGN, pc_arena::persist_end, pc_arena::persist_hw, pc_arena::persist_used, pc_arena::scratch_hw, pc_arena::scratch_top, and pc_arena::size.

Referenced by pc_arena_set_add().

◆ pc_arena_persist_alloc()

void * pc_arena_persist_alloc ( pc_arena a,
size_t  n 
)

Allocate n zero-initialized bytes of long-lived storage.

First-fits an existing free block; otherwise carves a new block from the free middle (growing the persistent end up) if it will not cross the scratch end.

Returns
aligned, zeroed pointer, or NULL if the arena cannot satisfy it.

Definition at line 49 of file arena.cpp.

References pc_arena::base, PC_ARENA_ALIGN, pc_arena::persist_end, pc_arena::persist_hw, and pc_arena::persist_used.

Referenced by pc_arena_set_persist_alloc().

◆ pc_arena_persist_free()

void pc_arena_persist_free ( pc_arena a,
void *  p 
)

Free a pointer previously returned by pc_arena_persist_alloc().

Coalesces with adjacent free blocks; if the freed block sits at the top of the persistent region it returns that space to the free middle (shrinks the boundary). Passing NULL is a no-op.

Definition at line 98 of file arena.cpp.

References pc_arena::base, pc_arena::persist_end, and pc_arena::persist_used.

Referenced by pc_arena_set_persist_free().

◆ pc_arena_scratch_alloc_aligned()

void * pc_arena_scratch_alloc_aligned ( pc_arena a,
size_t  n,
size_t  align 
)
inline

Bump-allocate n bytes of transient storage, aligned to align.

Parameters
alignpower-of-two alignment for the returned pointer; clamped to [PC_ARENA_ALIGN, PC_ARENA_MAX_ALIGN].
Returns
aligned pointer (NOT zeroed), or NULL if it would cross the persistent end.

Definition at line 109 of file arena.h.

References pc_arena::base, PC_ARENA_ALIGN, pc_arena_align_up(), PC_ARENA_MAX_ALIGN, pc_arena::scratch_hw, pc_arena::scratch_top, and pc_arena::size.

Referenced by pc_arena_scratch_alloc(), pc_arena_set_scratch_alloc_aligned(), pc_secure_alloc(), scratch_alloc(), ScratchBorrow::ScratchBorrow(), and SecureBorrow::SecureBorrow().

◆ pc_arena_scratch_alloc()

void * pc_arena_scratch_alloc ( pc_arena a,
size_t  n 
)

Bump-allocate n transient bytes at the baseline alignment (PC_ARENA_ALIGN).

Definition at line 153 of file arena.cpp.

References PC_ARENA_ALIGN, and pc_arena_scratch_alloc_aligned().

◆ pc_arena_scratch_mark()

size_t pc_arena_scratch_mark ( const pc_arena a)
inline

Capture the current scratch position (a savepoint for pc_arena_scratch_release()).

Definition at line 146 of file arena.h.

References pc_arena::scratch_top.

Referenced by pc_secure_mark(), scratch_mark(), ScratchBorrow::ScratchBorrow(), and SecureBorrow::SecureBorrow().

◆ pc_arena_scratch_release()

void pc_arena_scratch_release ( pc_arena a,
size_t  mark 
)
inline

Free every scratch allocation made since mark (a value from pc_arena_scratch_mark()).

Definition at line 152 of file arena.h.

References pc_arena::scratch_top.

Referenced by pc_arena_set_scratch_release(), scratch_release(), and ScratchBorrow::~ScratchBorrow().

◆ pc_arena_scratch_reset()

void pc_arena_scratch_reset ( pc_arena a)
inline

Free ALL scratch allocations in O(1).

Definition at line 162 of file arena.h.

References pc_arena::scratch_top, and pc_arena::size.

Referenced by pc_arena_set_scratch_reset(), and scratch_reset().

◆ pc_arena_owns()

bool pc_arena_owns ( const pc_arena a,
const void *  p 
)
inline

True if p points inside this pool's region.

Ownership is an address-range property, not bookkeeping. The pools occupy disjoint regions, so a pointer belongs to exactly one of them and the owner is recoverable from the address alone. That is what stops a secret-pool pointer from ever being accepted where a plaintext one is expected, and what makes a write that ran off the end land outside the range instead of silently into a neighbour.

The accessors answer this more cheaply still: their slot count and slot size are compile-time, so the whole pool is one region of known extent and the test is a single unsigned subtract against a constant bound - see pc_scratch_owns() / pc_secure_owns(). This general version is two compares, for an arena whose base and size are only known at run time.

Definition at line 183 of file arena.h.

References pc_arena::base, and pc_arena::size.

◆ pc_arena_free_bytes()

size_t pc_arena_free_bytes ( const pc_arena a)

Free bytes in the middle (max a single new allocation could take, minus a header).

Definition at line 162 of file arena.cpp.

References pc_arena::persist_end, and pc_arena::scratch_top.

Referenced by pc_arena_set_free_bytes().

◆ pc_arena_persist_used()

size_t pc_arena_persist_used ( const pc_arena a)

Persistent payload bytes currently allocated.

Definition at line 168 of file arena.cpp.

References pc_arena::persist_used.

Referenced by pc_arena_set_persist_used().

◆ pc_arena_scratch_used()

size_t pc_arena_scratch_used ( const pc_arena a)
inline

Scratch bytes currently allocated.

Definition at line 198 of file arena.h.

References pc_arena::scratch_top, and pc_arena::size.

Referenced by pc_arena_set_scratch_used(), pc_secure_used(), and scratch_used().

◆ pc_arena_set_init()

void pc_arena_set_init ( pc_arena_set s)

Initialize an empty set (no regions yet).

Definition at line 177 of file arena.cpp.

References pc_arena_set::count.

◆ pc_arena_set_add()

bool pc_arena_set_add ( pc_arena_set s,
void *  base,
size_t  size 
)

Add a region [base, base+size); regions are searched in the order added.

Returns
true if added, false if the set is full or the region is too small.

Definition at line 182 of file arena.cpp.

References pc_arena_set::count, PC_ARENA_ALIGN, pc_arena_init(), PC_ARENA_MAX_REGIONS, pc_arena_set::region, and pc_arena::size.

◆ pc_arena_set_persist_alloc()

void * pc_arena_set_persist_alloc ( pc_arena_set s,
size_t  n 
)

Persistent alloc from the first region that fits (see pc_arena_persist_alloc()).

Definition at line 198 of file arena.cpp.

References pc_arena_set::count, pc_arena_persist_alloc(), and pc_arena_set::region.

◆ pc_arena_set_persist_free()

void pc_arena_set_persist_free ( pc_arena_set s,
void *  p 
)

Free a persistent pointer, routed to its owning region by address.

Definition at line 211 of file arena.cpp.

References pc_arena::base, pc_arena_set::count, pc_arena_persist_free(), pc_arena_set::region, and pc_arena::size.

◆ pc_arena_set_scratch_alloc_aligned()

void * pc_arena_set_scratch_alloc_aligned ( pc_arena_set s,
size_t  n,
size_t  align 
)

Aligned scratch alloc from the first region that fits (see pc_arena_scratch_alloc_aligned()).

Definition at line 229 of file arena.cpp.

References pc_arena_set::count, pc_arena_scratch_alloc_aligned(), and pc_arena_set::region.

Referenced by pc_arena_set_scratch_alloc().

◆ pc_arena_set_scratch_alloc()

void * pc_arena_set_scratch_alloc ( pc_arena_set s,
size_t  n 
)

Scratch alloc from the first region that fits (see pc_arena_scratch_alloc()).

Definition at line 242 of file arena.cpp.

References PC_ARENA_ALIGN, and pc_arena_set_scratch_alloc_aligned().

◆ pc_arena_set_scratch_mark()

pc_arena_mark pc_arena_set_scratch_mark ( const pc_arena_set s)

Capture the scratch position of every region.

Definition at line 247 of file arena.cpp.

References pc_arena_set::count, pc_arena_mark::count, pc_arena_set::region, pc_arena::scratch_top, and pc_arena_mark::top.

◆ pc_arena_set_scratch_release()

void pc_arena_set_scratch_release ( pc_arena_set s,
const pc_arena_mark m 
)

Restore every region's scratch position to m (frees scratch made since).

Definition at line 258 of file arena.cpp.

References pc_arena_set::count, pc_arena_mark::count, pc_arena_scratch_release(), pc_arena_set::region, and pc_arena_mark::top.

◆ pc_arena_set_scratch_reset()

void pc_arena_set_scratch_reset ( pc_arena_set s)

Reset scratch in every region.

Definition at line 267 of file arena.cpp.

References pc_arena_set::count, pc_arena_scratch_reset(), and pc_arena_set::region.

◆ pc_arena_set_free_bytes()

size_t pc_arena_set_free_bytes ( const pc_arena_set s)

Total free middle bytes summed over all regions.

Definition at line 275 of file arena.cpp.

References pc_arena_set::count, pc_arena_free_bytes(), and pc_arena_set::region.

◆ pc_arena_set_persist_used()

size_t pc_arena_set_persist_used ( const pc_arena_set s)

Persistent payload bytes allocated, summed over all regions.

Definition at line 285 of file arena.cpp.

References pc_arena_set::count, pc_arena_persist_used(), and pc_arena_set::region.

◆ pc_arena_set_scratch_used()

size_t pc_arena_set_scratch_used ( const pc_arena_set s)

Scratch bytes allocated, summed over all regions.

Definition at line 295 of file arena.cpp.

References pc_arena_set::count, pc_arena_scratch_used(), and pc_arena_set::region.