SectrPrototype/code/memory.odin

127 lines
4.2 KiB
Odin

package sectr
import "core:fmt"
import "core:mem"
import "core:mem/virtual"
import "core:runtime"
import "core:os"
Byte :: 1
Kilobyte :: 1024 * Byte
Megabyte :: 1024 * Kilobyte
Gigabyte :: 1024 * Megabyte
Terabyte :: 1024 * Gigabyte
Petabyte :: 1024 * Terabyte
Exabyte :: 1024 * Petabyte
kilobytes :: proc ( kb : $ integer_type ) -> integer_type {
return kb * Kilobyte
}
megabytes :: proc ( mb : $ integer_type ) -> integer_type {
return mb * Megabyte
}
gigabyte :: proc ( gb : $ integer_type ) -> integer_type {
return gb * Gigabyte
}
terabyte :: proc ( tb : $ integer_type ) -> integer_type {
return tb * Terabyte
}
// Initialize a sub-section of our virtual memory as a sub-arena
sub_arena_init :: proc( address : ^ byte, size : int ) -> ( ^ mem.Arena) {
Arena :: mem.Arena
arena_size :: size_of( Arena)
sub_arena := cast( ^ Arena ) address
mem_slice := mem.slice_ptr( mem.ptr_offset( address, arena_size), size )
mem.arena_init( sub_arena, mem_slice )
return sub_arena
}
// Helper to get the the beginning of memory after a slice
memory_after :: proc( slice : []byte ) -> ( ^ byte) {
return mem.ptr_offset( & slice[0], len(slice) )
}
// Since this is a prototype, all memory is always tracked. No arena is is interfaced directly.
TrackedAllocator :: struct {
backing : mem.Arena,
internals : mem.Arena,
tracker : mem.Tracking_Allocator,
}
tracked_allocator :: proc ( self : ^ TrackedAllocator ) -> mem.Allocator {
return mem.tracking_allocator( & self.tracker )
}
tracked_allocator_init :: proc( size, internals_size : int, allocator := context.allocator ) -> TrackedAllocator
{
result : TrackedAllocator
Arena :: mem.Arena
Tracking_Allocator :: mem.Tracking_Allocator
arena_allocator :: mem.arena_allocator
arena_init :: mem.arena_init
slice_ptr :: mem.slice_ptr
arena_size :: size_of( Arena)
backing_size := size + arena_size
internals_size := internals_size + arena_size
raw_size := backing_size + internals_size
raw_mem, raw_mem_code := mem.alloc( raw_size, mem.DEFAULT_ALIGNMENT, allocator )
if ( raw_mem_code != mem.Allocator_Error.None )
{
// TODO(Ed) : Setup a proper logging interface
fmt. printf( "Failed to allocate memory for the TrackingAllocator" )
runtime.debug_trap()
os. exit( -1 )
// TODO(Ed) : Figure out the error code enums..
}
arena_init( & result.backing, slice_ptr( cast( ^ byte) raw_mem, backing_size ) )
arena_init( & result.internals, slice_ptr( memory_after( result.backing.data), internals_size ) )
backing_allocator := arena_allocator( & result.backing )
internals_allocator := arena_allocator( & result.internals )
mem.tracking_allocator_init( & result.tracker, backing_allocator, internals_allocator )
return result
}
tracked_allocator_init_vmem :: proc( vmem : [] byte, internals_size : int ) -> ^ TrackedAllocator
{
Arena :: mem.Arena
Tracking_Allocator :: mem.Tracking_Allocator
arena_allocator :: mem.arena_allocator
arena_init :: mem.arena_init
tracking_alloator_init :: mem.tracking_allocator_init
ptr_offset :: mem.ptr_offset
slice_ptr :: mem.slice_ptr
arena_size :: size_of( Arena)
tracking_allocator_size :: size_of( Tracking_Allocator )
backing_size := len(vmem) - internals_size
raw_size := backing_size + internals_size
if backing_size < 0 || len(vmem) < raw_size
{
// TODO(Ed) : Setup a proper logging interface
fmt. printf( "Provided virtual memory slice is not large enough to hold the TrackedAllocator" )
runtime.debug_trap()
os. exit( -1 )
// TODO(Ed) : Figure out the error code enums..
}
result := cast( ^ TrackedAllocator) & vmem[0]
result_slice := slice_ptr( & vmem[0], tracking_allocator_size )
backing_slice := slice_ptr( memory_after( result_slice ), backing_size )
internals_slice := slice_ptr( memory_after( backing_slice), internals_size )
backing := & result.backing
internals := & result.internals
arena_init( backing, backing_slice )
arena_init( internals, internals_slice )
tracking_alloator_init( & result.tracker, arena_allocator( backing ), arena_allocator( internals ) )
return result
}