Skip to content

Commit a9bda42

Browse files
committed
Add optional fallback allocator
1 parent 086d0af commit a9bda42

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

core/src/allocator.zig

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,20 @@ const free_list_count: usize = 6;
1111

1212
const Alloc = @This();
1313

14+
/// The lists of free chunks.
1415
free_lists: [free_list_count]?*Chunk = @splat(null),
1516

17+
/// The beginning address of the memory region that can be allocated from.
1618
low_boundary: usize,
19+
20+
/// The next address beyond the highest address of the memory region can allocated from.
1721
high_boundary: usize,
1822

23+
/// An optional fallback allocator that is used when the allocator runs out of memory.
24+
/// This allows allocation from multiple disjoint memory regions.
25+
fallback: ?*Alloc = null,
26+
27+
/// A mutex used to protect access to the allocator.
1928
mutex: microzig.interrupt.Mutex = .{},
2029

2130
/// Return a []u8 slice that contains the memory located between the
@@ -152,7 +161,7 @@ const vtable: std.mem.Allocator.VTable =
152161
///
153162
/// Returns:
154163
/// - `?[*]u8`: A pointer to the allocated memory, or null if insufficient memory is available
155-
fn do_alloc(ptr: *anyopaque, len: usize, alignment: Alignment, _: usize) ?[*]u8 {
164+
fn do_alloc(ptr: *anyopaque, len: usize, alignment: Alignment, pc: usize) ?[*]u8 {
156165
const self: *Alloc = @ptrCast(@alignCast(ptr));
157166

158167
self.mutex.lock();
@@ -241,6 +250,10 @@ fn do_alloc(ptr: *anyopaque, len: usize, alignment: Alignment, _: usize) ?[*]u8
241250
free_index += 1;
242251
}
243252

253+
if (self.fallback) |f| {
254+
return do_alloc(f, len, alignment, pc);
255+
}
256+
244257
return null;
245258
}
246259

@@ -307,9 +320,19 @@ fn do_resize(ptr: *anyopaque, memory: []u8, _: Alignment, new_len: usize, _: usi
307320
///
308321
/// Parameters:
309322
/// - `memory` : The memory to free
310-
fn do_free(ptr: *anyopaque, memory: []u8, _: Alignment, _: usize) void {
323+
fn do_free(ptr: *anyopaque, memory: []u8, alignment: Alignment, pc: usize) void {
311324
const self: *Alloc = @ptrCast(@alignCast(ptr));
312325

326+
const addr = @intFromPtr(memory.ptr);
327+
if (addr < self.low_boundary or addr >= self.high_boundary) {
328+
if (self.fallback) |f| {
329+
do_free(f, memory, alignment, pc);
330+
return;
331+
}
332+
333+
@panic("free - address is not in range");
334+
}
335+
313336
self.mutex.lock();
314337
defer self.mutex.unlock();
315338

0 commit comments

Comments
 (0)