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

Caller-owned bounded-arena allocator for miniz. More...

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

Go to the source code of this file.

Data Structures

struct  epub_miniz_workspace_t
 Exactly-sized, maximally-aligned storage for one miniz arena. More...
struct  epub_miniz_arena_t
 Descriptor for one caller-owned miniz allocation arena. More...

Enumerations

enum  epub_miniz_alloc_limits_t : uint32_t { k_epub_miniz_pool_bytes = 163840U }
 Static pool geometry for the miniz arena. More...

Functions

ra8_err_t epub_miniz_arena_init (epub_miniz_arena_t *arena, void *workspace, size_t workspace_bytes)
 Initialise or reset a miniz arena over caller-owned storage.
void epub_miniz_arena_deinit (epub_miniz_arena_t *arena)
 Invalidate an arena descriptor after miniz has released its blocks.
void * epub_miniz_alloc (void *opaque, size_t items, size_t size)
 miniz-compatible allocator (mz_alloc_func).
void epub_miniz_free (void *opaque, void *address)
 miniz-compatible free (mz_free_func).
void * epub_miniz_realloc (void *opaque, void *address, size_t items, size_t size)
 miniz-compatible realloc (mz_realloc_func).

Detailed Description

Caller-owned bounded-arena allocator for miniz.

Tag
[Ring 4 / Domain] {World: NS}

The RA8D2 firmware is deliberately zero-heap: the linker script defines no .heap region and _sbrk() (ra8_sbrk_trap.c) traps any allocation, per NASA Power of 10 Rule 3. But epub opens .epub archives through the vendored miniz ZIP reader, whose mz_zip_reader_init_mem / mz_zip_reader_extract_to_mem allocate their central-directory state and a ~11 KiB tinfl_decompressor from the heap. Calling the default malloc on the target hits the _sbrk trap and HardFaults.

This module provides a self-contained first-fit free-list allocator over a caller-owned workspace, exposing the three callbacks miniz needs on its mz_zip_archive (m_pAlloc / m_pFree / m_pRealloc). Every archive owns a separate arena and passes its descriptor through miniz's m_pAlloc_opaque callback context. No hidden singleton or host-only heap fallback exists.

The free list coalesces adjacent free blocks on every free, so the pool is reusable across an arbitrary number of epub_load_chapter calls (each extract allocates then frees its decompressor) and across re-opens (closing a book frees its central directory). No explicit reset is required.

Note
One arena is not thread-safe. Independent arenas do not share state and may back simultaneously-live EPUB and CBZ objects.

Definition in file epub_miniz_alloc.h.

Enumeration Type Documentation

◆ epub_miniz_alloc_limits_t

enum epub_miniz_alloc_limits_t : uint32_t

Static pool geometry for the miniz arena.

Sized for the peak live footprint of one open .epub. Two footprints share the pool and must both fit alongside the central-directory arrays (which grow with the archive's file count and live for the book's whole open):

  • Whole-entry extract (mz_zip_reader_extract_to_mem, used by epub_load_chapter / ..._get_resource): the ~11 KiB inflate decompressor plus, on the streamed path, a bounded compressed-read buffer (MZ_ZIP_MAX_IO_BUF_SIZE, 64 KiB).
  • Streaming entry cursor (epub_entry_open, #231, over mz_zip_reader_extract_iter_*): the iterator state (~8.4 KiB, embeds the inflator) plus – for a DEFLATE entry – a 32 KiB LZ dictionary window and the same 64 KiB compressed-read buffer. A stored (method-0) entry needs only the ~8.4 KiB iterator state (miniz reads it directly, no dict/IO bufs).

The DEFLATE streaming cursor is therefore the peak: ~8.4 + 32 + 64 = ~105 KiB of transient inflate state, on top of the resident central directory. 160 KiB gives that peak room while staying tiny against the 1.6 MiB SRAM. A large in-content image (a manga page) is the motivating #231 case and is streamed through this cursor rather than materialised whole.

Enumerator
k_epub_miniz_pool_bytes 

Arena size, bytes (160 KiB).

Definition at line 74 of file epub_miniz_alloc.h.

Function Documentation

◆ epub_miniz_alloc()

void * epub_miniz_alloc ( void * opaque,
size_t items,
size_t size )

miniz-compatible allocator (mz_alloc_func).

Returns a block of at least items * size bytes from opaque's arena, aligned to max_align_t. First-fit over the free list; splits an oversized free block when the remainder can hold a header plus a minimum payload. Returns NULL on overflow of items * size or pool exhaustion.

Parameters
[in]opaquePointer to an initialised epub_miniz_arena_t.
[in]itemsElement count.
[in]sizeElement size, bytes.
Returns
Pointer to an aligned block, or NULL on overflow / exhaustion.
Precondition
items * size does not overflow size_t (checked; NULL if it does).
opaque names a live arena (NULL is rejected).
The arena has a free block large enough (else NULL).
Postcondition
On success the returned block is marked in-use and is >= requested.
On failure the pool is unchanged.
Note
One arena is not thread-safe; distinct arenas are independent.
Since
0.1.0

Definition at line 318 of file epub_miniz_alloc.c.

References internal_align_up(), internal_cell_at(), internal_end(), internal_next(), internal_payload(), internal_ready(), internal_request_bytes(), internal_split(), priv_blk_t::is_free, k_priv_align, k_priv_blk_free, k_priv_blk_used, k_priv_walk_max, and priv_blk_t::size.

Referenced by epub_miniz_realloc(), internal_set_alloc(), and priv_epub_set_miniz_alloc().

◆ epub_miniz_arena_deinit()

void epub_miniz_arena_deinit ( epub_miniz_arena_t * arena)

Invalidate an arena descriptor after miniz has released its blocks.

Clears only the descriptor; caller-owned workspace bytes remain available for a later explicit reinitialization.

Parameters
[in,out]arenaArena to invalidate; NULL is accepted.
Precondition
All allocations from arena have been released.
No miniz archive retains arena as its allocation context.
Postcondition
A non-NULL descriptor is zeroed; workspace bytes are unchanged.
A NULL argument performs no operation.
Note
Reinitialise with epub_miniz_arena_init before reuse.
Since
0.1.0

Definition at line 311 of file epub_miniz_alloc.c.

Referenced by epub_close(), epub_open(), epub_open_streamed(), priv_comic_cbz_close(), and priv_comic_cbz_open().

◆ epub_miniz_arena_init()

ra8_err_t epub_miniz_arena_init ( epub_miniz_arena_t * arena,
void * workspace,
size_t workspace_bytes )
nodiscard

Initialise or reset a miniz arena over caller-owned storage.

Parameters
[out]arenaDescriptor to initialise.
[in,out]workspaceMaximally-aligned backing storage.
[in]workspace_bytesWritable bytes at workspace.
Return values
k_ra8_okWorkspace accepted and reset to one free block.
k_ra8_err_null_ptrarena or workspace is NULL.
k_ra8_err_invalid_sizeFewer than k_epub_miniz_pool_bytes bytes were supplied.
k_ra8_err_invalid_argworkspace is not aligned for max_align_t.
Precondition
No allocation from arena is live when reinitialising it.
Postcondition
On success exactly k_epub_miniz_pool_bytes are bound.
On failure arena and workspace are unchanged.
Note
One arena is not thread-safe; distinct arenas are independent.
Since
0.1.0

Definition at line 288 of file epub_miniz_alloc.c.

References epub_miniz_arena_t::capacity, internal_cell_at(), internal_pointer_address(), priv_blk_t::is_free, k_epub_miniz_pool_bytes, k_priv_blk_free, k_priv_hdr_bytes, k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_err_null_ptr, k_ra8_ok, and priv_blk_t::size.

Referenced by internal_set_alloc(), and priv_epub_set_miniz_alloc().

◆ epub_miniz_free()

void epub_miniz_free ( void * opaque,
void * address )

miniz-compatible free (mz_free_func).

Marks address's block free and coalesces it with adjacent free blocks. A NULL address, invalid arena, or pointer outside that arena is ignored.

Parameters
[in]opaquePointer to the owning epub_miniz_arena_t.
[in]addressBlock previously returned by epub_miniz_alloc / epub_miniz_realloc, or NULL.
Precondition
address is NULL or a live block from this allocator.
opaque is the same live arena that allocated address.
Postcondition
address's block is free and merged with any free neighbours.
A NULL / out-of-pool address leaves the pool unchanged.
Note
One arena is not thread-safe; distinct arenas are independent.
Since
0.1.0

Definition at line 347 of file epub_miniz_alloc.c.

References internal_coalesce(), internal_header(), internal_in_pool(), priv_blk_t::is_free, and k_priv_blk_free.

Referenced by epub_miniz_realloc(), internal_set_alloc(), and priv_epub_set_miniz_alloc().

◆ epub_miniz_realloc()

void * epub_miniz_realloc ( void * opaque,
void * address,
size_t items,
size_t size )

miniz-compatible realloc (mz_realloc_func).

Grows or shrinks address to at least items * size bytes. Keeps the block in place when it already fits; otherwise allocates a new block, copies the old payload, and frees the old block. realloc(NULL, n) allocates; realloc(p, 0) frees and returns NULL.

Parameters
[in]opaquePointer to the owning epub_miniz_arena_t.
[in]addressExisting block, or NULL.
[in]itemsNew element count.
[in]sizeNew element size, bytes.
Returns
Pointer to a block of at least the requested size, or NULL on overflow / exhaustion (in which case address remains valid).
Precondition
opaque names a live arena.
address is NULL or a live block from that arena.
items * size does not overflow (checked).
Postcondition
On a moved grow, the old payload bytes are preserved in the new block.
On NULL-return for a non-NULL address, that block is still valid.
Note
One arena is not thread-safe; distinct arenas are independent.
Since
0.1.0

Definition at line 358 of file epub_miniz_alloc.c.

References epub_miniz_alloc(), epub_miniz_free(), internal_align_up(), internal_header(), internal_in_pool(), internal_request_bytes(), memcpy(), and priv_blk_t::size.

Referenced by internal_set_alloc(), and priv_epub_set_miniz_alloc().