|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
The one reusable hash + pin + evict cache engine (#147, #345). More...
Go to the source code of this file.
Data Structures | |
| struct | ra8_keycache_cell_t |
| Per-cell link metadata (one caller-owned array entry per cell). More... | |
| struct | ra8_keycache_cfg_t |
| Caller-supplied storage + policy + renderer for ra8_keycache_init. More... | |
| struct | ra8_keycache_t |
| Cache engine state (caller-owned; treat as private). More... | |
| struct | ra8_keycache_view_t |
| A pinned view of a cached cell returned by ra8_keycache_get. More... | |
Typedefs | |
| typedef uint32_t(* | ra8_keycache_hash_fn) (const void *key, uint32_t key_bytes, void *ctx) |
| Hash a key blob to a raw 32-bit value (the engine folds to a bucket). | |
| typedef ra8_err_t(* | ra8_keycache_render_fn) (void *ctx, const void *key, uint8_t *cell, uint32_t cell_bytes, void *user) |
Fill a cell with the rendered bytes for key (render-on-miss seam). | |
Enumerations | |
| enum | ra8_keycache_evict_t : uint8_t { k_ra8_keycache_evict_lru = 0U , k_ra8_keycache_evict_slru = 1U } |
| Eviction policy selected in ra8_keycache_cfg_t::evict. More... | |
Functions | |
| ra8_err_t | ra8_keycache_init (ra8_keycache_t *kc, const ra8_keycache_cfg_t *cfg) |
| Initialise a cache engine over caller-supplied storage. | |
| ra8_err_t | ra8_keycache_get (ra8_keycache_t *kc, const void *key, ra8_keycache_view_t *out_view) |
Get (and pin) the cell for key, rendering it on a miss. | |
| ra8_err_t | ra8_keycache_prefetch (ra8_keycache_t *kc, const void *key) |
Warm the cell for key into the cache without holding a pin. | |
| ra8_err_t | ra8_keycache_put (ra8_keycache_t *kc, const uint8_t *data) |
| Release one pin on a cell previously returned by ra8_keycache_get. | |
| ra8_err_t | ra8_keycache_stats (const ra8_keycache_t *kc, uint32_t *out_hits, uint32_t *out_misses, uint32_t *out_evictions) |
| Report the cache hit / miss / eviction counters. | |
The one reusable hash + pin + evict cache engine (#147, #345).
The single hash + pin + evict engine every reader cache is built on. #345 folded ::ra8_vmem's once-duplicate SLRU/hash/pin machinery into this one implementation, so the eviction policy is now a config choice rather than a second copy of the code. A keycache maps a fixed-size opaque key to a fixed-size opaque cell of filled bytes: a hit returns a pinned view of the cell; a miss evicts an unpinned victim, fills the cell through a caller-supplied render-on-miss callback, inserts it, and pins it. The caller releases the pin with ra8_keycache_put once it is done reading the cell.
The victim is always an unpinned cell (pinned cells are skipped); which one depends on the policy the caller selects:
The policy changes which cell is evicted, never how many are resident: the bounded-RAM guarantee (residency <= cell_count) holds at every setting.
Keys are compared byte-wise (memcmp over key_bytes), so a key struct must be fully initialised (zero-filled, no indeterminate padding) before use. The hash is injectable (cfg.hash, cfg.hash_ctx); a NULL hash selects the built-in FNV-1a over the key bytes. A facade whose key carries structure (::ra8_vmem hashes on the derived page number) supplies its own; the folding to [0, bucket_count) is always the engine's, so the hash callback returns a raw 32-bit value.
The render callback writes per-entry metadata there (e.g. the rendered glyph or tile width/height) and ra8_keycache_get hands the descriptor back alongside the cell data. This is how a typed facade (::ra8_glyph_atlas, ::ra8_tile_cache) recovers its dimensions without a parallel side table.
Zero allocation (NASA P10 Rule 3): the caller provides every array – the cell storage, the key storage, the optional user-descriptor storage, the per-cell link metadata, and the hash buckets – carved once from a tier ::ra8_arena / ::ra8_slab at init (hot tier = SRAM/DTCM).
Definition in file ra8_keycache.h.
| typedef uint32_t(* ra8_keycache_hash_fn) (const void *key, uint32_t key_bytes, void *ctx) |
Hash a key blob to a raw 32-bit value (the engine folds to a bucket).
Called on every lookup, insert, and evict to place a key in a hash bucket. Returns a raw 32-bit hash; the engine reduces it to [0, bucket_count). A NULL callback in the config selects the built-in FNV-1a over the key_bytes. Must be a pure function of the key bytes (and any immutable ctx) so a stored key rehashes to the same bucket it was inserted under.
| [in] | key | The key_bytes-wide key blob to hash. |
| [in] | key_bytes | Key width in bytes. |
| [in] | ctx | Opaque context (hash_ctx from the config), or NULL. |
Definition at line 119 of file ra8_keycache.h.
| typedef ra8_err_t(* ra8_keycache_render_fn) (void *ctx, const void *key, uint8_t *cell, uint32_t cell_bytes, void *user) |
Fill a cell with the rendered bytes for key (render-on-miss seam).
Called on a cache miss to populate cell with the content keyed by key, and (when the cache has a user descriptor) to write that entry's metadata into user. The glyph atlas rasterises a glyph here; the tile cache decodes an image tile; ::ra8_vmem loads a page; tests use a synthetic generator.
| [in] | ctx | Opaque render context (render_ctx from the config). |
| [in] | key | The key_bytes-wide key being filled. |
| [out] | cell | Destination cell buffer (cell_bytes writable). |
| [in] | cell_bytes | Cell capacity in bytes. |
| [out] | user | Per-cell user descriptor (user_bytes), or NULL when the cache was configured with user_bytes == 0. |
Definition at line 143 of file ra8_keycache.h.
| enum ra8_keycache_evict_t : uint8_t |
Eviction policy selected in ra8_keycache_cfg_t::evict.
Chooses how the engine orders victims. LRU keeps a single recency list; SLRU keeps a probationary + protected pair for scan resistance. Both skip pinned cells and both guarantee residency <= cell_count.
| Enumerator | |
|---|---|
| k_ra8_keycache_evict_lru | Single-list LRU (the default when 0). |
| k_ra8_keycache_evict_slru | Segmented LRU / 2Q (scan-resistant). |
Definition at line 95 of file ra8_keycache.h.
|
nodiscard |
Get (and pin) the cell for key, rendering it on a miss.
On a hit the cell is re-referenced (LRU: moved to the MRU; SLRU: promoted toward the protected segment) and pinned. On a miss an unpinned victim is evicted (LRU: the LRU cell; SLRU: the probationary LRU first, then the protected LRU), the cell is filled through the configured render callback, inserted, and pinned. The returned view stays valid until ra8_keycache_put.
| [in] | kc | Initialised cache. |
| [in] | key | key_bytes-wide key to fetch (fully initialised). |
| [out] | out_view | Receives the pinned cell view. |
| k_ra8_ok | Cell resident and pinned; *out_view set. |
| k_ra8_err_null_ptr | kc, key, or out_view was NULL. |
| k_ra8_err_no_mem | Every cell is pinned (cannot evict for the miss). |
| k_ra8_err_* | The render callback failed (returned verbatim). |
Definition at line 865 of file ra8_keycache.c.
References ra8_keycache_t::cfg, ra8_keycache_t::hits, internal_access(), internal_cell_ptr(), internal_hash_lookup(), internal_miss(), internal_user_ptr(), k_ra8_ok, ra8_keycache_cfg_t::meta, ra8_keycache_t::misses, ra8_keycache_cell_t::pin_count, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by ra8_glyph_atlas_get(), ra8_keycache_prefetch(), ra8_tile_cache_get(), and ra8_vmem_get().
|
nodiscard |
Initialise a cache engine over caller-supplied storage.
| [out] | kc | Cache state to populate (zero-initialised by the caller). |
| [in] | cfg | Storage + policy + renderer configuration (see ra8_keycache_cfg_t). |
| k_ra8_ok | Cache ready; all cells cold. |
| k_ra8_err_null_ptr | kc, cfg, or a required cfg pointer is NULL. |
| k_ra8_err_invalid_size | cell_count, cell_bytes, key_bytes, or bucket_count was zero. |
| k_ra8_err_invalid_arg | cfg->protected_pct exceeds 100 (SLRU). |
Definition at line 778 of file ra8_keycache.c.
References ra8_keycache_cfg_t::evict, internal_protected_cap(), internal_seed_cells(), internal_validate_cfg_policy(), internal_validate_cfg_ptrs(), internal_validate_cfg_sizes(), k_ra8_keycache_evict_slru, k_ra8_ok, ra8_keycache_t::protected_cap, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by ra8_glyph_atlas_init(), ra8_tile_cache_init(), and ra8_vmem_init().
|
nodiscard |
Warm the cell for key into the cache without holding a pin.
The read-ahead / prefetch primitive: a ra8_keycache_get immediately followed by a ra8_keycache_put, so on return the cell is resident but unpinned (evictable). A hit is a no-op refresh; a miss renders the cell through the configured callback and inserts it. Warming changes only residency – never the bytes a later ra8_keycache_get returns – so it is transparent to the caller. This is the image-tile analogue of ra8_vmem_prefetch (which warms a page-cache frame). The cell is inserted at the MRU (single-list LRU), so a wrong read-ahead guess can age out hot data before itself; the scan-resistant probationary insert is tracked by the cache-consolidation work (#345).
| [in,out] | kc | Initialised cache. |
| [in] | key | key_bytes-wide key to warm (fully initialised). |
| k_ra8_ok | The cell is resident and unpinned (warmed or hit). |
| k_ra8_err_null_ptr | kc or key was NULL. |
| k_ra8_err_no_mem | Every cell is pinned (cannot evict to warm). |
| k_ra8_err_* | The render callback failed (returned verbatim). |
Definition at line 883 of file ra8_keycache.c.
References ra8_keycache_view_t::data, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_keycache_get(), ra8_keycache_put(), and s_tag.
Referenced by ra8_tile_cache_prefetch().
|
nodiscard |
Release one pin on a cell previously returned by ra8_keycache_get.
| [in] | kc | Initialised cache. |
| [in] | data | The data pointer from a returned ra8_keycache_view_t. |
| k_ra8_ok | Pin released. |
| k_ra8_err_null_ptr | kc or data was NULL. |
| k_ra8_err_invalid_arg | data is not a cell of this cache, or the cell was not pinned. |
Definition at line 897 of file ra8_keycache.c.
References ra8_keycache_cfg_t::cell_bytes, ra8_keycache_cfg_t::cell_count, ra8_keycache_cfg_t::cell_mem, ra8_keycache_t::cfg, k_ra8_err_invalid_arg, k_ra8_ok, ra8_keycache_cfg_t::meta, ra8_keycache_cell_t::pin_count, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by ra8_glyph_atlas_put(), ra8_keycache_prefetch(), ra8_tile_cache_put(), and ra8_vmem_put().
|
nodiscard |
Report the cache hit / miss / eviction counters.
| [in] | kc | Initialised cache. |
| [out] | out_hits | Hits so far (may be NULL). |
| [out] | out_misses | Misses so far (may be NULL). |
| [out] | out_evictions | Evictions so far (may be NULL). |
| k_ra8_ok | Counters reported. |
| k_ra8_err_null_ptr | kc was NULL. |
| k_ra8_err_invalid_state | The cache was not initialised. |
Definition at line 922 of file ra8_keycache.c.
References ra8_keycache_cfg_t::cell_mem, ra8_keycache_t::cfg, ra8_keycache_t::evictions, ra8_keycache_t::hits, k_ra8_err_invalid_state, k_ra8_ok, ra8_keycache_t::misses, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by ra8_glyph_atlas_stats(), ra8_tile_cache_stats(), and ra8_vmem_stats().