ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_slab.h File Reference

Fixed-cell slab allocator – O(1), zero-fragmentation, zero-heap. More...

#include <stdint.h>
#include "ra8_err.h"
Include dependency graph for ra8_slab.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ra8_slab_t
 Caller-owned state for one fixed-cell pool. More...

Enumerations

enum  ra8_slab_const_t : uint32_t {
  k_ra8_slab_nil = 0xFFFFFFFFU ,
  k_ra8_slab_min_cell_bytes = 4U ,
  k_ra8_slab_align_bytes = 4U
}
 Slab sizing limits and the freelist terminator. More...

Functions

ra8_err_t ra8_slab_init (ra8_slab_t *slab, void *buffer, uint32_t buffer_bytes, uint32_t cell_bytes)
 Initialise a slab over a caller-owned buffer.
ra8_err_t ra8_slab_alloc (ra8_slab_t *slab, void **out_cell)
 Allocate one cell from the slab (O(1)).
ra8_err_t ra8_slab_free (ra8_slab_t *slab, void *cell)
 Return a previously-allocated cell to the slab (O(1)).
ra8_err_t ra8_slab_stats (const ra8_slab_t *slab, uint32_t *out_free, uint32_t *out_total)
 Report the slab's free / total cell counts.

Detailed Description

Fixed-cell slab allocator – O(1), zero-fragmentation, zero-heap.

Tag
[Ring 2 / Core] {World: NS}

Layer 0 of the #147 memory hierarchy. A slab carves a caller-owned buffer into a fixed number of equal-size cells and hands them out / takes them back in O(1) from an intrusive freelist. Because every cell is the same size there is no external fragmentation, and because the backing buffer is supplied by the caller (carved once from a per-tier arena at init), nothing is ever malloc'd after init – NASA Power-of-10 Rule 3.

The freelist is threaded through the free cells themselves: each free cell's first 4 bytes hold the index of the next free cell (k_ra8_slab_nil terminates). So a slab needs zero side-table memory and cell_bytes must be at least 4 and a multiple of 4; the backing buffer must be 4-byte aligned (and aligned to whatever the cells' payload needs).

Typical Layer-2 use: 4 KiB page frames in SDRAM. Typical Layer-3 use: glyph bitmaps in SRAM. The slab is agnostic to what a cell holds.

[[gnu::aligned(8)]] * static uint8_t s_pool[64U * 4096U];
ra8_slab_t frames = {};
(void)ra8_slab_init(&frames, s_pool, sizeof(s_pool), 4096U); // 64 x 4 KiB
void* f = nullptr;
if (ra8_slab_alloc(&frames, &f) == k_ra8_ok) { ... ra8_slab_free(&frames, f); }
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
static ra8_esp_hosted_pool_state_t s_pool
Singleton state of the memory and queue half.
ra8_err_t ra8_slab_alloc(ra8_slab_t *slab, void **out_cell)
Allocate one cell from the slab (O(1)).
Definition ra8_slab.c:111
ra8_err_t ra8_slab_free(ra8_slab_t *slab, void *cell)
Return a previously-allocated cell to the slab (O(1)).
Definition ra8_slab.c:125
ra8_err_t ra8_slab_init(ra8_slab_t *slab, void *buffer, uint32_t buffer_bytes, uint32_t cell_bytes)
Initialise a slab over a caller-owned buffer.
Definition ra8_slab.c:85
Caller-owned state for one fixed-cell pool.
Definition ra8_slab.h:75
Note
Not thread-safe; callers serialise (single-threaded reader / IRQs masked).
Since
0.1.0

Definition in file ra8_slab.h.

Enumeration Type Documentation

◆ ra8_slab_const_t

enum ra8_slab_const_t : uint32_t

Slab sizing limits and the freelist terminator.

Since
0.1.0
Enumerator
k_ra8_slab_nil 

Freelist terminator (no next cell).

k_ra8_slab_min_cell_bytes 

Smallest cell (holds one index).

k_ra8_slab_align_bytes 

Required cell-size + buffer alignment.

Definition at line 57 of file ra8_slab.h.

Function Documentation

◆ ra8_slab_alloc()

ra8_err_t ra8_slab_alloc ( ra8_slab_t * slab,
void ** out_cell )
nodiscard

Allocate one cell from the slab (O(1)).

Parameters
[in]slabInitialised slab.
[out]out_cellReceives the cell pointer on success.
Returns
ra8_err_t Error code.
Return values
k_ra8_okA cell was handed out; *out_cell set.
k_ra8_err_null_ptrslab or out_cell was NULL.
k_ra8_err_no_memThe slab is exhausted (no free cell).
Precondition
slab was populated by ra8_slab_init.
out_cell is writable.
Postcondition
On success *out_cell points at cell_bytes of usable storage.
On success free_count decreased by one.
Note
Not thread-safe. The returned cell's contents are unspecified.
Since
0.1.0

Definition at line 111 of file ra8_slab.c.

References ra8_slab_t::base, ra8_slab_t::cell_bytes, ra8_slab_t::free_count, ra8_slab_t::free_head, internal_slab_next(), k_ra8_err_no_mem, k_ra8_ok, k_ra8_slab_nil, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by mem_run_slab().

◆ ra8_slab_free()

ra8_err_t ra8_slab_free ( ra8_slab_t * slab,
void * cell )
nodiscard

Return a previously-allocated cell to the slab (O(1)).

Parameters
[in]slabInitialised slab.
[in]cellA cell pointer previously returned by ra8_slab_alloc.
Returns
ra8_err_t Error code.
Return values
k_ra8_okCell returned to the freelist.
k_ra8_err_null_ptrslab or cell was NULL.
k_ra8_err_invalid_argcell is outside the slab or not on a cell boundary.
Precondition
cell came from this slab and is not already free.
slab was populated by ra8_slab_init.
Postcondition
On success free_count increased by one and cell is reusable.
On any non-ok return the slab is unchanged.
Note
Not thread-safe. Double-free of an in-bounds cell is not detected (it corrupts the freelist); callers must not double-free.
Since
0.1.0

Definition at line 125 of file ra8_slab.c.

References ra8_slab_t::base, ra8_slab_t::cell_bytes, ra8_slab_t::cell_count, ra8_slab_t::free_count, ra8_slab_t::free_head, internal_slab_set_next(), k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by mem_run_slab().

◆ ra8_slab_init()

ra8_err_t ra8_slab_init ( ra8_slab_t * slab,
void * buffer,
uint32_t buffer_bytes,
uint32_t cell_bytes )
nodiscard

Initialise a slab over a caller-owned buffer.

Divides buffer into floor(buffer_bytes / cell_bytes) cells and threads every cell onto the freelist so all cells start free.

Parameters
[out]slabSlab state to populate (zero-initialised by caller).
[in]bufferBacking memory, 4-byte aligned, out-living the slab.
[in]buffer_bytesSize of buffer in bytes.
[in]cell_bytesBytes per cell (>= 4 and a multiple of 4).
Returns
ra8_err_t Error code.
Return values
k_ra8_okSlab ready; all cells free.
k_ra8_err_null_ptrslab or buffer was NULL.
k_ra8_err_invalid_sizecell_bytes < 4, not 4-aligned, or larger than buffer_bytes (zero cells).
Precondition
buffer is at least buffer_bytes and 4-byte aligned.
slab does not alias buffer.
Postcondition
On success slab->free_count == slab->cell_count >= 1.
On any non-ok return slab is left unmodified-usable (not bound).
Note
Not thread-safe.
Since
0.1.0

Definition at line 85 of file ra8_slab.c.

References ra8_slab_t::base, ra8_slab_t::cell_bytes, ra8_slab_t::cell_count, ra8_slab_t::free_count, ra8_slab_t::free_head, internal_slab_set_next(), k_ra8_err_invalid_size, k_ra8_ok, k_ra8_slab_align_bytes, k_ra8_slab_min_cell_bytes, k_ra8_slab_nil, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by mem_run_slab().

◆ ra8_slab_stats()

ra8_err_t ra8_slab_stats ( const ra8_slab_t * slab,
uint32_t * out_free,
uint32_t * out_total )
nodiscard

Report the slab's free / total cell counts.

Parameters
[in]slabInitialised slab.
[out]out_freeFree cell count (may be NULL).
[out]out_totalTotal cell count (may be NULL).
Returns
ra8_err_t Error code.
Return values
k_ra8_okCounters reported.
k_ra8_err_null_ptrslab was NULL.
Precondition
slab was populated by ra8_slab_init.
At least one output pointer is non-NULL to be useful.
Postcondition
On success the requested counters are written.
No slab state is mutated.
Note
Thread-safe with respect to a quiescent slab (pure read).
Since
0.1.0

Definition at line 149 of file ra8_slab.c.

References ra8_slab_t::base, ra8_slab_t::cell_count, ra8_slab_t::free_count, k_ra8_err_invalid_state, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by mem_run_slab().