mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 07:08:48 +00:00
[mem]: Code formatting
This commit is contained in:
+186
-34
@@ -63,30 +63,58 @@ DEFAULT_PAGE_SIZE ::
|
|||||||
4 * 1024
|
4 * 1024
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (rawptr, Allocator_Error) {
|
alloc :: proc(
|
||||||
|
size: int,
|
||||||
|
alignment: int = DEFAULT_ALIGNMENT,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (rawptr, Allocator_Error) {
|
||||||
data, err := runtime.mem_alloc(size, alignment, allocator, loc)
|
data, err := runtime.mem_alloc(size, alignment, allocator, loc)
|
||||||
return raw_data(data), err
|
return raw_data(data), err
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
alloc_bytes :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
alloc_bytes :: proc(
|
||||||
|
size: int,
|
||||||
|
alignment: int = DEFAULT_ALIGNMENT,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
return runtime.mem_alloc(size, alignment, allocator, loc)
|
return runtime.mem_alloc(size, alignment, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
alloc_bytes_non_zeroed :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
alloc_bytes_non_zeroed :: proc(
|
||||||
|
size: int,
|
||||||
|
alignment: int = DEFAULT_ALIGNMENT,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
return runtime.mem_alloc_non_zeroed(size, alignment, allocator, loc)
|
return runtime.mem_alloc_non_zeroed(size, alignment, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
free :: proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
free :: proc(
|
||||||
|
ptr: rawptr,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> Allocator_Error {
|
||||||
return runtime.mem_free(ptr, allocator, loc)
|
return runtime.mem_free(ptr, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
free_with_size :: proc(ptr: rawptr, byte_count: int, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
free_with_size :: proc(
|
||||||
|
ptr: rawptr,
|
||||||
|
byte_count: int,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> Allocator_Error {
|
||||||
return runtime.mem_free_with_size(ptr, byte_count, allocator, loc)
|
return runtime.mem_free_with_size(ptr, byte_count, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
free_bytes :: proc(bytes: []byte, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
free_bytes :: proc(
|
||||||
|
bytes: []byte,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> Allocator_Error {
|
||||||
return runtime.mem_free_bytes(bytes, allocator, loc)
|
return runtime.mem_free_bytes(bytes, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,13 +123,26 @@ free_all :: proc(allocator := context.allocator, loc := #caller_location) -> All
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (rawptr, Allocator_Error) {
|
resize :: proc(
|
||||||
|
ptr: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
new_size: int,
|
||||||
|
alignment: int = DEFAULT_ALIGNMENT,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (rawptr, Allocator_Error) {
|
||||||
data, err := runtime.mem_resize(ptr, old_size, new_size, alignment, allocator, loc)
|
data, err := runtime.mem_resize(ptr, old_size, new_size, alignment, allocator, loc)
|
||||||
return raw_data(data), err
|
return raw_data(data), err
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
resize_bytes :: proc(old_data: []byte, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
resize_bytes :: proc(
|
||||||
|
old_data: []byte,
|
||||||
|
new_size: int,
|
||||||
|
alignment: int = DEFAULT_ALIGNMENT,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
return runtime.mem_resize(raw_data(old_data), len(old_data), new_size, alignment, allocator, loc)
|
return runtime.mem_resize(raw_data(old_data), len(old_data), new_size, alignment, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +156,11 @@ query_features :: proc(allocator: Allocator, loc := #caller_location) -> (set: A
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
query_info :: proc(pointer: rawptr, allocator: Allocator, loc := #caller_location) -> (props: Allocator_Query_Info) {
|
query_info :: proc(
|
||||||
|
pointer: rawptr,
|
||||||
|
allocator: Allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (props: Allocator_Query_Info) {
|
||||||
props.pointer = pointer
|
props.pointer = pointer
|
||||||
if allocator.procedure != nil {
|
if allocator.procedure != nil {
|
||||||
allocator.procedure(allocator.data, .Query_Info, 0, 0, &props, 0, loc)
|
allocator.procedure(allocator.data, .Query_Info, 0, 0, &props, 0, loc)
|
||||||
@@ -123,25 +168,44 @@ query_info :: proc(pointer: rawptr, allocator: Allocator, loc := #caller_locatio
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete_string :: proc(
|
||||||
|
str: string,
|
||||||
delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> Allocator_Error {
|
||||||
return runtime.delete_string(str, allocator, loc)
|
return runtime.delete_string(str, allocator, loc)
|
||||||
}
|
}
|
||||||
delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
|
||||||
|
delete_cstring :: proc(
|
||||||
|
str: cstring,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> Allocator_Error {
|
||||||
return runtime.delete_cstring(str, allocator, loc)
|
return runtime.delete_cstring(str, allocator, loc)
|
||||||
}
|
}
|
||||||
delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error {
|
|
||||||
|
delete_dynamic_array :: proc(
|
||||||
|
array: $T/[dynamic]$E,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> Allocator_Error {
|
||||||
return runtime.delete_dynamic_array(array, loc)
|
return runtime.delete_dynamic_array(array, loc)
|
||||||
}
|
}
|
||||||
delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
|
||||||
|
delete_slice :: proc(
|
||||||
|
array: $T/[]$E,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> Allocator_Error {
|
||||||
return runtime.delete_slice(array, allocator, loc)
|
return runtime.delete_slice(array, allocator, loc)
|
||||||
}
|
}
|
||||||
delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error {
|
|
||||||
|
delete_map :: proc(
|
||||||
|
m: $T/map[$K]$V,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> Allocator_Error {
|
||||||
return runtime.delete_map(m, loc)
|
return runtime.delete_map(m, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
delete :: proc{
|
delete :: proc{
|
||||||
delete_string,
|
delete_string,
|
||||||
delete_cstring,
|
delete_cstring,
|
||||||
@@ -150,46 +214,102 @@ delete :: proc{
|
|||||||
delete_map,
|
delete_map,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) {
|
new :: proc(
|
||||||
|
$T: typeid,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (^T, Allocator_Error) {
|
||||||
return new_aligned(T, align_of(T), allocator, loc)
|
return new_aligned(T, align_of(T), allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) {
|
new_aligned :: proc(
|
||||||
|
$T: typeid,
|
||||||
|
alignment: int,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (t: ^T, err: Allocator_Error) {
|
||||||
return runtime.new_aligned(T, alignment, allocator, loc)
|
return runtime.new_aligned(T, alignment, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) {
|
new_clone :: proc(
|
||||||
|
data: $T,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (t: ^T, err: Allocator_Error) {
|
||||||
return runtime.new_clone(data, allocator, loc)
|
return runtime.new_clone(data, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (slice: T, err: Allocator_Error) {
|
make_aligned :: proc(
|
||||||
|
$T: typeid/[]$E,
|
||||||
|
#any_int len: int,
|
||||||
|
alignment: int,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (slice: T, err: Allocator_Error) {
|
||||||
return runtime.make_aligned(T, len, alignment, allocator, loc)
|
return runtime.make_aligned(T, len, alignment, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
|
make_slice :: proc(
|
||||||
|
$T: typeid/[]$E,
|
||||||
|
#any_int len: int,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (T, Allocator_Error) {
|
||||||
return runtime.make_slice(T, len, allocator, loc)
|
return runtime.make_slice(T, len, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
|
make_dynamic_array :: proc(
|
||||||
|
$T: typeid/[dynamic]$E,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (T, Allocator_Error) {
|
||||||
return runtime.make_dynamic_array(T, allocator, loc)
|
return runtime.make_dynamic_array(T, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
|
make_dynamic_array_len :: proc(
|
||||||
|
$T: typeid/[dynamic]$E,
|
||||||
|
#any_int len: int,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (T, Allocator_Error) {
|
||||||
return runtime.make_dynamic_array_len_cap(T, len, len, allocator, loc)
|
return runtime.make_dynamic_array_len_cap(T, len, len, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) {
|
make_dynamic_array_len_cap :: proc(
|
||||||
|
$T: typeid/[dynamic]$E,
|
||||||
|
#any_int len: int,
|
||||||
|
#any_int cap: int,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (array: T, err: Allocator_Error) {
|
||||||
return runtime.make_dynamic_array_len_cap(T, len, cap, allocator, loc)
|
return runtime.make_dynamic_array_len_cap(T, len, cap, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = 1<<runtime.MAP_MIN_LOG2_CAPACITY, allocator := context.allocator, loc := #caller_location) -> (m: T, err: Allocator_Error) {
|
make_map :: proc(
|
||||||
|
$T: typeid/map[$K]$E,
|
||||||
|
#any_int cap: int = 1<<runtime.MAP_MIN_LOG2_CAPACITY,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (m: T, err: Allocator_Error) {
|
||||||
return runtime.make_map(T, cap, allocator, loc)
|
return runtime.make_map(T, cap, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) {
|
make_multi_pointer :: proc(
|
||||||
|
$T: typeid/[^]$E,
|
||||||
|
#any_int len: int,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location
|
||||||
|
) -> (mp: T, err: Allocator_Error) {
|
||||||
return runtime.make_multi_pointer(T, len, allocator, loc)
|
return runtime.make_multi_pointer(T, len, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,26 +322,58 @@ make :: proc{
|
|||||||
make_multi_pointer,
|
make_multi_pointer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> (res: rawptr, err: Allocator_Error) {
|
default_resize_align :: proc(
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
new_size: int,
|
||||||
|
alignment: int,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (res: rawptr, err: Allocator_Error) {
|
||||||
data: []byte
|
data: []byte
|
||||||
data, err = default_resize_bytes_align(([^]byte)(old_memory)[:old_size], new_size, alignment, allocator, loc)
|
data, err = default_resize_bytes_align(
|
||||||
|
([^]byte) (old_memory)[:old_size],
|
||||||
|
new_size,
|
||||||
|
alignment,
|
||||||
|
allocator,
|
||||||
|
loc,
|
||||||
|
)
|
||||||
res = raw_data(data)
|
res = raw_data(data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
default_resize_bytes_align_non_zeroed :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
default_resize_bytes_align_non_zeroed :: proc(
|
||||||
|
old_data: []byte,
|
||||||
|
new_size: int,
|
||||||
|
alignment: int,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
return _default_resize_bytes_align(old_data, new_size, alignment, false, allocator, loc)
|
return _default_resize_bytes_align(old_data, new_size, alignment, false, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
default_resize_bytes_align :: proc(
|
||||||
|
old_data: []byte,
|
||||||
|
new_size: int,
|
||||||
|
alignment: int,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
return _default_resize_bytes_align(old_data, new_size, alignment, true, allocator, loc)
|
return _default_resize_bytes_align(old_data, new_size, alignment, true, allocator, loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
_default_resize_bytes_align :: #force_inline proc(old_data: []byte, new_size, alignment: int, should_zero: bool, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
_default_resize_bytes_align :: #force_inline proc(
|
||||||
|
old_data: []byte,
|
||||||
|
new_size: int,
|
||||||
|
alignment: int,
|
||||||
|
should_zero: bool,
|
||||||
|
allocator := context.allocator,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
old_memory := raw_data(old_data)
|
old_memory := raw_data(old_data)
|
||||||
old_size := len(old_data)
|
old_size := len(old_data)
|
||||||
if old_memory == nil {
|
if old_memory == nil {
|
||||||
|
|||||||
+98
-77
@@ -3,9 +3,14 @@ package mem
|
|||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|
||||||
nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
nil_allocator_proc :: proc(
|
||||||
size, alignment: int,
|
allocator_data: rawptr,
|
||||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
mode: Allocator_Mode,
|
||||||
|
size, alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,8 +21,6 @@ nil_allocator :: proc() -> Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom allocators
|
|
||||||
|
|
||||||
Arena :: struct {
|
Arena :: struct {
|
||||||
data: []byte,
|
data: []byte,
|
||||||
offset: int,
|
offset: int,
|
||||||
@@ -30,7 +33,6 @@ Arena_Temp_Memory :: struct {
|
|||||||
prev_offset: int,
|
prev_offset: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
arena_init :: proc(a: ^Arena, data: []byte) {
|
arena_init :: proc(a: ^Arena, data: []byte) {
|
||||||
a.data = data
|
a.data = data
|
||||||
a.offset = 0
|
a.offset = 0
|
||||||
@@ -54,9 +56,15 @@ arena_allocator :: proc(arena: ^Arena) -> Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
arena_allocator_proc :: proc(
|
||||||
size, alignment: int,
|
allocator_data: rawptr,
|
||||||
old_memory: rawptr, old_size: int, location := #caller_location) -> ([]byte, Allocator_Error) {
|
mode: Allocator_Mode,
|
||||||
|
size: int,
|
||||||
|
alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
location := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
arena := cast(^Arena)allocator_data
|
arena := cast(^Arena)allocator_data
|
||||||
|
|
||||||
switch mode {
|
switch mode {
|
||||||
@@ -120,8 +128,6 @@ end_arena_temp_memory :: proc(tmp: Arena_Temp_Memory) {
|
|||||||
tmp.arena.temp_count -= 1
|
tmp.arena.temp_count -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Scratch_Allocator :: struct {
|
Scratch_Allocator :: struct {
|
||||||
data: []byte,
|
data: []byte,
|
||||||
curr_offset: int,
|
curr_offset: int,
|
||||||
@@ -151,9 +157,14 @@ scratch_allocator_destroy :: proc(s: ^Scratch_Allocator) {
|
|||||||
s^ = {}
|
s^ = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
scratch_allocator_proc :: proc(
|
||||||
size, alignment: int,
|
allocator_data: rawptr,
|
||||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
mode: Allocator_Mode,
|
||||||
|
size, alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
|
|
||||||
s := (^Scratch_Allocator)(allocator_data)
|
s := (^Scratch_Allocator)(allocator_data)
|
||||||
|
|
||||||
@@ -299,10 +310,6 @@ scratch_allocator :: proc(allocator: ^Scratch_Allocator) -> Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Stack_Allocation_Header :: struct {
|
Stack_Allocation_Header :: struct {
|
||||||
prev_offset: int,
|
prev_offset: int,
|
||||||
padding: int,
|
padding: int,
|
||||||
@@ -339,34 +346,44 @@ stack_allocator :: proc(stack: ^Stack) -> Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stack_allocator_proc :: proc(
|
||||||
stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
allocator_data: rawptr,
|
||||||
size, alignment: int,
|
mode: Allocator_Mode,
|
||||||
old_memory: rawptr, old_size: int, location := #caller_location) -> ([]byte, Allocator_Error) {
|
size: int,
|
||||||
|
alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
location := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
s := cast(^Stack)allocator_data
|
s := cast(^Stack)allocator_data
|
||||||
|
|
||||||
if s.data == nil {
|
if s.data == nil {
|
||||||
return nil, .Invalid_Argument
|
return nil, .Invalid_Argument
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_alloc :: proc(s: ^Stack, size, alignment: int, zero_memory: bool) -> ([]byte, Allocator_Error) {
|
raw_alloc :: proc(
|
||||||
|
s: ^Stack,
|
||||||
|
size: int,
|
||||||
|
alignment: int,
|
||||||
|
zero_memory: bool,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
curr_addr := uintptr(raw_data(s.data)) + uintptr(s.curr_offset)
|
curr_addr := uintptr(raw_data(s.data)) + uintptr(s.curr_offset)
|
||||||
padding := calc_padding_with_header(curr_addr, uintptr(alignment), size_of(Stack_Allocation_Header))
|
padding := calc_padding_with_header(
|
||||||
|
curr_addr,
|
||||||
|
uintptr(alignment),
|
||||||
|
size_of(Stack_Allocation_Header),
|
||||||
|
)
|
||||||
if s.curr_offset + padding + size > len(s.data) {
|
if s.curr_offset + padding + size > len(s.data) {
|
||||||
return nil, .Out_Of_Memory
|
return nil, .Out_Of_Memory
|
||||||
}
|
}
|
||||||
s.prev_offset = s.curr_offset
|
s.prev_offset = s.curr_offset
|
||||||
s.curr_offset += padding
|
s.curr_offset += padding
|
||||||
|
|
||||||
next_addr := curr_addr + uintptr(padding)
|
next_addr := curr_addr + uintptr(padding)
|
||||||
header := (^Stack_Allocation_Header)(next_addr - size_of(Stack_Allocation_Header))
|
header := (^Stack_Allocation_Header)(next_addr - size_of(Stack_Allocation_Header))
|
||||||
header.padding = padding
|
header.padding = padding
|
||||||
header.prev_offset = s.prev_offset
|
header.prev_offset = s.prev_offset
|
||||||
|
|
||||||
s.curr_offset += size
|
s.curr_offset += size
|
||||||
|
|
||||||
s.peak_used = max(s.peak_used, s.curr_offset)
|
s.peak_used = max(s.peak_used, s.curr_offset)
|
||||||
|
|
||||||
if zero_memory {
|
if zero_memory {
|
||||||
zero(rawptr(next_addr), size)
|
zero(rawptr(next_addr), size)
|
||||||
}
|
}
|
||||||
@@ -467,12 +484,6 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Small_Stack_Allocation_Header :: struct {
|
Small_Stack_Allocation_Header :: struct {
|
||||||
padding: u8,
|
padding: u8,
|
||||||
}
|
}
|
||||||
@@ -505,9 +516,14 @@ small_stack_allocator :: proc(stack: ^Small_Stack) -> Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
small_stack_allocator_proc :: proc(
|
||||||
size, alignment: int,
|
allocator_data: rawptr,
|
||||||
old_memory: rawptr, old_size: int, location := #caller_location) -> ([]byte, Allocator_Error) {
|
mode: Allocator_Mode,
|
||||||
|
size, alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
location := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
s := cast(^Small_Stack)allocator_data
|
s := cast(^Small_Stack)allocator_data
|
||||||
|
|
||||||
if s.data == nil {
|
if s.data == nil {
|
||||||
@@ -612,10 +628,6 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Dynamic_Pool :: struct {
|
Dynamic_Pool :: struct {
|
||||||
block_size: int,
|
block_size: int,
|
||||||
out_band_size: int,
|
out_band_size: int,
|
||||||
@@ -632,15 +644,18 @@ Dynamic_Pool :: struct {
|
|||||||
block_allocator: Allocator,
|
block_allocator: Allocator,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DYNAMIC_POOL_BLOCK_SIZE_DEFAULT :: 65536
|
DYNAMIC_POOL_BLOCK_SIZE_DEFAULT :: 65536
|
||||||
DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT :: 6554
|
DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT :: 6554
|
||||||
|
|
||||||
|
dynamic_pool_allocator_proc :: proc(
|
||||||
|
allocator_data: rawptr,
|
||||||
dynamic_pool_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
mode: Allocator_Mode,
|
||||||
size, alignment: int,
|
size: int,
|
||||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
pool := (^Dynamic_Pool)(allocator_data)
|
pool := (^Dynamic_Pool)(allocator_data)
|
||||||
|
|
||||||
switch mode {
|
switch mode {
|
||||||
@@ -689,19 +704,21 @@ dynamic_pool_allocator :: proc(pool: ^Dynamic_Pool) -> Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic_pool_init :: proc(pool: ^Dynamic_Pool,
|
dynamic_pool_init :: proc(
|
||||||
block_allocator := context.allocator,
|
pool: ^Dynamic_Pool,
|
||||||
array_allocator := context.allocator,
|
block_allocator := context.allocator,
|
||||||
block_size := DYNAMIC_POOL_BLOCK_SIZE_DEFAULT,
|
array_allocator := context.allocator,
|
||||||
out_band_size := DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT,
|
block_size := DYNAMIC_POOL_BLOCK_SIZE_DEFAULT,
|
||||||
alignment := 8) {
|
out_band_size := DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT,
|
||||||
pool.block_size = block_size
|
alignment := 8,
|
||||||
pool.out_band_size = out_band_size
|
) {
|
||||||
pool.alignment = alignment
|
pool.block_size = block_size
|
||||||
|
pool.out_band_size = out_band_size
|
||||||
|
pool.alignment = alignment
|
||||||
pool.block_allocator = block_allocator
|
pool.block_allocator = block_allocator
|
||||||
pool.out_band_allocations.allocator = array_allocator
|
pool.out_band_allocations.allocator = array_allocator
|
||||||
pool. unused_blocks.allocator = array_allocator
|
pool.unused_blocks.allocator = array_allocator
|
||||||
pool. used_blocks.allocator = array_allocator
|
pool.used_blocks.allocator = array_allocator
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic_pool_destroy :: proc(pool: ^Dynamic_Pool) {
|
dynamic_pool_destroy :: proc(pool: ^Dynamic_Pool) {
|
||||||
@@ -709,11 +726,9 @@ dynamic_pool_destroy :: proc(pool: ^Dynamic_Pool) {
|
|||||||
delete(pool.unused_blocks)
|
delete(pool.unused_blocks)
|
||||||
delete(pool.used_blocks)
|
delete(pool.used_blocks)
|
||||||
delete(pool.out_band_allocations)
|
delete(pool.out_band_allocations)
|
||||||
|
|
||||||
zero(pool, size_of(pool^))
|
zero(pool, size_of(pool^))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
dynamic_pool_alloc :: proc(pool: ^Dynamic_Pool, bytes: int) -> (rawptr, Allocator_Error) {
|
dynamic_pool_alloc :: proc(pool: ^Dynamic_Pool, bytes: int) -> (rawptr, Allocator_Error) {
|
||||||
data, err := dynamic_pool_alloc_bytes(pool, bytes)
|
data, err := dynamic_pool_alloc_bytes(pool, bytes)
|
||||||
@@ -736,9 +751,14 @@ dynamic_pool_alloc_bytes :: proc(p: ^Dynamic_Pool, bytes: int) -> ([]byte, Alloc
|
|||||||
new_block = pop(&p.unused_blocks)
|
new_block = pop(&p.unused_blocks)
|
||||||
} else {
|
} else {
|
||||||
data: []byte
|
data: []byte
|
||||||
data, err = p.block_allocator.procedure(p.block_allocator.data, Allocator_Mode.Alloc,
|
data, err = p.block_allocator.procedure(
|
||||||
p.block_size, p.alignment,
|
p.block_allocator.data,
|
||||||
nil, 0)
|
Allocator_Mode.Alloc,
|
||||||
|
p.block_size,
|
||||||
|
p.alignment,
|
||||||
|
nil,
|
||||||
|
0,
|
||||||
|
)
|
||||||
new_block = raw_data(data)
|
new_block = raw_data(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -808,10 +828,14 @@ dynamic_pool_free_all :: proc(p: ^Dynamic_Pool) {
|
|||||||
clear(&p.unused_blocks)
|
clear(&p.unused_blocks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panic_allocator_proc :: proc(
|
||||||
panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
allocator_data: rawptr,
|
||||||
size, alignment: int,
|
mode: Allocator_Mode,
|
||||||
old_memory: rawptr, old_size: int,loc := #caller_location) -> ([]byte, Allocator_Error) {
|
size, alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
|
|
||||||
switch mode {
|
switch mode {
|
||||||
case .Alloc:
|
case .Alloc:
|
||||||
@@ -859,11 +883,6 @@ panic_allocator :: proc() -> Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Buddy_Block :: struct #align(align_of(uint)) {
|
Buddy_Block :: struct #align(align_of(uint)) {
|
||||||
size: uint,
|
size: uint,
|
||||||
is_free: bool,
|
is_free: bool,
|
||||||
@@ -929,7 +948,6 @@ buddy_block_coalescence :: proc(head, tail: ^Buddy_Block) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
buddy_block_find_best :: proc(head, tail: ^Buddy_Block, size: uint) -> ^Buddy_Block {
|
buddy_block_find_best :: proc(head, tail: ^Buddy_Block, size: uint) -> ^Buddy_Block {
|
||||||
assert(size != 0)
|
assert(size != 0)
|
||||||
@@ -998,7 +1016,6 @@ buddy_block_find_best :: proc(head, tail: ^Buddy_Block, size: uint) -> ^Buddy_Bl
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Buddy_Allocator :: struct {
|
Buddy_Allocator :: struct {
|
||||||
head: ^Buddy_Block,
|
head: ^Buddy_Block,
|
||||||
tail: ^Buddy_Block,
|
tail: ^Buddy_Block,
|
||||||
@@ -1089,9 +1106,13 @@ buddy_allocator_free :: proc(b: ^Buddy_Allocator, ptr: rawptr) -> Allocator_Erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
buddy_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
buddy_allocator_proc :: proc(
|
||||||
size, alignment: int,
|
allocator_data: rawptr, mode: Allocator_Mode,
|
||||||
old_memory: rawptr, old_size: int,loc := #caller_location) -> ([]byte, Allocator_Error) {
|
size, alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> ([]byte, Allocator_Error) {
|
||||||
|
|
||||||
b := (^Buddy_Allocator)(allocator_data)
|
b := (^Buddy_Allocator)(allocator_data)
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -14,10 +14,12 @@ Exabyte :: runtime.Exabyte
|
|||||||
set :: proc "contextless" (data: rawptr, value: byte, len: int) -> rawptr {
|
set :: proc "contextless" (data: rawptr, value: byte, len: int) -> rawptr {
|
||||||
return runtime.memset(data, i32(value), len)
|
return runtime.memset(data, i32(value), len)
|
||||||
}
|
}
|
||||||
|
|
||||||
zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
|
zero :: proc "contextless" (data: rawptr, len: int) -> rawptr {
|
||||||
intrinsics.mem_zero(data, len)
|
intrinsics.mem_zero(data, len)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
zero_explicit :: proc "contextless" (data: rawptr, len: int) -> rawptr {
|
zero_explicit :: proc "contextless" (data: rawptr, len: int) -> rawptr {
|
||||||
// This routine tries to avoid the compiler optimizing away the call,
|
// This routine tries to avoid the compiler optimizing away the call,
|
||||||
// so that it is always executed. It is intended to provided
|
// so that it is always executed. It is intended to provided
|
||||||
@@ -27,20 +29,22 @@ zero_explicit :: proc "contextless" (data: rawptr, len: int) -> rawptr {
|
|||||||
intrinsics.atomic_thread_fence(.Seq_Cst) // Prevent reordering
|
intrinsics.atomic_thread_fence(.Seq_Cst) // Prevent reordering
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
zero_item :: proc "contextless" (item: $P/^$T) -> P {
|
zero_item :: proc "contextless" (item: $P/^$T) -> P {
|
||||||
intrinsics.mem_zero(item, size_of(T))
|
intrinsics.mem_zero(item, size_of(T))
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
zero_slice :: proc "contextless" (data: $T/[]$E) -> T {
|
zero_slice :: proc "contextless" (data: $T/[]$E) -> T {
|
||||||
zero(raw_data(data), size_of(E)*len(data))
|
zero(raw_data(data), size_of(E)*len(data))
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
|
copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
|
||||||
intrinsics.mem_copy(dst, src, len)
|
intrinsics.mem_copy(dst, src, len)
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
|
copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
|
||||||
intrinsics.mem_copy_non_overlapping(dst, src, len)
|
intrinsics.mem_copy_non_overlapping(dst, src, len)
|
||||||
return dst
|
return dst
|
||||||
@@ -120,6 +124,7 @@ compare_ptrs :: proc "contextless" (a, b: rawptr, n: int) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ptr_offset :: intrinsics.ptr_offset
|
ptr_offset :: intrinsics.ptr_offset
|
||||||
|
|
||||||
ptr_sub :: intrinsics.ptr_sub
|
ptr_sub :: intrinsics.ptr_sub
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
@@ -211,6 +216,7 @@ align_forward_uintptr :: proc(ptr, align: uintptr) -> uintptr {
|
|||||||
align_forward_int :: proc(ptr, align: int) -> int {
|
align_forward_int :: proc(ptr, align: int) -> int {
|
||||||
return int(align_forward_uintptr(uintptr(ptr), uintptr(align)))
|
return int(align_forward_uintptr(uintptr(ptr), uintptr(align)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
align_forward_uint :: proc(ptr, align: uint) -> uint {
|
align_forward_uint :: proc(ptr, align: uint) -> uint {
|
||||||
return uint(align_forward_uintptr(uintptr(ptr), uintptr(align)))
|
return uint(align_forward_uintptr(uintptr(ptr), uintptr(align)))
|
||||||
@@ -230,6 +236,7 @@ align_backward_uintptr :: proc(ptr, align: uintptr) -> uintptr {
|
|||||||
align_backward_int :: proc(ptr, align: int) -> int {
|
align_backward_int :: proc(ptr, align: int) -> int {
|
||||||
return int(align_backward_uintptr(uintptr(ptr), uintptr(align)))
|
return int(align_backward_uintptr(uintptr(ptr), uintptr(align)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
align_backward_uint :: proc(ptr, align: uint) -> uint {
|
align_backward_uint :: proc(ptr, align: uint) -> uint {
|
||||||
return uint(align_backward_uintptr(uintptr(ptr), uintptr(align)))
|
return uint(align_backward_uintptr(uintptr(ptr), uintptr(align)))
|
||||||
@@ -247,7 +254,6 @@ reinterpret_copy :: proc "contextless" ($T: typeid, ptr: rawptr) -> (value: T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Fixed_Byte_Buffer :: distinct [dynamic]byte
|
Fixed_Byte_Buffer :: distinct [dynamic]byte
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
@@ -264,8 +270,6 @@ make_fixed_byte_buffer :: proc "contextless" (backing: []byte) -> Fixed_Byte_Buf
|
|||||||
return transmute(Fixed_Byte_Buffer)d
|
return transmute(Fixed_Byte_Buffer)d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
align_formula :: proc "contextless" (size, align: int) -> int {
|
align_formula :: proc "contextless" (size, align: int) -> int {
|
||||||
result := size + align-1
|
result := size + align-1
|
||||||
@@ -276,12 +280,10 @@ align_formula :: proc "contextless" (size, align: int) -> int {
|
|||||||
calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, header_size: int) -> int {
|
calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, header_size: int) -> int {
|
||||||
p, a := ptr, align
|
p, a := ptr, align
|
||||||
modulo := p & (a-1)
|
modulo := p & (a-1)
|
||||||
|
|
||||||
padding := uintptr(0)
|
padding := uintptr(0)
|
||||||
if modulo != 0 {
|
if modulo != 0 {
|
||||||
padding = a - modulo
|
padding = a - modulo
|
||||||
}
|
}
|
||||||
|
|
||||||
needed_space := uintptr(header_size)
|
needed_space := uintptr(header_size)
|
||||||
if padding < needed_space {
|
if padding < needed_space {
|
||||||
needed_space -= padding
|
needed_space -= padding
|
||||||
@@ -296,8 +298,6 @@ calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, he
|
|||||||
return int(padding)
|
return int(padding)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@(require_results, deprecated="prefer 'slice.clone'")
|
@(require_results, deprecated="prefer 'slice.clone'")
|
||||||
clone_slice :: proc(slice: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> (new_slice: T) {
|
clone_slice :: proc(slice: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> (new_slice: T) {
|
||||||
new_slice, _ = make(T, len(slice), allocator, loc)
|
new_slice, _ = make(T, len(slice), allocator, loc)
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ mutex_allocator_init :: proc(m: ^Mutex_Allocator, backing_allocator: Allocator)
|
|||||||
m.mutex = {}
|
m.mutex = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
mutex_allocator :: proc(m: ^Mutex_Allocator) -> Allocator {
|
mutex_allocator :: proc(m: ^Mutex_Allocator) -> Allocator {
|
||||||
return Allocator{
|
return Allocator{
|
||||||
@@ -22,11 +21,16 @@ mutex_allocator :: proc(m: ^Mutex_Allocator) -> Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
mutex_allocator_proc :: proc(
|
||||||
size, alignment: int,
|
allocator_data: rawptr,
|
||||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> (result: []byte, err: Allocator_Error) {
|
mode: Allocator_Mode,
|
||||||
|
size: int,
|
||||||
|
alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (result: []byte, err: Allocator_Error) {
|
||||||
m := (^Mutex_Allocator)(allocator_data)
|
m := (^Mutex_Allocator)(allocator_data)
|
||||||
|
|
||||||
sync.mutex_guard(&m.mutex)
|
sync.mutex_guard(&m.mutex)
|
||||||
return m.backing.procedure(m.backing.data, mode, size, alignment, old_memory, old_size, loc)
|
return m.backing.procedure(m.backing.data, mode, size, alignment, old_memory, old_size, loc)
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-11
@@ -3,22 +3,36 @@ package mem
|
|||||||
import "base:builtin"
|
import "base:builtin"
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|
||||||
Raw_Any :: runtime.Raw_Any
|
Raw_Any :: runtime.Raw_Any
|
||||||
Raw_String :: runtime.Raw_String
|
|
||||||
Raw_Cstring :: runtime.Raw_Cstring
|
Raw_String :: runtime.Raw_String
|
||||||
Raw_Slice :: runtime.Raw_Slice
|
|
||||||
|
Raw_Cstring :: runtime.Raw_Cstring
|
||||||
|
|
||||||
|
Raw_Slice :: runtime.Raw_Slice
|
||||||
|
|
||||||
Raw_Dynamic_Array :: runtime.Raw_Dynamic_Array
|
Raw_Dynamic_Array :: runtime.Raw_Dynamic_Array
|
||||||
Raw_Map :: runtime.Raw_Map
|
|
||||||
Raw_Soa_Pointer :: runtime.Raw_Soa_Pointer
|
Raw_Map :: runtime.Raw_Map
|
||||||
|
|
||||||
|
Raw_Soa_Pointer :: runtime.Raw_Soa_Pointer
|
||||||
|
|
||||||
|
Raw_Complex32 :: runtime.Raw_Complex32
|
||||||
|
|
||||||
|
Raw_Complex64 :: runtime.Raw_Complex64
|
||||||
|
|
||||||
|
Raw_Complex128 :: runtime.Raw_Complex128
|
||||||
|
|
||||||
|
Raw_Quaternion64 :: runtime.Raw_Quaternion64
|
||||||
|
|
||||||
Raw_Complex32 :: runtime.Raw_Complex32
|
|
||||||
Raw_Complex64 :: runtime.Raw_Complex64
|
|
||||||
Raw_Complex128 :: runtime.Raw_Complex128
|
|
||||||
Raw_Quaternion64 :: runtime.Raw_Quaternion64
|
|
||||||
Raw_Quaternion128 :: runtime.Raw_Quaternion128
|
Raw_Quaternion128 :: runtime.Raw_Quaternion128
|
||||||
|
|
||||||
Raw_Quaternion256 :: runtime.Raw_Quaternion256
|
Raw_Quaternion256 :: runtime.Raw_Quaternion256
|
||||||
Raw_Quaternion64_Vector_Scalar :: runtime.Raw_Quaternion64_Vector_Scalar
|
|
||||||
|
Raw_Quaternion64_Vector_Scalar :: runtime.Raw_Quaternion64_Vector_Scalar
|
||||||
|
|
||||||
Raw_Quaternion128_Vector_Scalar :: runtime.Raw_Quaternion128_Vector_Scalar
|
Raw_Quaternion128_Vector_Scalar :: runtime.Raw_Quaternion128_Vector_Scalar
|
||||||
|
|
||||||
Raw_Quaternion256_Vector_Scalar :: runtime.Raw_Quaternion256_Vector_Scalar
|
Raw_Quaternion256_Vector_Scalar :: runtime.Raw_Quaternion256_Vector_Scalar
|
||||||
|
|
||||||
make_any :: proc "contextless" (data: rawptr, id: typeid) -> any {
|
make_any :: proc "contextless" (data: rawptr, id: typeid) -> any {
|
||||||
|
|||||||
@@ -1,45 +1,47 @@
|
|||||||
package mem
|
package mem
|
||||||
|
|
||||||
// The Rollback Stack Allocator was designed for the test runner to be fast,
|
/*
|
||||||
// able to grow, and respect the Tracking Allocator's requirement for
|
The Rollback Stack Allocator was designed for the test runner to be fast,
|
||||||
// individual frees. It is not overly concerned with fragmentation, however.
|
able to grow, and respect the Tracking Allocator's requirement for
|
||||||
//
|
individual frees. It is not overly concerned with fragmentation, however.
|
||||||
// It has support for expansion when configured with a block allocator and
|
|
||||||
// limited support for out-of-order frees.
|
|
||||||
//
|
|
||||||
// Allocation has constant-time best and usual case performance.
|
|
||||||
// At worst, it is linear according to the number of memory blocks.
|
|
||||||
//
|
|
||||||
// Allocation follows a first-fit strategy when there are multiple memory
|
|
||||||
// blocks.
|
|
||||||
//
|
|
||||||
// Freeing has constant-time best and usual case performance.
|
|
||||||
// At worst, it is linear according to the number of memory blocks and number
|
|
||||||
// of freed items preceding the last item in a block.
|
|
||||||
//
|
|
||||||
// Resizing has constant-time performance, if it's the last item in a block, or
|
|
||||||
// the new size is smaller. Naturally, this becomes linear-time if there are
|
|
||||||
// multiple blocks to search for the pointer's owning block. Otherwise, the
|
|
||||||
// allocator defaults to a combined alloc & free operation internally.
|
|
||||||
//
|
|
||||||
// Out-of-order freeing is accomplished by collapsing a run of freed items
|
|
||||||
// from the last allocation backwards.
|
|
||||||
//
|
|
||||||
// Each allocation has an overhead of 8 bytes and any extra bytes to satisfy
|
|
||||||
// the requested alignment.
|
|
||||||
|
|
||||||
|
It has support for expansion when configured with a block allocator and
|
||||||
|
limited support for out-of-order frees.
|
||||||
|
|
||||||
|
Allocation has constant-time best and usual case performance.
|
||||||
|
At worst, it is linear according to the number of memory blocks.
|
||||||
|
|
||||||
|
Allocation follows a first-fit strategy when there are multiple memory
|
||||||
|
blocks.
|
||||||
|
|
||||||
|
Freeing has constant-time best and usual case performance.
|
||||||
|
At worst, it is linear according to the number of memory blocks and number
|
||||||
|
of freed items preceding the last item in a block.
|
||||||
|
|
||||||
|
Resizing has constant-time performance, if it's the last item in a block, or
|
||||||
|
the new size is smaller. Naturally, this becomes linear-time if there are
|
||||||
|
multiple blocks to search for the pointer's owning block. Otherwise, the
|
||||||
|
allocator defaults to a combined alloc & free operation internally.
|
||||||
|
|
||||||
|
Out-of-order freeing is accomplished by collapsing a run of freed items
|
||||||
|
from the last allocation backwards.
|
||||||
|
|
||||||
|
Each allocation has an overhead of 8 bytes and any extra bytes to satisfy
|
||||||
|
the requested alignment.
|
||||||
|
*/
|
||||||
import "base:runtime"
|
import "base:runtime"
|
||||||
|
|
||||||
ROLLBACK_STACK_DEFAULT_BLOCK_SIZE :: 4 * Megabyte
|
ROLLBACK_STACK_DEFAULT_BLOCK_SIZE :: 4 * Megabyte
|
||||||
|
|
||||||
// This limitation is due to the size of `prev_ptr`, but it is only for the
|
/*
|
||||||
// head block; any allocation in excess of the allocator's `block_size` is
|
This limitation is due to the size of `prev_ptr`, but it is only for the
|
||||||
// valid, so long as the block allocator can handle it.
|
head block; any allocation in excess of the allocator's `block_size` is
|
||||||
//
|
valid, so long as the block allocator can handle it.
|
||||||
// This is because allocations over the block size are not split up if the item
|
|
||||||
// within is freed; they are immediately returned to the block allocator.
|
|
||||||
ROLLBACK_STACK_MAX_HEAD_BLOCK_SIZE :: 2 * Gigabyte
|
|
||||||
|
|
||||||
|
This is because allocations over the block size are not split up if the item
|
||||||
|
within is freed; they are immediately returned to the block allocator.
|
||||||
|
*/
|
||||||
|
ROLLBACK_STACK_MAX_HEAD_BLOCK_SIZE :: 2 * Gigabyte
|
||||||
|
|
||||||
Rollback_Stack_Header :: bit_field u64 {
|
Rollback_Stack_Header :: bit_field u64 {
|
||||||
prev_offset: uintptr | 32,
|
prev_offset: uintptr | 32,
|
||||||
@@ -60,7 +62,6 @@ Rollback_Stack :: struct {
|
|||||||
block_allocator: Allocator,
|
block_allocator: Allocator,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@(private="file", require_results)
|
@(private="file", require_results)
|
||||||
rb_ptr_in_bounds :: proc(block: ^Rollback_Stack_Block, ptr: rawptr) -> bool {
|
rb_ptr_in_bounds :: proc(block: ^Rollback_Stack_Block, ptr: rawptr) -> bool {
|
||||||
start := raw_data(block.buffer)
|
start := raw_data(block.buffer)
|
||||||
@@ -294,9 +295,13 @@ rollback_stack_allocator :: proc(stack: ^Rollback_Stack) -> Allocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
rollback_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
rollback_stack_allocator_proc :: proc(
|
||||||
size, alignment: int,
|
allocator_data: rawptr,
|
||||||
old_memory: rawptr, old_size: int, location := #caller_location,
|
mode: Allocator_Mode,
|
||||||
|
size, alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
location := #caller_location,
|
||||||
) -> (result: []byte, err: Allocator_Error) {
|
) -> (result: []byte, err: Allocator_Error) {
|
||||||
stack := cast(^Rollback_Stack)allocator_data
|
stack := cast(^Rollback_Stack)allocator_data
|
||||||
|
|
||||||
|
|||||||
@@ -12,22 +12,23 @@ Tracking_Allocator_Entry :: struct {
|
|||||||
err: Allocator_Error,
|
err: Allocator_Error,
|
||||||
location: runtime.Source_Code_Location,
|
location: runtime.Source_Code_Location,
|
||||||
}
|
}
|
||||||
|
|
||||||
Tracking_Allocator_Bad_Free_Entry :: struct {
|
Tracking_Allocator_Bad_Free_Entry :: struct {
|
||||||
memory: rawptr,
|
memory: rawptr,
|
||||||
location: runtime.Source_Code_Location,
|
location: runtime.Source_Code_Location,
|
||||||
}
|
}
|
||||||
Tracking_Allocator :: struct {
|
|
||||||
backing: Allocator,
|
|
||||||
allocation_map: map[rawptr]Tracking_Allocator_Entry,
|
|
||||||
bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry,
|
|
||||||
mutex: sync.Mutex,
|
|
||||||
clear_on_free_all: bool,
|
|
||||||
|
|
||||||
total_memory_allocated: i64,
|
Tracking_Allocator :: struct {
|
||||||
total_allocation_count: i64,
|
backing: Allocator,
|
||||||
total_memory_freed: i64,
|
allocation_map: map[rawptr]Tracking_Allocator_Entry,
|
||||||
total_free_count: i64,
|
bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry,
|
||||||
peak_memory_allocated: i64,
|
mutex: sync.Mutex,
|
||||||
|
clear_on_free_all: bool,
|
||||||
|
total_memory_allocated: i64,
|
||||||
|
total_allocation_count: i64,
|
||||||
|
total_memory_freed: i64,
|
||||||
|
total_free_count: i64,
|
||||||
|
peak_memory_allocated: i64,
|
||||||
current_memory_allocated: i64,
|
current_memory_allocated: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +36,6 @@ tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: Alloc
|
|||||||
t.backing = backing_allocator
|
t.backing = backing_allocator
|
||||||
t.allocation_map.allocator = internals_allocator
|
t.allocation_map.allocator = internals_allocator
|
||||||
t.bad_free_array.allocator = internals_allocator
|
t.bad_free_array.allocator = internals_allocator
|
||||||
|
|
||||||
if .Free_All in query_features(t.backing) {
|
if .Free_All in query_features(t.backing) {
|
||||||
t.clear_on_free_all = true
|
t.clear_on_free_all = true
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,6 @@ tracking_allocator_destroy :: proc(t: ^Tracking_Allocator) {
|
|||||||
delete(t.bad_free_array)
|
delete(t.bad_free_array)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Clear only the current allocation data while keeping the totals intact.
|
// Clear only the current allocation data while keeping the totals intact.
|
||||||
tracking_allocator_clear :: proc(t: ^Tracking_Allocator) {
|
tracking_allocator_clear :: proc(t: ^Tracking_Allocator) {
|
||||||
sync.mutex_lock(&t.mutex)
|
sync.mutex_lock(&t.mutex)
|
||||||
@@ -78,9 +77,14 @@ tracking_allocator :: proc(data: ^Tracking_Allocator) -> Allocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
tracking_allocator_proc :: proc(
|
||||||
size, alignment: int,
|
allocator_data: rawptr,
|
||||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> (result: []byte, err: Allocator_Error) {
|
mode: Allocator_Mode,
|
||||||
|
size, alignment: int,
|
||||||
|
old_memory: rawptr,
|
||||||
|
old_size: int,
|
||||||
|
loc := #caller_location,
|
||||||
|
) -> (result: []byte, err: Allocator_Error) {
|
||||||
track_alloc :: proc(data: ^Tracking_Allocator, entry: ^Tracking_Allocator_Entry) {
|
track_alloc :: proc(data: ^Tracking_Allocator, entry: ^Tracking_Allocator_Entry) {
|
||||||
data.total_memory_allocated += i64(entry.size)
|
data.total_memory_allocated += i64(entry.size)
|
||||||
data.total_allocation_count += 1
|
data.total_allocation_count += 1
|
||||||
|
|||||||
Reference in New Issue
Block a user