69typedef enum : uint64_t {
81typedef enum : uint8_t {
105 uint64_t h = ((uint64_t)k.
object_id << 32U) | (uint64_t)k.
page;
199 for (int32_t j = idx->
bucket[ob]; j != -1; prev = j, j = idx->
next[j]) {
200 if (j == (int32_t)frame) {
231 idx->
bucket[b] = (int32_t)frame;
261 if (*filled < cache->capacity) {
262 const uint32_t frame = *filled;
266 uint32_t scanned = 0U;
267 const uint32_t frame = pol->
pick_victim(cache, &scanned);
295 const size_t alignment =
alignof(max_align_t);
296 if (value > (SIZE_MAX - (alignment - 1U))) {
299 return (value + alignment - 1U) & ~(alignment - 1U);
322 if ((result ==
nullptr) || ((left != 0U) && (right > (SIZE_MAX / left)))) {
325 *result = left * right;
329typedef enum : uint32_t {
342 size_t policy_frame_bytes;
350 const size_t parts[] = {
357 for (
size_t i = 0U; i < (
sizeof(parts) /
sizeof(parts[0])); ++i) {
359 if ((aligned == 0U) || (total > (SIZE_MAX - aligned))) {
371 if ((span == 0U) || (*used > workspace->
capacity) || (span > (workspace->
capacity - *used))) {
374 void* result = &workspace->
data[*used];
410 if ((required == 0U) || (workspace->
data ==
nullptr) ||
411 (((uintptr_t)workspace->
data %
alignof(max_align_t)) != 0U) ||
427 idx->
mask = hsize - 1U;
428 if ((*frames ==
nullptr) || (idx->
bucket ==
nullptr) || (idx->
next ==
nullptr) ||
429 (*policy_data ==
nullptr)) {
434 for (uint32_t i = 0U; i < hsize; ++i) {
493 uint32_t filled = 0U;
529 if (out !=
nullptr) {
532 if ((pol ==
nullptr) || (trace ==
nullptr) || (capacity == 0U) || (workspace ==
nullptr) ||
539 void* policy_data =
nullptr;
542 .capacity = capacity,
543 .policy_data =
nullptr,
544 .policy_workspace = policy_data,
545 .policy_workspace_bytes =
547 if (!ready || ((pol->
init !=
nullptr) && (pol->
init(&cache) != 0))) {
553 if (pol->
deinit !=
nullptr) {
int cb_replay(const cache_policy_t *pol, const cb_trace_t *trace, uint32_t capacity, cb_workspace_t *workspace, cb_result_t *out)
Replay an access trace through one policy at a fixed capacity.
cb_hash_shift_t
Murmur3 finalizer bit-shift amounts used in internal_hash.
@ k_hash_shift
Murmur3 64-bit finalizer shift.
static void * internal_workspace_take(cb_workspace_t *workspace, size_t *used, size_t bytes)
static bool internal_size_multiply(size_t left, size_t right, size_t *result)
Multiply byte factors without overflowing size_t.
static void internal_index_remove(cb_index_t *idx, const cb_frame_t *frames, uint32_t frame)
Unlink frame's current key from its bucket chain before eviction.
size_t cb_replay_workspace_required(const cache_policy_t *pol, uint32_t capacity)
Return the exact caller workspace required by one replay.
static uint32_t internal_replay_take_frame(const cache_policy_t *pol, cb_cache_t *cache, cb_index_t *idx, uint32_t *filled, cb_result_t *out)
Pick the frame that receives key: a free frame while the cache fills, else the policy's victim (accou...
static uint32_t internal_pow2_ceil(uint32_t v)
Round v up to a power of two (>= 1).
static uint32_t internal_hash(cb_key_t k)
Mix an (object,page) key into a 32-bit hash for bucket selection.
@ k_cb_max_hash_capacity
Largest safe fourfold hash input.
static bool internal_key_eq(cb_key_t a, cb_key_t b)
Report whether two cache keys name the same (object, page).
static bool internal_replay_open(cb_index_t *idx, cb_frame_t **frames, void **policy_data, const cache_policy_t *pol, uint32_t capacity, cb_workspace_t *workspace)
Carve and initialize one replay's exact caller-owned storage.
static int32_t internal_index_find(const cb_index_t *idx, const cb_frame_t *frames, cb_key_t key)
Find the resident frame currently holding key, or -1.
cb_hash_mul_t
Murmur3 finalizer constants used in internal_hash.
@ k_hash_mix_mul
Murmur3 64-bit finalizer multiplier.
static void internal_replay_close(cb_index_t *idx, cb_frame_t *frames)
End the borrowed workspace bindings made by internal_replay_open.
static size_t internal_align_size(size_t value)
Round a byte count to the next maximum fundamental alignment.
static int internal_replay_stream(const cache_policy_t *pol, const cb_trace_t *trace, cb_cache_t *cache, cb_index_t *index, cb_result_t *out)
Drive one resettable trace through an already-bound cache and index.
static void internal_index_push(cb_index_t *idx, uint32_t frame, cb_key_t key)
Link frame into the bucket chain for key after a fresh insert.
Eviction-policy comparison harness for the #147 memory-hierarchy decision record: the DIP seam every ...
struct cb_trace cb_trace_t
Bounded byte-source and text-sink seams for cache_bench.
@ k_cb_io_ok
Operation completed.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
static uint32_t internal_hash(const ra8_keycache_t *kc, const void *key)
Hash a key blob into a bucket index using the configured policy.
The replacement-policy DIP seam (the eventual firmware Layer-2 seam).
void(* on_access)(cb_cache_t *c, uint32_t frame)
A resident key was just hit at frame (update recency/freq).
void(* on_insert)(cb_cache_t *c, uint32_t frame)
frame was just (re)populated with a freshly-loaded key.
void(* deinit)(cb_cache_t *c)
Release policy state.
size_t state_base_bytes
Fixed policy workspace bytes.
size_t state_frame_bytes
Additional bytes per frame.
uint32_t(* pick_victim)(cb_cache_t *c, uint32_t *scanned)
Choose a live frame to evict.
int(* init)(cb_cache_t *c)
Allocate + init policy state for a cb_cache_t.
The fixed-capacity frame cache a policy manages.
cb_frame_t * frames
capacity frame slots.
One frame slot in the fixed page cache.
cb_key_t key
Resident key, valid only when live is true.
bool live
true: slot holds a resident page.
Exact key->frame lookup over the resident set (chained hash).
uint32_t mask
Bucket-count-minus-one bit mask.
int32_t * bucket
Head frame index per bucket, or -1.
int32_t * next
Per-frame chain link, or -1.
A cache key: one (object, page) the reader's vm_get touches.
uint32_t object_id
Opaque object handle (book / archive / font).
uint32_t page
Page index within the object (offset / page-size).
Per-(policy, trace, size) result row.
uint64_t hits
Resident-set hits.
uint32_t worst_scan
Max frames scanned in any eviction.
uint64_t evictions
pick_victim calls.
uint64_t total_scan
Sum of frames scanned (avg proxy).
uint64_t accesses
Total accesses replayed.
Caller-owned state for one independent trace pass.
Caller-owned replay workspace and exact capacity diagnostics.
uint8_t * data
Aligned writable storage.
size_t required
Exact bytes required by the latest request.
size_t high_water
Largest successfully provisioned request.
size_t capacity
Supplied bytes.
Resettable, allocation-free access streams for cache_bench.
cb_io_status_t cb_trace_cursor_next(cb_trace_cursor_t *cursor, cb_key_t *key, bool *done)
Emit the next key.
cb_io_status_t cb_trace_cursor_finish(const cb_trace_cursor_t *cursor)
Validate a captured pass against its bound count and fingerprint.
cb_io_status_t cb_trace_cursor_open(const cb_trace_t *trace, cb_trace_cursor_t *cursor)
Reset a cursor for an independent pass over a trace.