arena: add Fixed which is just Linear that doesn't allocate its backing memory, rename Paging to Paged
This commit is contained in:
parent
5d0a71c5be
commit
9807636359
1 changed files with 28 additions and 24 deletions
|
|
@ -12,22 +12,21 @@ import (
|
||||||
"git.brut.systems/judah/xx/mem"
|
"git.brut.systems/judah/xx/mem"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Linear is a simple bump allocator with a fixed amount of backing memory.
|
// Fixed is a simple bump allocator that uses the given buffer.
|
||||||
func Linear(capacity_in_bytes uintptr) Arena {
|
//
|
||||||
if capacity_in_bytes <= 0 {
|
// Fixed will NOT resize when it runs out of memory.
|
||||||
panic("linear: capacity_in_bytes must be greater than zero")
|
func Fixed(data []byte) Arena {
|
||||||
|
if len(data) == 0 || len(data) != cap(data) {
|
||||||
|
panic("fixed: length & capacity must be equal and greater than zero")
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var offset uintptr
|
||||||
data = make([]byte, capacity_in_bytes)
|
|
||||||
offset uintptr
|
|
||||||
)
|
|
||||||
return func(a Action, size, align uintptr, watermark *uintptr) (unsafe.Pointer, error) {
|
return func(a Action, size, align uintptr, watermark *uintptr) (unsafe.Pointer, error) {
|
||||||
switch a {
|
switch a {
|
||||||
case ACTION_ALLOC:
|
case ACTION_ALLOC:
|
||||||
aligned := mem.AlignForward(size, align)
|
aligned := mem.AlignForward(size, align)
|
||||||
if offset+aligned > capacity_in_bytes {
|
if offset+aligned > uintptr(cap(data)) {
|
||||||
return nil, errors.New("linear: out of memory")
|
return nil, errors.New("fixed: out of memory")
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr := &data[offset]
|
ptr := &data[offset]
|
||||||
|
|
@ -38,25 +37,30 @@ func Linear(capacity_in_bytes uintptr) Arena {
|
||||||
offset = 0
|
offset = 0
|
||||||
case ACTION_SAVE:
|
case ACTION_SAVE:
|
||||||
if watermark == nil {
|
if watermark == nil {
|
||||||
return nil, errors.New("linear: cannot save to nil watermark")
|
return nil, errors.New("fixed: cannot save to nil watermark")
|
||||||
}
|
}
|
||||||
|
|
||||||
*watermark = offset
|
*watermark = offset
|
||||||
case ACTION_RESTORE:
|
case ACTION_RESTORE:
|
||||||
if watermark == nil {
|
if watermark == nil {
|
||||||
return nil, errors.New("linear: cannot restore nil watermark")
|
return nil, errors.New("fixed: cannot restore nil watermark")
|
||||||
}
|
}
|
||||||
|
|
||||||
clear(data[*watermark:offset])
|
clear(data[*watermark:offset])
|
||||||
offset = *watermark
|
offset = *watermark
|
||||||
default:
|
default:
|
||||||
panic("linear: unimplemented action - " + a.String())
|
panic("fixed: unimplemented action - " + a.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Linear is a simple bump allocator with a fixed amount of backing memory.
|
||||||
|
func Linear(capacity_in_bytes uintptr) Arena {
|
||||||
|
return Fixed(make([]byte, capacity_in_bytes))
|
||||||
|
}
|
||||||
|
|
||||||
// Ring is an Arena that only allocates values of the given type.
|
// Ring is an Arena that only allocates values of the given type.
|
||||||
// When capacity is exceeded, previous allocations will be reused to accommodate new ones
|
// When capacity is exceeded, previous allocations will be reused to accommodate new ones
|
||||||
//
|
//
|
||||||
|
|
@ -172,12 +176,12 @@ func Chunked(max_allocs_per_chunk uintptr) Arena {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paging is a linear arena that allocates pages of virtual memory.
|
// Paged is a linear arena that allocates pages of virtual memory.
|
||||||
// The memory allocated is only committed to physical memory as it is used,
|
// The memory allocated is only committed to physical memory as it is used,
|
||||||
// so total_reserved_in_bytes should is the total amount of addressable memory to reserve.
|
// so total_reserved_in_bytes should is the total amount of addressable memory to reserve.
|
||||||
//
|
//
|
||||||
// Note: resetting a Paging arena will cause the currently commited memory to be decommited (i.e. unmapped from physical memory).
|
// Note: resetting a Paged arena will cause the currently commited memory to be decommited (i.e. unmapped from physical memory).
|
||||||
func Paging(page_size, total_reserved_in_bytes uintptr) Arena {
|
func Paged(page_size, total_reserved_in_bytes uintptr) Arena {
|
||||||
var (
|
var (
|
||||||
committed uintptr
|
committed uintptr
|
||||||
offset uintptr
|
offset uintptr
|
||||||
|
|
@ -185,13 +189,13 @@ func Paging(page_size, total_reserved_in_bytes uintptr) Arena {
|
||||||
|
|
||||||
base, err := mem.Reserve(total_reserved_in_bytes)
|
base, err := mem.Reserve(total_reserved_in_bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("paging: failed to reserve address space - %s", err))
|
panic(fmt.Sprintf("paged: failed to reserve address space - %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo(judah): is this needed?
|
// @todo(judah): is this needed?
|
||||||
runtime.AddCleanup(&base, func(_ struct{}) {
|
runtime.AddCleanup(&base, func(_ struct{}) {
|
||||||
if err := mem.Release(base); err != nil {
|
if err := mem.Release(base); err != nil {
|
||||||
panic(fmt.Sprintf("paging: failed to release memory - %s", err))
|
panic(fmt.Sprintf("paged: failed to release memory - %s", err))
|
||||||
}
|
}
|
||||||
}, struct{}{})
|
}, struct{}{})
|
||||||
|
|
||||||
|
|
@ -200,7 +204,7 @@ func Paging(page_size, total_reserved_in_bytes uintptr) Arena {
|
||||||
case ACTION_ALLOC:
|
case ACTION_ALLOC:
|
||||||
aligned := mem.AlignForward(size, align)
|
aligned := mem.AlignForward(size, align)
|
||||||
if offset+aligned > total_reserved_in_bytes {
|
if offset+aligned > total_reserved_in_bytes {
|
||||||
return nil, errors.New("paging: out of addressable memory")
|
return nil, errors.New("paged: out of addressable memory")
|
||||||
}
|
}
|
||||||
|
|
||||||
if offset+aligned > committed {
|
if offset+aligned > committed {
|
||||||
|
|
@ -208,7 +212,7 @@ func Paging(page_size, total_reserved_in_bytes uintptr) Arena {
|
||||||
to_commit := mem.AlignForward(required, page_size)
|
to_commit := mem.AlignForward(required, page_size)
|
||||||
|
|
||||||
if err := mem.Commit(base[committed:to_commit-committed], mem.AccessRead|mem.AccessWrite); err != nil {
|
if err := mem.Commit(base[committed:to_commit-committed], mem.AccessRead|mem.AccessWrite); err != nil {
|
||||||
return nil, fmt.Errorf("paging: failed to commit memory - %w", err)
|
return nil, fmt.Errorf("paged: failed to commit memory - %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
committed = to_commit
|
committed = to_commit
|
||||||
|
|
@ -221,7 +225,7 @@ func Paging(page_size, total_reserved_in_bytes uintptr) Arena {
|
||||||
case ACTION_RESET:
|
case ACTION_RESET:
|
||||||
if committed > 0 {
|
if committed > 0 {
|
||||||
if err := mem.Decommit(base[:mem.AlignForward(committed, page_size)]); err != nil {
|
if err := mem.Decommit(base[:mem.AlignForward(committed, page_size)]); err != nil {
|
||||||
return nil, fmt.Errorf("paging: failed to decommit memory - %w", err)
|
return nil, fmt.Errorf("paged: failed to decommit memory - %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,7 +237,7 @@ func Paging(page_size, total_reserved_in_bytes uintptr) Arena {
|
||||||
|
|
||||||
case ACTION_SAVE:
|
case ACTION_SAVE:
|
||||||
if watermark == nil {
|
if watermark == nil {
|
||||||
return nil, errors.New("paging: cannot save to nil watermark")
|
return nil, errors.New("paged: cannot save to nil watermark")
|
||||||
}
|
}
|
||||||
|
|
||||||
*watermark = offset
|
*watermark = offset
|
||||||
|
|
@ -241,7 +245,7 @@ func Paging(page_size, total_reserved_in_bytes uintptr) Arena {
|
||||||
|
|
||||||
case ACTION_RESTORE:
|
case ACTION_RESTORE:
|
||||||
if watermark == nil {
|
if watermark == nil {
|
||||||
return nil, errors.New("paging: cannot restore nil watermark")
|
return nil, errors.New("paged: cannot restore nil watermark")
|
||||||
}
|
}
|
||||||
|
|
||||||
clear(base[*watermark:offset])
|
clear(base[*watermark:offset])
|
||||||
|
|
@ -250,7 +254,7 @@ func Paging(page_size, total_reserved_in_bytes uintptr) Arena {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("paging: unimplemented action - " + a.String())
|
panic("paged: unimplemented action - " + a.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue