diff --git a/arena/arenas.go b/arena/arenas.go index e82fca6..de090cc 100644 --- a/arena/arenas.go +++ b/arena/arenas.go @@ -187,17 +187,25 @@ func Paged(page_size, total_reserved_in_bytes uintptr) Arena { offset uintptr ) - base, err := mem.Reserve(total_reserved_in_bytes) + // @note(judah): Because, runtime.AddCleanup requires a Go-allocated + // pointer, we need to keep *something* around so we don't leak. + type cleanupwrapper struct { + data []byte + } + + data, err := mem.Reserve(total_reserved_in_bytes) if err != nil { panic(fmt.Sprintf("paged: failed to reserve address space - %s", err)) } + base := new(cleanupwrapper{data}) + // @todo(judah): is this needed? - runtime.AddCleanup(&base, func(_ struct{}) { - if err := mem.Release(base); err != nil { + runtime.AddCleanup(base, func(memory []byte) { + if err := mem.Release(memory); err != nil { panic(fmt.Sprintf("paged: failed to release memory - %s", err)) } - }, struct{}{}) + }, data) return func(a Action, size, align uintptr, watermark *uintptr) (unsafe.Pointer, error) { switch a { @@ -211,20 +219,20 @@ func Paged(page_size, total_reserved_in_bytes uintptr) Arena { required := offset + aligned to_commit := mem.AlignForward(required, page_size) - if err := mem.Commit(base[committed:to_commit], mem.AccessRead|mem.AccessWrite); err != nil { + if err := mem.Commit(base.data[committed:to_commit], mem.AccessRead|mem.AccessWrite); err != nil { return nil, fmt.Errorf("paged: failed to commit memory - %w", err) } committed = to_commit } - ptr := &base[offset] + ptr := &base.data[offset] offset += aligned return unsafe.Pointer(ptr), nil case ACTION_RESET: if committed > 0 { - if err := mem.Decommit(base[:mem.AlignForward(committed, page_size)]); err != nil { + if err := mem.Decommit(base.data[:mem.AlignForward(committed, page_size)]); err != nil { return nil, fmt.Errorf("paged: failed to decommit memory - %w", err) } } @@ -248,7 +256,7 @@ func Paged(page_size, total_reserved_in_bytes uintptr) Arena { return nil, errors.New("paged: cannot restore nil watermark") } - clear(base[*watermark:offset]) + clear(base.data[*watermark:offset]) offset = *watermark return nil, nil diff --git a/go.mod b/go.mod index 97aca90..45f5282 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module git.brut.systems/judah/xx -go 1.25.0 +go 1.26.0 require github.com/ebitengine/purego v0.9.1