ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_slab.c
Go to the documentation of this file.
1
17
18#include "ra8_slab.h"
19
20#include <stddef.h>
21#include <stdint.h>
22#include <string.h>
23
24#include "ra8_attributes.h"
25#include "ra8_check.h"
26#include "ra8_err.h"
27
29static const char* const s_tag = "ra8_slab";
30
52RA8_INTERNAL static uint32_t internal_slab_next(const ra8_slab_t* slab, uint32_t idx)
53{
54 uint32_t next = 0U;
55 (void)memcpy(&next, &slab->base[(size_t)idx * (size_t)slab->cell_bytes], sizeof(next));
56 return next;
57}
58
80RA8_INTERNAL static void internal_slab_set_next(ra8_slab_t* slab, uint32_t idx, uint32_t next)
81{
82 (void)memcpy(&slab->base[(size_t)idx * (size_t)slab->cell_bytes], &next, sizeof(next));
83}
84
85ra8_err_t ra8_slab_init(ra8_slab_t* slab, void* buffer, uint32_t buffer_bytes, uint32_t cell_bytes)
86{
87 RA8_CHECK_NULL_PTR(slab, s_tag, "slab must not be nullptr");
88 RA8_CHECK_NULL_PTR(buffer, s_tag, "buffer must not be nullptr");
89 if (cell_bytes < (uint32_t)k_ra8_slab_min_cell_bytes) {
91 }
92 if ((cell_bytes % (uint32_t)k_ra8_slab_align_bytes) != 0U) {
94 }
95 const uint32_t count = buffer_bytes / cell_bytes;
96 if (count == 0U) {
98 }
99 slab->base = (uint8_t*)buffer;
100 slab->cell_bytes = cell_bytes;
101 slab->cell_count = count;
102 for (uint32_t i = 0U; i < count; ++i) {
103 const uint32_t next = ((i + 1U) < count) ? (i + 1U) : (uint32_t)k_ra8_slab_nil;
104 internal_slab_set_next(slab, i, next);
105 }
106 slab->free_head = 0U;
107 slab->free_count = count;
108 return k_ra8_ok;
109}
110
111ra8_err_t ra8_slab_alloc(ra8_slab_t* slab, void** out_cell)
112{
113 RA8_CHECK_NULL_PTR(slab, s_tag, "slab must not be nullptr");
114 RA8_CHECK_NULL_PTR(out_cell, s_tag, "out_cell must not be nullptr");
115 if (slab->free_head == (uint32_t)k_ra8_slab_nil) {
116 return k_ra8_err_no_mem;
117 }
118 const uint32_t idx = slab->free_head;
119 slab->free_head = internal_slab_next(slab, idx);
120 slab->free_count--;
121 *out_cell = (void*)&slab->base[(size_t)idx * (size_t)slab->cell_bytes];
122 return k_ra8_ok;
123}
124
126{
127 RA8_CHECK_NULL_PTR(slab, s_tag, "slab must not be nullptr");
128 RA8_CHECK_NULL_PTR(cell, s_tag, "cell must not be nullptr");
129 const uintptr_t cell_addr = (uintptr_t)cell;
130 const uintptr_t base_addr = (uintptr_t)slab->base;
131 if (cell_addr < base_addr) {
133 }
134 const uintptr_t off = cell_addr - base_addr;
135 const uintptr_t span = (uintptr_t)slab->cell_count * (uintptr_t)slab->cell_bytes;
136 if (off >= span) {
138 }
139 if ((off % (uintptr_t)slab->cell_bytes) != 0U) {
141 }
142 const uint32_t idx = (uint32_t)(off / (uintptr_t)slab->cell_bytes);
143 internal_slab_set_next(slab, idx, slab->free_head);
144 slab->free_head = idx;
145 slab->free_count++;
146 return k_ra8_ok;
147}
148
149ra8_err_t ra8_slab_stats(const ra8_slab_t* slab, uint32_t* out_free, uint32_t* out_total)
150{
151 RA8_CHECK_NULL_PTR(slab, s_tag, "slab must not be nullptr");
152 if (slab->base == nullptr) {
154 }
155 if (out_free != nullptr) {
156 *out_free = slab->free_count;
157 }
158 if (out_total != nullptr) {
159 *out_total = slab->cell_count;
160 }
161 return k_ra8_ok;
162}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
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
static void internal_slab_set_next(ra8_slab_t *slab, uint32_t idx, uint32_t next)
Write the freelist next-index into cell idx.
Definition ra8_slab.c:80
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
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.
Definition ra8_slab.c:149
static uint32_t internal_slab_next(const ra8_slab_t *slab, uint32_t idx)
Read the freelist next-index stored in free cell idx.
Definition ra8_slab.c:52
Fixed-cell slab allocator – O(1), zero-fragmentation, zero-heap.
@ k_ra8_slab_align_bytes
Required cell-size + buffer alignment.
Definition ra8_slab.h:60
@ k_ra8_slab_nil
Freelist terminator (no next cell).
Definition ra8_slab.h:58
@ k_ra8_slab_min_cell_bytes
Smallest cell (holds one index).
Definition ra8_slab.h:59
Caller-owned state for one fixed-cell pool.
Definition ra8_slab.h:75
uint32_t cell_bytes
Bytes per cell (>= 4, multiple of 4).
Definition ra8_slab.h:77
uint32_t free_head
Index of the first free cell, or k_ra8_slab_nil.
Definition ra8_slab.h:79
uint32_t cell_count
Total cells the buffer was divided into.
Definition ra8_slab.h:78
uint32_t free_count
Cells currently free (observability).
Definition ra8_slab.h:80
uint8_t * base
First byte of the cell array (caller buffer).
Definition ra8_slab.h:76