@@ -11,11 +11,20 @@ const free_list_count: usize = 6;
1111
1212const Alloc = @This ();
1313
14+ /// The lists of free chunks.
1415free_lists : [free_list_count ]? * Chunk = @splat (null ),
1516
17+ /// The beginning address of the memory region that can be allocated from.
1618low_boundary : usize ,
19+
20+ /// The next address beyond the highest address of the memory region can allocated from.
1721high_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.
1928mutex : 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