Is there one available?
I have been using this in C: malloc0/malloc0.c at main · muayyad-alsadi/malloc0 · GitHub
But i have trouble trying to port it to odin, can anyone help?
Here what i got so far:
@(default_calling_convention = "c")
foreign _ {
update_memory_view::proc() ---
}
import "base:intrinsics"
__heap_tail:uint;
__heap_mark:uint;
__mi:bool
@(default_calling_convention = "c")
foreign _ {
__heap_base: u8
}
_mem_alignment :: 4
_size_t_bytes :: 4
_mem_flag_used :: 0xbf82583a
_mem_flag_free :: 0xab34d705
page_alloc :: proc(page_count: int) -> (data: []byte, err: mem.Allocator_Error) {
prev_page_count := intrinsics.wasm_memory_grow(0, uintptr(page_count))
if !__mi {
__heap_tail = transmute(uint) transmute(^uint) &__heap_base
__heap_mark = transmute(uint) transmute(^uint) &__heap_base
__mi = true
}
n := uint(page_count)
n += (8 - (n % _mem_alignment)) % _mem_alignment
// check if size is enough
total :uint= uint(__heap_tail) + n + 3*_size_t_bytes
size :uint=auto_cast intrinsics.wasm_memory_size(0)<<16
if total > size {
ignore := intrinsics.wasm_memory_grow(0, auto_cast ((total>>16)-(size>>16)+1) )
update_memory_view()
}
r := transmute(uint) __heap_tail
(transmute(^uint)r)^ =n
r+= _size_t_bytes;
(transmute(^uint)r)^ =_mem_flag_used
r+= _size_t_bytes
__heap_tail = r + n
(transmute(^uint)__heap_tail)^ = n
__heap_tail += _size_t_bytes
ret:= transmute([^]u8) r;
return ret[0:page_count], .None
}
page_free::proc(p: rawptr) -> (err: mem.Allocator_Error) {
n: uint
if p == nil {
return .None
}
r := transmute(uint) p
r -= _size_t_bytes
if (transmute(^uint) r)^ != _mem_flag_used {
return .None
}
flag: uint = _mem_flag_free
(transmute(^uint) r)^ = flag
r -= _size_t_bytes
n = (transmute(^uint)r)^
ptr_tail := (transmute(uint)p) + n + _size_t_bytes
if __heap_tail != ptr_tail {
return .None
}
__heap_tail = r
for(r > transmute(uint)&__heap_base) {
r -= _size_t_bytes
n = (transmute(^uint)r)^
r -= n
r -= _size_t_bytes
flag = (transmute(^uint)r)^
if flag != _mem_flag_free {
break
}
r -= _size_t_bytes
n = (transmute(^uint) r)^
__heap_tail = r
}
return .None
}
page_realloc::proc(p: rawptr, old_size, new_size: int) -> (data: []byte, err: mem.Allocator_Error)
{
if p == nil {
return page_alloc(new_size)
}
ret, e :=page_alloc(new_size)
oldBytes :[]byte= ([^]byte)(p)[:old_size]
for it, i in oldBytes {
ret[i] = it
}
ignore := page_free(p)
return ret, e
}
page_allocator :: proc() -> mem.Allocator {
procedure :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int,
location := #caller_location) -> ([]byte, mem.Allocator_Error) {
#partial switch mode {
case .Alloc, .Alloc_Non_Zeroed:
return page_alloc(size)
case .Resize:
return page_realloc(old_memory, old_size, size)
case.Free:
return nil, page_free(old_memory)
case .Query_Features:
set := (^mem.Allocator_Mode_Set)(old_memory)
if set != nil {
set^ = {.Alloc, .Free, .Resize, .Query_Features}
}
}
return nil, nil
}
return {
procedure = procedure,
data = nil,
}
}