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

Caching block device – LRU sector cache + write-through over a backend. More...

#include "ra8_io_blockdev_cache.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_io_blockdev.h"
#include "ra8_io_blockdev_backend.h"
Include dependency graph for ra8_io_blockdev_cache.c:

Go to the source code of this file.

Functions

static uint32_t internal_cache_find (const ra8_io_blockdev_cache_state_t *st, uint32_t lba)
 Find the cache slot holding lba.
static uint32_t internal_cache_pick_victim (const ra8_io_blockdev_cache_state_t *st)
 Pick a slot to (re)use: the first free slot, else least-recently-used.
static ra8_err_t internal_cache_read_block (ra8_io_blockdev_cache_state_t *st, uint32_t lba, uint8_t *dst)
 Read one block through the cache (hit) or fill it (miss).
static ra8_err_t internal_cache_write_block (ra8_io_blockdev_cache_state_t *st, uint32_t lba, const uint8_t *src)
 Write one block through to the backend and update the cache.
static ra8_err_t internal_cache_read (void *ctx, uint32_t lba, uint32_t count, uint8_t *buf)
 Cache vtable: read count blocks at lba into buf.
static ra8_err_t internal_cache_write (void *ctx, uint32_t lba, uint32_t count, const uint8_t *buf)
 Cache vtable: write count blocks from buf at lba.
static ra8_err_t internal_cache_erase (void *ctx, uint32_t lba, uint32_t count)
 Cache vtable: erase through to the backend and drop stale slots.
static ra8_err_t internal_cache_get_caps (const void *ctx, ra8_io_blockdev_caps_t *out)
 Cache vtable: report the wrapped backend's capabilities.
static ra8_err_t internal_cache_sync (void *ctx)
 Cache vtable: flush the wrapped backend.
static void internal_cache_state_init (ra8_io_blockdev_cache_state_t *state, const ra8_io_blockdev_t *under, uint8_t *data, ra8_io_blockdev_cache_slot_t *slots, uint32_t n_slots)
 Populate the scalar fields of a fresh cache state.
static void internal_cache_reset_slots (ra8_io_blockdev_cache_slot_t *slots, uint32_t n_slots)
 Reset a slot array to the empty (no sectors cached) state.
ra8_err_t ra8_io_blockdev_cache_init (ra8_io_blockdev_t *bd, ra8_io_blockdev_cache_state_t *state, const ra8_io_blockdev_t *under, uint8_t *data, ra8_io_blockdev_cache_slot_t *slots, uint32_t n_slots)
 Bind a caching block device over an existing backend.
ra8_err_t ra8_io_blockdev_cache_stats (const ra8_io_blockdev_cache_state_t *state, uint32_t *out_hits, uint32_t *out_misses)
 Report the cache hit/miss counters.

Variables

static const char *const s_tag = "ra8_io_blockdev_cache"
 Module log tag.
static const ra8_io_blockdev_iface_t s_cache_iface
 Caching block-device vtable.

Detailed Description

Caching block device – LRU sector cache + write-through over a backend.

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

Reads check a caller-owned sector cache and fill it on a miss (evicting the least-recently-used slot); writes go straight through to the wrapped backend and update the cache. Capabilities and sync delegate to the backend. Every predicate is a single condition, so no MC/DC vectors are due.

Definition in file ra8_io_blockdev_cache.c.

Function Documentation

◆ internal_cache_erase()

ra8_err_t internal_cache_erase ( void * ctx,
uint32_t lba,
uint32_t count )
static

Cache vtable: erase through to the backend and drop stale slots.

Delegates the erase, then invalidates any cached slot whose block lies in the erased range (three single-condition guards).

Parameters
[in]ctxCache state (as a void cookie).
[in]lbaFirst logical block address.
[in]countNumber of blocks to erase.
Returns
ra8_err_t Error code.
Return values
k_ra8_okRange erased and stale slots dropped.
k_ra8_err_null_ptrctx was NULL.
k_ra8_err_*Propagated from the backend erase.
Precondition
ctx is a populated cache state.
The range fits the backend capacity.
Postcondition
On success no cached slot covers the erased range.
On a backend error the cache is left unchanged.
Note
Not thread-safe with respect to the cache.
Since
0.1.0

Definition at line 299 of file ra8_io_blockdev_cache.c.

References k_ra8_ok, ra8_io_blockdev_cache_slot_t::lba, ra8_io_blockdev_cache_state_t::n_slots, RA8_CHECK_NULL_PTR, RA8_INTERNAL, ra8_io_blockdev_erase(), RA8_RETURN_ON_ERROR, s_tag, ra8_io_blockdev_cache_state_t::slots, ra8_io_blockdev_cache_state_t::under, and ra8_io_blockdev_cache_slot_t::valid.

◆ internal_cache_find()

uint32_t internal_cache_find ( const ra8_io_blockdev_cache_state_t * st,
uint32_t lba )
static

Find the cache slot holding lba.

Linear scan over valid slots; two single-condition checks avoid a compound decision.

Parameters
[in]stCache state.
[in]lbaLogical block address to look up.
Returns
uint32_t Slot index, or st->n_slots when not cached.
Return values
st->n_slotsThe block is not in the cache.
Precondition
st is a populated cache state.
st->slots holds st->n_slots entries.
Postcondition
No state is mutated.
The return is st->n_slots iff lba is uncached.
Note
Not thread-safe with respect to the cache.
Since
0.1.0

Definition at line 55 of file ra8_io_blockdev_cache.c.

References ra8_io_blockdev_cache_slot_t::lba, ra8_io_blockdev_cache_state_t::n_slots, RA8_INTERNAL, ra8_io_blockdev_cache_state_t::slots, and ra8_io_blockdev_cache_slot_t::valid.

Referenced by internal_cache_read_block(), and internal_cache_write_block().

◆ internal_cache_get_caps()

ra8_err_t internal_cache_get_caps ( const void * ctx,
ra8_io_blockdev_caps_t * out )
static

Cache vtable: report the wrapped backend's capabilities.

The cache does not change the medium's geometry, so it forwards.

Parameters
[in]ctxCache state (as a const void cookie).
[out]outCapabilities snapshot.
Returns
ra8_err_t Error code.
Return values
k_ra8_ok*out populated from the backend.
k_ra8_err_null_ptrctx or out was NULL.
k_ra8_err_*Propagated from the backend.
Precondition
ctx is a populated cache state.
out is writable.
Postcondition
On success *out mirrors the wrapped backend.
No cache state is mutated.
Note
Thread-safe (pure read of the backend).
Since
0.1.0

Definition at line 343 of file ra8_io_blockdev_cache.c.

References RA8_CHECK_NULL_PTR, RA8_INTERNAL, ra8_io_blockdev_get_caps(), s_tag, and ra8_io_blockdev_cache_state_t::under.

◆ internal_cache_pick_victim()

uint32_t internal_cache_pick_victim ( const ra8_io_blockdev_cache_state_t * st)
static

Pick a slot to (re)use: the first free slot, else least-recently-used.

A free slot wins immediately; otherwise the slot with the smallest last_use stamp is evicted.

Parameters
[in]stCache state.
Returns
uint32_t Index of the slot to use.
Return values
<st->n_slotsAlways a valid slot index.
Precondition
st has at least one slot.
st->slots holds st->n_slots entries.
Postcondition
No state is mutated.
The returned slot is a free slot or the LRU victim.
Note
Not thread-safe with respect to the cache.
Since
0.1.0

Definition at line 90 of file ra8_io_blockdev_cache.c.

References ra8_io_blockdev_cache_slot_t::last_use, ra8_io_blockdev_cache_state_t::n_slots, RA8_INTERNAL, ra8_io_blockdev_cache_state_t::slots, and ra8_io_blockdev_cache_slot_t::valid.

Referenced by internal_cache_read_block(), and internal_cache_write_block().

◆ internal_cache_read()

ra8_err_t internal_cache_read ( void * ctx,
uint32_t lba,
uint32_t count,
uint8_t * buf )
static

Cache vtable: read count blocks at lba into buf.

Iterates the range one block at a time through internal_cache_read_block.

Parameters
[in]ctxCache state (as a void cookie).
[in]lbaFirst logical block address.
[in]countNumber of blocks to read.
[out]bufDestination buffer.
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlocks read.
k_ra8_err_null_ptrctx or buf was NULL.
k_ra8_err_*Propagated from the backend read.
Precondition
ctx is a populated cache state.
buf is writable for count * 512 bytes.
Postcondition
On success buf holds the requested blocks.
The cache reflects every block touched.
Note
Not thread-safe with respect to the cache.
Since
0.1.0

Definition at line 220 of file ra8_io_blockdev_cache.c.

References internal_cache_read_block(), k_ra8_io_block_size_bytes, k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, and s_tag.

◆ internal_cache_read_block()

ra8_err_t internal_cache_read_block ( ra8_io_blockdev_cache_state_t * st,
uint32_t lba,
uint8_t * dst )
static

Read one block through the cache (hit) or fill it (miss).

On a hit, copies from the cache and bumps the LRU stamp; on a miss, reads one block from the backend into the victim slot, records it, and copies it out. Updates the hit/miss counters.

Parameters
[in]stCache state.
[in]lbaLogical block address.
[out]dstDestination of one 512-byte block.
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlock delivered into dst.
k_ra8_err_*Propagated from the backend read.
Precondition
st is a populated cache state.
dst is writable for one block.
Postcondition
On success dst holds the block and the cache reflects it.
Exactly one of hits/misses is incremented.
Note
Not thread-safe with respect to the cache.
Since
0.1.0

Definition at line 130 of file ra8_io_blockdev_cache.c.

References ra8_io_blockdev_cache_state_t::clock, ra8_io_blockdev_cache_state_t::data, ra8_io_blockdev_cache_state_t::hits, internal_cache_find(), internal_cache_pick_victim(), k_ra8_io_block_size_bytes, k_ra8_ok, ra8_io_blockdev_cache_slot_t::last_use, ra8_io_blockdev_cache_slot_t::lba, memcpy(), ra8_io_blockdev_cache_state_t::misses, ra8_io_blockdev_cache_state_t::n_slots, ra8_io_blockdev_read(), RA8_RETURN_ON_ERROR, s_tag, ra8_io_blockdev_cache_state_t::slots, ra8_io_blockdev_cache_state_t::under, and ra8_io_blockdev_cache_slot_t::valid.

Referenced by internal_cache_read().

◆ internal_cache_reset_slots()

void internal_cache_reset_slots ( ra8_io_blockdev_cache_slot_t * slots,
uint32_t n_slots )
static

Reset a slot array to the empty (no sectors cached) state.

Marks every slot invalid and clears its LBA and LRU stamp so the first access fills a free slot rather than evicting stale data.

Parameters
[out]slotsCache metadata array of n_slots entries.
[in]n_slotsNumber of slots to reset (>= 1).
Returns
void
Precondition
slots is non-NULL and holds n_slots entries.
n_slots is non-zero.
Postcondition
Every slot in [0, n_slots) is invalid.
Every slot's lba and last_use are zero.
Note
Not thread-safe with respect to the cache.
Since
0.1.0

Definition at line 451 of file ra8_io_blockdev_cache.c.

References ra8_io_blockdev_cache_slot_t::last_use, ra8_io_blockdev_cache_slot_t::lba, RA8_INTERNAL, and ra8_io_blockdev_cache_slot_t::valid.

Referenced by ra8_io_blockdev_cache_init().

◆ internal_cache_state_init()

void internal_cache_state_init ( ra8_io_blockdev_cache_state_t * state,
const ra8_io_blockdev_t * under,
uint8_t * data,
ra8_io_blockdev_cache_slot_t * slots,
uint32_t n_slots )
static

Populate the scalar fields of a fresh cache state.

Records the caller-owned backend, data buffer, and slot array on state and zeroes the monotonic clock and the hit/miss counters. The slot array itself is reset separately by internal_cache_reset_slots.

Parameters
[out]stateCache state to populate (already null-checked).
[in]underWrapped backend (must out-live the cache).
[in]dataCache data buffer of n_slots * 512 bytes.
[in]slotsCache metadata array of n_slots entries.
[in]n_slotsNumber of cached sectors (>= 1).
Returns
void
Precondition
state is non-NULL and writable.
n_slots is non-zero.
Postcondition
state references under, data, and slots.
state->clock, state->hits, and state->misses are zero.
Note
Not thread-safe with respect to the cache.
Since
0.1.0

Definition at line 415 of file ra8_io_blockdev_cache.c.

References ra8_io_blockdev_cache_state_t::clock, ra8_io_blockdev_cache_state_t::data, ra8_io_blockdev_cache_state_t::hits, ra8_io_blockdev_cache_state_t::misses, ra8_io_blockdev_cache_state_t::n_slots, RA8_INTERNAL, ra8_io_blockdev_cache_state_t::slots, and ra8_io_blockdev_cache_state_t::under.

Referenced by ra8_io_blockdev_cache_init().

◆ internal_cache_sync()

ra8_err_t internal_cache_sync ( void * ctx)
static

Cache vtable: flush the wrapped backend.

Writes are write-through so nothing is buffered here; the call forwards so a backend with its own buffering can commit.

Parameters
[in]ctxCache state (as a void cookie).
Returns
ra8_err_t Error code.
Return values
k_ra8_okBackend flushed.
k_ra8_err_null_ptrctx was NULL.
k_ra8_err_*Propagated from the backend sync.
Precondition
ctx is a populated cache state.
The cache is idle.
Postcondition
On success the backend reflects every prior write.
No cache state is mutated.
Note
Not thread-safe with respect to the cache.
Since
0.1.0

Definition at line 374 of file ra8_io_blockdev_cache.c.

References RA8_CHECK_NULL_PTR, RA8_INTERNAL, ra8_io_blockdev_sync(), s_tag, and ra8_io_blockdev_cache_state_t::under.

◆ internal_cache_write()

ra8_err_t internal_cache_write ( void * ctx,
uint32_t lba,
uint32_t count,
const uint8_t * buf )
static

Cache vtable: write count blocks from buf at lba.

Iterates the range one block at a time through internal_cache_write_block.

Parameters
[in]ctxCache state (as a void cookie).
[in]lbaFirst logical block address.
[in]countNumber of blocks to write.
[in]bufSource buffer.
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlocks written through.
k_ra8_err_null_ptrctx or buf was NULL.
k_ra8_err_*Propagated from the backend write.
Precondition
ctx is a populated cache state.
buf is readable for count * 512 bytes.
Postcondition
On success the backend holds the blocks and the cache reflects them.
On a backend error earlier blocks may already be committed.
Note
Not thread-safe with respect to the cache.
Since
0.1.0

Definition at line 260 of file ra8_io_blockdev_cache.c.

References internal_cache_write_block(), k_ra8_io_block_size_bytes, k_ra8_ok, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, and s_tag.

◆ internal_cache_write_block()

ra8_err_t internal_cache_write_block ( ra8_io_blockdev_cache_state_t * st,
uint32_t lba,
const uint8_t * src )
static

Write one block through to the backend and update the cache.

Write-through: the backend is written first, then the cache slot for the block is inserted or refreshed so a following read hits.

Parameters
[in]stCache state.
[in]lbaLogical block address.
[in]srcSource of one 512-byte block.
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlock committed and cached.
k_ra8_err_*Propagated from the backend write.
Precondition
st is a populated cache state.
src is readable for one block.
Postcondition
On success the backend and the cache both hold the block.
On a backend error the cache is left unchanged for this block.
Note
Not thread-safe with respect to the cache.
Since
0.1.0

Definition at line 178 of file ra8_io_blockdev_cache.c.

References ra8_io_blockdev_cache_state_t::clock, ra8_io_blockdev_cache_state_t::data, internal_cache_find(), internal_cache_pick_victim(), k_ra8_io_block_size_bytes, k_ra8_ok, ra8_io_blockdev_cache_slot_t::last_use, ra8_io_blockdev_cache_slot_t::lba, memcpy(), ra8_io_blockdev_cache_state_t::n_slots, ra8_io_blockdev_write(), RA8_RETURN_ON_ERROR, s_tag, ra8_io_blockdev_cache_state_t::slots, ra8_io_blockdev_cache_state_t::under, and ra8_io_blockdev_cache_slot_t::valid.

Referenced by internal_cache_write().

◆ ra8_io_blockdev_cache_init()

ra8_err_t ra8_io_blockdev_cache_init ( ra8_io_blockdev_t * bd,
ra8_io_blockdev_cache_state_t * state,
const ra8_io_blockdev_t * under,
uint8_t * data,
ra8_io_blockdev_cache_slot_t * slots,
uint32_t n_slots )
nodiscard

Bind a caching block device over an existing backend.

Parameters
[out]bdHandle to bind (zero-initialised by the caller).
[out]stateCaller-owned cache state to populate.
[in]underBackend to wrap (must out-live the cache).
[in]dataCache data buffer of n_slots * 512 bytes.
[in]slotsCache metadata array of n_slots entries.
[in]n_slotsNumber of cached sectors (>= 1).
Returns
ra8_err_t Error code.
Return values
k_ra8_okCache bound; bd is usable.
k_ra8_err_null_ptrbd, state, under, data, or slots NULL.
k_ra8_err_invalid_sizen_slots was zero.
Precondition
data covers n_slots * 512 bytes and slots holds n_slots entries.
under, bd, state, data, slots out-live every cached access.
Postcondition
On success bd reads/writes through an LRU cache over under.
On any non-ok return bd and state are left unbound/untouched.
Note
Not thread-safe with respect to the same cache.
Since
0.1.0

Definition at line 461 of file ra8_io_blockdev_cache.c.

References ra8_io_blockdev_t::ctx, ra8_io_blockdev_t::iface, internal_cache_reset_slots(), internal_cache_state_init(), k_ra8_err_invalid_size, k_ra8_ok, RA8_CHECK_NULL_PTR, s_cache_iface, and s_tag.

Referenced by internal_demo_mount().

◆ ra8_io_blockdev_cache_stats()

ra8_err_t ra8_io_blockdev_cache_stats ( const ra8_io_blockdev_cache_state_t * state,
uint32_t * out_hits,
uint32_t * out_misses )
nodiscard

Report the cache hit/miss counters.

Parameters
[in]stateBound cache state.
[out]out_hitsRead hits so far (may be NULL).
[out]out_missesRead misses so far (may be NULL).
Returns
ra8_err_t Error code.
Return values
k_ra8_okCounters reported.
k_ra8_err_null_ptrstate was NULL.
Precondition
state was populated by ra8_io_blockdev_cache_init.
At least one of the output pointers is non-NULL to be useful.
Postcondition
On success the requested counters are written.
No state is mutated.
Note
Thread-safe (pure read).
Since
0.1.0

Definition at line 483 of file ra8_io_blockdev_cache.c.

References ra8_io_blockdev_cache_state_t::hits, k_ra8_ok, ra8_io_blockdev_cache_state_t::misses, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by internal_demo_run().

Variable Documentation

◆ s_cache_iface

const ra8_io_blockdev_iface_t s_cache_iface
static
Initial value:
= {
}
static ra8_err_t internal_cache_sync(void *ctx)
Cache vtable: flush the wrapped backend.
static ra8_err_t internal_cache_get_caps(const void *ctx, ra8_io_blockdev_caps_t *out)
Cache vtable: report the wrapped backend's capabilities.
static ra8_err_t internal_cache_erase(void *ctx, uint32_t lba, uint32_t count)
Cache vtable: erase through to the backend and drop stale slots.
static ra8_err_t internal_cache_read(void *ctx, uint32_t lba, uint32_t count, uint8_t *buf)
Cache vtable: read count blocks at lba into buf.
static ra8_err_t internal_cache_write(void *ctx, uint32_t lba, uint32_t count, const uint8_t *buf)
Cache vtable: write count blocks from buf at lba.

Caching block-device vtable.

Definition at line 382 of file ra8_io_blockdev_cache.c.

Referenced by ra8_io_blockdev_cache_init().

◆ s_tag

const char* const s_tag = "ra8_io_blockdev_cache"
static

Module log tag.

Definition at line 31 of file ra8_io_blockdev_cache.c.