diff options
| author | gingerBill <bill@gingerbill.org> | 2019-12-31 13:54:42 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2019-12-31 13:54:42 +0000 |
| commit | 5a50ab7a999e637708812fe5a67eef93ddb7865c (patch) | |
| tree | b633b02f0347626c29edcf1e7b9747a34ffa1a0b /core/runtime | |
| parent | 4578544007b4f0362518816f2ff36b93b0585bc5 (diff) | |
Add new runtime files.
Diffstat (limited to 'core/runtime')
| -rw-r--r-- | core/runtime/default_allocators.odin | 124 | ||||
| -rw-r--r-- | core/runtime/procs_everything_else.odin | 24 |
2 files changed, 148 insertions, 0 deletions
diff --git a/core/runtime/default_allocators.odin b/core/runtime/default_allocators.odin new file mode 100644 index 000000000..89ac7a147 --- /dev/null +++ b/core/runtime/default_allocators.odin @@ -0,0 +1,124 @@ +package runtime + +import "core:os" + +default_allocator_proc :: os.heap_allocator_proc; + +default_allocator :: proc() -> Allocator { + return os.heap_allocator(); +} + + +Default_Temp_Allocator :: struct { + data: []byte, + curr_offset: int, + prev_offset: int, + backup_allocator: Allocator, + leaked_allocations: [dynamic]rawptr, + default_to_default_allocator: bool, +} + +default_temp_allocator_init :: proc(allocator: ^Default_Temp_Allocator, data: []byte, backup_allocator := context.allocator) { + allocator.data = data; + allocator.curr_offset = 0; + allocator.prev_offset = 0; + allocator.backup_allocator = backup_allocator; +} + +default_temp_allocator_destroy :: proc(using allocator: ^Default_Temp_Allocator) { + if allocator == nil { + return; + } + for ptr in leaked_allocations { + free(ptr, backup_allocator); + } + delete(leaked_allocations); + delete(data, backup_allocator); + allocator^ = {}; +} + +default_temp_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, + size, alignment: int, + old_memory: rawptr, old_size: int, flags: u64 = 0, loc := #caller_location) -> rawptr { + + allocator := (^Default_Temp_Allocator)(allocator_data); + + if allocator.data == nil { + DEFAULT_SCRATCH_BACKING_SIZE :: 1<<22; + a := context.allocator; + if !(context.allocator.procedure != default_temp_allocator_proc && + context.allocator.data != allocator_data) { + a = default_allocator(); + } + default_temp_allocator_init(allocator, make([]byte, 1<<22, a), a); + } + + switch mode { + case .Alloc: + switch { + case allocator.curr_offset+size <= len(allocator.data): + offset := align_forward_uintptr(uintptr(allocator.curr_offset), uintptr(alignment)); + ptr := &allocator.data[offset]; + mem_zero(ptr, size); + allocator.prev_offset = int(offset); + allocator.curr_offset = int(offset) + size; + return ptr; + case size <= len(allocator.data): + offset := align_forward_uintptr(uintptr(0), uintptr(alignment)); + ptr := &allocator.data[offset]; + mem_zero(ptr, size); + allocator.prev_offset = int(offset); + allocator.curr_offset = int(offset) + size; + return ptr; + } + // TODO(bill): Should leaks be notified about? Should probably use a logging system that is built into the context system + a := allocator.backup_allocator; + if a.procedure == nil { + a = context.allocator; + allocator.backup_allocator = a; + } + + ptr := mem_alloc(size, alignment, a, loc); + if allocator.leaked_allocations == nil { + allocator.leaked_allocations = make([dynamic]rawptr, a); + } + append(&allocator.leaked_allocations, ptr); + + return ptr; + + case .Free: + last_ptr := rawptr(&allocator.data[allocator.prev_offset]); + if old_memory == last_ptr { + full_size := allocator.curr_offset - allocator.prev_offset; + allocator.curr_offset = allocator.prev_offset; + mem_zero(last_ptr, full_size); + return nil; + } + // NOTE(bill): It's allocator memory, don't worry about freeing + + case .Free_All: + allocator.curr_offset = 0; + allocator.prev_offset = 0; + for ptr in allocator.leaked_allocations { + free(ptr, allocator.backup_allocator); + } + clear(&allocator.leaked_allocations); + + case .Resize: + last_ptr := rawptr(&allocator.data[allocator.prev_offset]); + if old_memory == last_ptr && len(allocator.data)-allocator.prev_offset >= size { + allocator.curr_offset = allocator.prev_offset+size; + return old_memory; + } + return default_temp_allocator_proc(allocator_data, Allocator_Mode.Alloc, size, alignment, old_memory, old_size, flags, loc); + } + + return nil; +} + +default_temp_allocator :: proc(allocator: ^Default_Temp_Allocator) -> Allocator { + return Allocator{ + procedure = default_temp_allocator_proc, + data = allocator, + }; +} diff --git a/core/runtime/procs_everything_else.odin b/core/runtime/procs_everything_else.odin new file mode 100644 index 000000000..6d982a13e --- /dev/null +++ b/core/runtime/procs_everything_else.odin @@ -0,0 +1,24 @@ +//+build !windows !amd64 +package runtime + +@(link_name="memset") +memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { + b := byte(val); + + p_start := uintptr(ptr); + p_end := p + uintptr(max(len, 0)); + for p := p_start; p < p_end; p += 1 { + (^byte)(p)^ = b; + } + + return ptr; + // when size_of(rawptr) == 8 { + // @(link_name="llvm.memset.p0i8.i64") + // llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---; + // } else { + // @(link_name="llvm.memset.p0i8.i32") + // llvm_memset :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) ---; + // } + + // return llvm_memset(ptr, byte(val), len, 1, false); +} |